когда приведение указателя указывает на структуру, содержащую объединение - PullRequest
0 голосов
/ 06 марта 2011

У меня проблема со структурой, содержащей объединение.Вот проблема:

typedef struct
{
    unsigned char Type;                          
    union
    {
        unsigned char Length;
        unsigned __int16 Length2;
    }
    char Value[0];    
} TLV_TUPLE, *PTLV_TUPLE;

Если Type == 0x40h, я использую Length2, в противном случае используйте Length.

Я использую эту структуру для чтения этого потока файлов (в шестнадцатеричном формате):

FE 01 01 40 12 00 30 …

Теперь код:

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

Затем, когда я проверяю значение pTlv с помощью отладчика, я вижу это:

pTlv->Type == FE
pTlv->Length == 1
pTlv->Length2 == 4001
pTlv->Value == 12

Не должно ли Length2 быть 0x101 и value быть 48?

машина с прямым порядком байтов.

Пожалуйста, помогите мне с этим ...

1 Ответ

2 голосов
/ 06 марта 2011

Здесь происходит то, что структура дополняется дополнительным байтом, так что объединение может быть правильно выровнено.

01 после заполнения FE, фактическое объединение начинается сследующий байт.Это связано с тем, что на требование выравнивания для объединения влияют требования выравнивания его частей.

Поскольку Length2 требует выравнивания на двухбайтовой границе, перед ним вставляется байт заполнения, чтобы обеспечитьэто происходит.

Если бы поток, который вы читали, был FE FF 01 40 12 00 30 ..., вы все равно получили бы те же значения.


В целом, я думаю, "Shouldn’t Length2 be 0101 and value be 48?" должен был бы действительно прочитать64 (0x40), а не 48 (0x30).Я предполагаю, что это была опечатка с вашей стороны.


Если вам нужна структура, чтобы не было заполнения, нет стандартного способа сделать это, кроме вашегоКомпилятор должен предоставить способ.Например, вы можете использовать что-то вроде атрибутов в gcc:

typedef  struct {
    unsigned char Type;                          
    union {
        unsigned char Length;
        unsigned __int16 Length2;
    }
    char Value[0];    
} __attribute__ ((aligned(1),packed)) TLV_TUPLE;

В других средах может быть #pragma pack или что-то похожее для достижения того же конца.

...