我有一个结构体,由编码器的供应商提供。
数据大多是 16 位字。有时是带位域的 16 位字,有时是 32 位变量,有时是 48 位变量或 64 位变量。
我创建建了这个个结构体,是 44 个 16 位字,也就是 88 字节。但我检查大小时,它却是 100 字节。这表明结构体中插入了填充字节。幸好有__packed 属性这种东西。
我添加了__packed 属性,却收到了 “packed 属性被忽略” 的警告。
后来我意识到需要在所有地方都加上 packed。于是我在能想到的所有地方都加了,之后就没有再收到警告了!
但是,结构体的大小仍然是 100 字节,而不是 88 字节。
代码如下:
typedef __packed union
{
uint8_t byte;
__packed struct
{
uint8_t start_address:4;
uint8_t end_address:4;
};
} OEM_COMP_MEMORY_STRUCT;
typedef __packed union
{
uint16_t word[4];
uint32_t dword[2];
uint8_t byte[8];
OEM_COMP_MEMORY_STRUCT addresses[8];
} MEMORY_ALLOCATION_STRUCT;
typedef __packed union
{
uint8_t byte[88];
uint16_t word[44];
__packed struct {
uint16_t MASK0; // 4
uint16_t MASK1; // 5
uint16_t MASK2; // 6
uint16_t MASK3; // 7
uint16_t EnDat_version; // 8
MEMORY_ALLOCATION_STRUCT OEM; // 9, 10, 11, 12
uint16_t transfer_format_position; // 13
uint16_t Encoder_type; // 14
uint32_t Signal_period; // 15, 16
uint16_t Number_of_revolutions; // 17
uint16_t Distance_of_reference_marks; // 18
uint16_t Position_first_reference_mark; // 19
uint32_t Measuring_step; // 20 21
uint32_t Datum_shift; // 22 23
ID_NUMBER_STRUCT id_number; // 24, 25, 26
SERIAL_NUMBER_STRUCT serial_number; // 27, 28, 29
DIRECTION_ROTATION_STRUCT direction_of_rotation; // 30
EXTERNAL_COMMISSIONING_DIAG_STRUCT external_commissioning_diagnostics; // 31
uint16_t Maximum_velocity; // 32
VELOCITY_RANGE_STRUCT Velocity_range1; // 33
VELOCITY_RANGE_STRUCT Velocity_range2; // 34
ERROR_MESSAGE_STRUCT Support_of_error_message1;// 35
WARNINGS_STRUCT Support_of_warnings; // 36
ENDAT_COMMAND_SET_STRUCT EnDat_command_set; // 37
VALUE_UNITS_STRUCT measuring_length; // 38
VALUE_UNITS_STRUCT maximum_processing_time; // 39
TWO_BYTES_STRUCT EnDat_ordering; // 40
uint16_t word41;
uint16_t word42;
uint16_t word43;
uint16_t word44;
uint16_t word45;
uint16_t word46;
uint16_t checksum; // simple sum of the bytes in the structure word[43] = sum(word[0]...word[42] & 0xFFFF
};
} PARM_ENCODER_MANUFACTURER_STRUCT; // *PEM
PARM_ENCODER_MANUFACTURER_STRUCT *PEM = ((PARM_ENCODER_MANUFACTURER_STRUCT *) &EMEM.NVMword[4]);
void check_PEM(void)
{
char buf[100];
uint16_t i;
for (i=0;i<44;i++)
{
PEM->word = i + 4;
}
write_debug_str("In check_PEM\r\n");
sprintf(buf,"MASK0: %u, 0x%04X, should be 4\r\n", PEM->MASK0, PEM->MASK0);
write_debug_str(buf);
sprintf(buf,"EnDat_version: %u, 0x%04X, should be 8\r\n", PEM->EnDat_version, PEM->EnDat_version);
write_debug_str(buf);
sprintf(buf,"OEM.word[0]: %u, 0x%04X, should be 9\r\n", PEM->OEM.word[0], PEM->OEM.word[0]);
write_debug_str(buf);
sprintf(buf,"OEM.word[1]: %u, 0x%04X, should be 10\r\n", PEM->OEM.word[1], PEM->OEM.word[1]);
write_debug_str(buf);
sprintf(buf,"OEM.word[2]: %u, 0x%04X, should be 11\r\n", PEM->OEM.word[2], PEM->OEM.word[2]);
write_debug_str(buf);
sprintf(buf,"OEM.word[3]: %u, 0x%04X, should be 12\r\n", PEM->OEM.word[3], PEM->OEM.word[3]);
write_debug_str(buf);
sprintf(buf,"transfer_format_position: %u, 0x%04X, should be 13\r\n", PEM->transfer_format_position, PEM->transfer_format_position);
write_debug_str(buf);
sprintf(buf,"Datum_shift: %lu, 0x%08lX, should be 22 23\r\n", PEM->Datum_shift, PEM->Datum_shift);
write_debug_str(buf);
}
运行程序该函数输出如下:
In check_PEM
MASK0: 4, 0x0004, should be 4
EnDat_version: 8, 0x0008, should be 8
OEM.word[0]: 10, 0x000A, should be 9
OEM.word[1]: 11, 0x000B, should be 10
OEM.word[2]: 12, 0x000C, should be 11
OEM.word[3]: 13, 0x000D, should be 12
transfer_format_position: 14, 0x000E, should be 13
Datum_shift: 1638424, 0x00190018, should be 22 23
问题出在 MEMORY_ALLOCATION_STRUCT 类型的 OEM 变量存在内存对齐问题;
而 __PACKED 关键字本应解决这个问题……
|
|