我遇到了以下c代码。
union packet_t {
uint8_t raw[10];
struct {
union {
uint16_t number;
uint8_t number_byte[2];
};
union {
uint32_t size;
uint16_t size_word[2];
uint8_t size_byte[4];
};
uint8_t body[4];
};
} packet;
当我尝试对其进行测试时,我遇到了一些奇怪的行为,希望有人可以帮助我找出此定义的问题所在。我做了一些搜索,但是没有类似的问题。
这是我尝试过的:
uint8_t test1[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a};
int i = 0;
for(i = 0; i < sizeof(test1); i++)
{
packet.raw[i] = test1[i];
}
printf("packet.size_word[0]=0x%04x\n", packet.size_word[0]);
printf("packet.size_word[1]=0x%04x\n", packet.size_word[1]);
输出为
packet.size_word[0]=0x0605
packet.size_word[1]=0x0807
它完全错过了0x03和0x04。
当我使用以下定义(删除“ uint32_t size;”)时,它可以正常工作。
union packet_t {
uint8_t raw[10];
struct {
union {
uint16_t number;
uint8_t number_byte[2];
};
union {
uint16_t size_word[2];
uint8_t size_byte[4];
};
uint8_t body[4];
};
} packet;
以下是输出:
packet.size_word[0]=0x0403
packet.size_word[1]=0x0605
有人知道为什么会这样吗?我以为联合中的项目总是占据相同的内存位置。
--------------------------更新11/25/2018 --------------- ------------------
所以我有信心现在是结构填充,并且取决于CPU架构。
我在Arduino上使用Atmega328p(8位MCU)进行了测试,它的工作原理很吸引人。由于MCU每次处理1个字节,因此没有结构填充。
但是,正如@selbie提到的那样,该代码根本不可移植,在编写此类代码时,我们必须考虑CPU架构和环境。最简单的解决方案是不使用它。
进一步阅读: