【发布时间】:2014-06-22 18:00:47
【问题描述】:
我正在使用 IAR(一种 C 编译器)为 TI 芯片(16 位 MCU)编程。
我有以下结构,
//I use union mainly because sometimes I use the 2 bytes word value
// and sometimes I only use one byte (either a or b)
typedef union {
uint16_t address;
struct
{
uint8_t parta;
uint8_t partb;
} details;
} address_t;
那我有如下mac地址定义,
typedef struct
{
uint8_t frame_type;
uint8_t sequence_number;
address_t source_address;
} mac_header_t;
到目前为止一切顺利。
当我通过无线电接收数据包时,它会存储在缓冲区数组中。
uint8_t buffer[MAX_PACKET_LEN];
//the first byte is packet length, mac address follows
mac_header_t *header = (mac_header_t *)(buffer + 1);
奇怪的事情发生了,
//The packet is say
// 0x07 (length)
// 0x07 (frame_type)
// 0x04 (sequence_number)
// 0x00 (source address parta)
// 0x00 (source address partb)
//The source address is indeed 0x00 0x00 (2 bytes)
assert(header->source_address.details.parta == 0); //correct! there's no problem
assert(header->source_address.details.partb == 0); //correct! there's no problem
//assignment from header->source_address to another object
address_t source_address = header->source_address;
assert(source_address.details.parta == 0); //no! it's 0x04!
assert(source_address.details.partb == 0); //this is right
所以奇怪的是,从 header->source_address 分配到另一个对象后,对齐方式从 0x00 0x00 变为 0x04 0x00(注意缓冲区,这实际上将指针向前移动了 1 个字节)!
在我使用#pragma pack(1) 之后,事情就解决了。
但是,我不确定为什么这实际上会导致问题。在不同对齐边界处分配 2 个对象会导致两个完全不同的值? (右手边是0x00 0x00,左手边是0x04 0x00)
这段代码是否在 C 中未定义?还是IAR的bug?
谢谢。
【问题讨论】:
-
这看起来像是一个非常明显的混叠违规。您可能应该从接收到的内存中手动填充
mac_header_t对象。 -
在
header = (mac_header_t *)(buffer + 1)之后,对非uint8_t结构成员的任何访问都将违反对齐要求,因为+ 1。 -
您应该真正使用正确的反序列化代码,逐字节处理每条消息。
标签: c embedded memory-alignment iar