karatelambda
karatelambda

Reputation: 1

when cast pointer to point to a struct containing union

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

Answers (1)

paxdiablo
paxdiablo

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

Related Questions