2014-11-28 3 views
2

Я использую следующие структуры для форматирования данных CAN-сообщений. messageData.ptr используется для дальнейшей обработки. Часть раздела используется для лучшего доступа. Проблема заключается в том, что whyever есть еще два байта между messageData.srcSpecifier и messageData.dataredundant bytes in union typedef

typedef union _MessagePureData_TypeDef 
{ 
    signed int S32[1]; 
    unsigned int U32[1]; 
    unsigned short U16[2]; 
    signed short S16[2]; 
    unsigned char U8[4]; 
} messagePureData; 

typedef union _MessageData_TypeDef 
{ 
    unsigned char ptr[6]; 
    struct 
    { 
     unsigned char srcDevice; 
     unsigned char srcSpecifier; 
     messagePureData data; 
    } section; 
} messageData; 

пример:

messageData.section.srcDevice = 0xAA; 
messageData.section.srcSpecifier = 0xBB; 
messageData.section.data.U32 = 0x11223344; 

результаты, которые messageData.ptr содержит: [0xAA, 0xBB, 0х01, 0x17, 0x44, 0x33]

так от где 0x01 и 0x17 ??

ответ

2

Выравнивание.
A messagePureData всегда выровнен для int, что, возможно, составляет 4 байта. Это означает, что section наиболее точно выровнен для 8 байтов, помещая два байта заполнения между srcSpecifier и data (так что весь объект структуры имеет выравнивание 8 и data один из 4). С другой стороны, ptr в качестве массива является непрерывным, поэтому он охватывает то же хранилище, что и два байта заполнения.

| ptr   | ptr + 1  | ptr + 2 | ptr + 3 | ptr + 4 | ptr + 5 | 
|    |    |   |   |   |    
| srcDevice | srcSpecifier | padding | padding | &data  | &data + 1 | ... 

^       ^    ^
| Address is multiple of 8 |     | Address is multiple of 4 
          |     
          | 
          | Address is a multiple of two; 
          | Unfeasible address for data. 

Вы можете упаковать структуру, чтобы обойти это.

0

Соединительный элемент содержит int членов, он имеет такое же требование к выравниванию, как int. Заполнение добавляется до data - член структуры, если необходимо, для обеспечения выравнивания.

На вашей платформе, похоже, что это требование составляет четыре байта. Два члена перед ним берут один байт, поэтому еще два должны сделать его смещение кратным четыре. Они не инициализируются никаким конкретным значением, поэтому вы видите произвольные значения, если вы смотрите на них.

0

Размер поля messagePureData data - 32 бит.

Поэтому компилятор сопоставляет его с 32-разрядным адресом, добавляя 2 байта (a.k.a. padding).

Вы можете использовать #pragma pack, чтобы компилятор не применял это повторное выравнивание.

Но не забывайте, что код сборки для доступа к этому полю может быть немного менее эффективным.