How to parse structure with bit fields in C?

Guys, there is a structure:
void* p = 02b05e1fa6c10000e997f00002e997f01209040919e5030904093be506090409cde52404e998f0180a046974610009040919e5030904093be506090409cde52404e992f0180a04756e640009040919e5030904093be506090409cde52416a00e13;


97 bytes.

Described the first part of the header structure with bit fields:
typedef struct Bits_
{
 unsigned tableID : 8;
 SectionSyntaxIndicator unsigned : 1; 
 unsigned Reserved1 : 1;
 unsigned Reserved2 : 2; 
 unsigned SectionLength : 12; 
 unsigned ProgramNumber : 16;
 unsigned Reserved3 : 2; 
 unsigned VersionNumber : 5;
 CurrentNextIndicator unsigned : 1; 
 unsigned SectionNumber : 8;
 LastSectionNumber unsigned : 8;
 unsigned Reserved4 : 3; 
 unsigned PCRPid : 13; 
 unsigned Reserved5 : 4; 
 unsigned ProgramInfoLength : 12; 
} Bits;


Trying to access the bits I need:
Bits *pmtFields = reinterpret_cast<bits*>(data);
printf("tableID=%.2X\n", pmtFields->tableID);
 printf("SectionSyntaxIndicator=%.2X\n", pmtFields->SectionSyntaxIndicator);
 printf("Reserved1=%.2X\n", pmtFields->Reserved1);
 printf("Reserved2=%.2X\n", pmtFields->Reserved2);
 printf("SectionLength=%.2X\n", pmtFields->SectionLength);
 printf("ProgramNumber=%.2X\n", pmtFields->ProgramNumber);
 printf("VersionNumber=%.2X\n", pmtFields->VersionNumber);
 printf("CurrentNextIndicator=%.2X\n", pmtFields->CurrentNextIndicator);
 printf("SectionNumber=%.2X\n", pmtFields->SectionNumber);
 printf("LastSectionNumber=%.2X\n", pmtFields->LastSectionNumber);
 printf("Reserved4=%.2X\n", pmtFields->Reserved4);
 printf("PCRPid=%.2X\n", pmtFields->PCRPid);
 printf("Reserved5=%.2X\n", pmtFields->Reserved5);
 printf("ProgramInfoLength=%.2X\n", pmtFields->ProgramInfoLength);</bits*>


Conclusion:

tableID=02 - right!
SectionSyntaxIndicator=00, Should be 1
Reserved1=00 -Should be 0
Reserved2=00-No Matter
SectionLength=5EB -should be 5E
ProgramNumber=C1A6 Should be 1FA6
VersionNumber=00 and so on....
CurrentNextIndicator=00
SectionNumber=00
LastSectionNumber=E9
Reserved4=07
PCRPid=1E12
Reserved5=00
ProgramInfoLength=902
SectionSyntaxIndicator=00
Reserved1=00
Reserved2=00
SectionLength=F5E


Cats, tell me, what's wrong? :)

p.s. here is a link to the full description of the structure:
www.etherguidesystems.com/help/sdos/mpeg/syntax/ta...
September 18th 19 at 23:59
4 answers
September 19th 19 at 00:01
Solution
So. For a start...
void* p = 02b05e1...

SectionSyntaxIndicator=00, Should be 1


The first 8 bits go to the "unsigned tableID", all the rules. And then in the description is single-bit "unsigned SectionSyntaxIndicator".

The value of the second byte == 0xB0, his first bit == 0 and the result is all normal.
The first 4 bits 0xB0 set to 0, so all of the following ("SectionSyntaxIndicator", "Reserved1", "Reserved2") fields will be 0 because this is the first four bits of the same byte.

The field "SectionLength" is a 12-bit, therefore it captures the second 4 bits of 0xB0 and the entire byte is 0x5E. So all the correct that you wrote 0x5EB.

Now. About bit fields in structures.
habrahabr.ru/post/142662

After this link I don't even know what else to write.
Overall, the program here is in no way to blame, just that apparently you've forgotten what the hex representation of the bytes is written first senior Quartet bit, and then lower. In the spring it is. :)
Thanks for the info!
But still decided to "parse" hands. - freeda_Reil commented on September 19th 19 at 00:04
September 19th 19 at 00:03
right that the compiler will deal with the alignment and all your mistakes here. But otherwise he is wrong.
Very right that bit fields are only perverts use! - freeda_Reil commented on September 19th 19 at 00:06
I ask: how many cases have equipment? - Maxwell_Rosenbau commented on September 19th 19 at 00:09
: no, a little bit. Oh PICS on the perverted with bit fields, but now even on STM8 only flags. Let bit, but explicitly specify, rather than to rely on that the compiler will do the right thing (especially to sdcc, unlike gcc, do you trust enough). - gia commented on September 19th 19 at 00:12
Well handles, handles refreshing the structure, well, or alignment_of and aligned_union in C++11 - Maxwell_Rosenbau commented on September 19th 19 at 00:15
September 19th 19 at 00:05
This is not necessary to do. Soon architecture will vary, as it will turn out God knows what!
A bit field is a terrible legacy 8-bit microcontrollers! Only where they belong!!!
And if you want perversion, then at least use the standard types (instead of unsigned need to write a uint16_t or uint32_t, depending on what is meant by this) and be sure to pack the structure, because, by default, gcc will place its members with the best alignment. The compiler is not aware of what you need in a row..
Isn't pragma pack on a bit field is affected? - freeda_Reil commented on September 19th 19 at 00:08
Yes, ?int*_t use, thank you )

Packing comes out. So, in General, is too platform-specific way... Be "hands" ( - Maxwell_Rosenbau commented on September 19th 19 at 00:11
: Once to write a procedure for parsing with byte operations and forget about this headache option. Especially since there part of the data is still on the limits of the byte is. - gia commented on September 19th 19 at 00:14
Ah, such structures simply lot and I'm too lazy ))) - Maxwell_Rosenbau commented on September 19th 19 at 00:17
September 19th 19 at 00:07
The problem with this structure is that its bit fields do not fit on the borders of unsigned (even given the fact that Data structure alignment will be offered for 4 bytes)

For example, ProgramNumber is at offset 24 bits, but its size is 16 bits. The compiler in this case is forced to shift forward ProgramNumber 8 bit, unsigned the next.

ProgramInfoLength - with an offset of 28 bits similarly may not be placed on this shift, because it is larger than 4 bits, so the compiler moves it forward by 4 bits.

As a result, the structure can not hold less than four unsigned.
If You want to use it to bypass the initial bit string "02b05e1fa6c1..." will have that string be considerably broadened (optional for 32 bit in each block):
  1. add padding'and 8 bits at offset 24 bits
  2. add 4 bits padding'and offset 32 + 32 + 28 bit
  3. add padding'20 bits and offset 32 + 32 + 32 + 12 bit

And repeat this procedure for each block

Find more questions by tags C