Reputation: 1
I have problem with a struct containing union. Here is the problem:
typedef struct
{
unsigned char Type;
union
{
unsigned char Length;
unsigned __int16 Length2;
}
char Value[0];
} TLV_TUPLE, *PTLV_TUPLE;
If Type == 0x40h
, I use Length2
, otherwise use Length
.
I use this structure to read this file stream (In hex):
FE 01 01 40 12 00 30 …
Now the code:
unsigned char * m_pTLV;
/*code here to let m_pTLV points to the
first byte of the file, that is, point to 'FE' */
PTLV_TUPLE pTlv = (PTLV_TUPLE)m_pTLV; // cast m_pTLV to PTLV_TUPLE
Then as I check the value of pTlv with debugger, I see this:
pTlv->Type == FE
pTlv->Length == 1
pTlv->Length2 == 4001
pTlv->Value == 12
Shouldn't Length2
be 0x101
and value
be 48
?
machine is little endian.
Please help me with this...
Upvotes: 0
Views: 1056
Reputation: 881383
What's happening here is that the structure is being padded with an extra byte so that the union can be correctly aligned.
The 01
following the FE
is padding, the actual union starts at the next byte. That's because the alignment requirement for a union is affected by the alignment requirements of its parts.
Since Length2
has a requirement to be aligned on a two-byte boundary, a padding byte is inserted before it to ensure this happens.
If the stream you read in was FE FF 01 40 12 00 30 ...
, you would still get the same values.
As an aside, I think "Shouldn’t Length2 be 0101 and value be 48?"
should actually have read 64 (0x40)
rather than 48 (0x30)
. I assume that was a typo on your part.
If you need the structure to not have padding, there's no standard way to do it but your compiler should provide a way. For example, you could use something like attributes in gcc
:
typedef struct {
unsigned char Type;
union {
unsigned char Length;
unsigned __int16 Length2;
}
char Value[0];
} __attribute__ ((aligned(1),packed)) TLV_TUPLE;
Other environments may provide a #pragma pack
or something similar to acheive the same end.
Upvotes: 2