结构数据对齐。大小必须是存在的最大类型的整数倍?
Struct data alignment. Size must be an integer multiple of the largest type present?
我正在制作一个 GUI,它 send/receives 通过串行端口传输数据。数据由在结构中定义的消息组成,如下所示:
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d[3];
uint16_t e;
} MyMsg_t;
我也在使用联合,因为它使我能够更轻松地设置数据字段并能够逐字节发送它。联盟看起来像这样:
typedef union
{
MyMsg_t msg;
uint8_t array[MyMsgLength];
} MyMsg;
我现在尝试向这样的消息中添加一些数据:
MyMsg msg;
msg.msg.a = (uint8_t) 1;
msg.msg.b = (uint8_t) 2;
msg.msg.c = (uint8_t) 3;
msg.msg.d[0] = (uint16_t) 4;
msg.msg.d[1] = (uint16_t) 5;
msg.msg.d[2] = (uint16_t) 6;
msg.msg.e = (uint16_t) 7;
我通过串行总线逐字节传输,接收端是:
1 2 3 19 4 0 5 0 6 0 7
(c到e中的数据因为总线的原因颠倒了)
看起来结构实际上是:
typedef struct
{
uint8_t a; //1
uint8_t b; //2
uint8_t c; //3
//uint8_t x //19
uint16_t d[3];
uint16_t e;
} MyMsg_t;
由此我可以假设它在 C 标准的某处说在这种情况下结构必须是最小 n * sizeof(uint16_t) 因为我们不能有例如 3.5 中最大的类型一个结构,但它必须是一个整数?
我猜这就是所谓的padding?有什么方法可以强制结构为 n * sizeof(uint8_t) 即使存在更大的类型?
我知道如何避免这种情况,但它需要不使用 union 和更多代码。有什么方法可以通过最少的代码干预优雅地避免这个问题吗?
不要忘记机器的字节顺序,这就是为什么不推荐这样做的原因。如果您不关心字节序或以其他方式处理它,那么这种方法是可以接受的。
您可以更改对齐方式以消除填充。但是,如何完成取决于编译器:
- Microsoft Visual C++ -
#pragma pack
- gcc -
__attribute__(packed)
, 也支持 #pragma pack
其他编译器可能有其他选项或方法来完成同样的事情。
我正在制作一个 GUI,它 send/receives 通过串行端口传输数据。数据由在结构中定义的消息组成,如下所示:
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d[3];
uint16_t e;
} MyMsg_t;
我也在使用联合,因为它使我能够更轻松地设置数据字段并能够逐字节发送它。联盟看起来像这样:
typedef union
{
MyMsg_t msg;
uint8_t array[MyMsgLength];
} MyMsg;
我现在尝试向这样的消息中添加一些数据:
MyMsg msg;
msg.msg.a = (uint8_t) 1;
msg.msg.b = (uint8_t) 2;
msg.msg.c = (uint8_t) 3;
msg.msg.d[0] = (uint16_t) 4;
msg.msg.d[1] = (uint16_t) 5;
msg.msg.d[2] = (uint16_t) 6;
msg.msg.e = (uint16_t) 7;
我通过串行总线逐字节传输,接收端是:
1 2 3 19 4 0 5 0 6 0 7
(c到e中的数据因为总线的原因颠倒了)
看起来结构实际上是:
typedef struct
{
uint8_t a; //1
uint8_t b; //2
uint8_t c; //3
//uint8_t x //19
uint16_t d[3];
uint16_t e;
} MyMsg_t;
由此我可以假设它在 C 标准的某处说在这种情况下结构必须是最小 n * sizeof(uint16_t) 因为我们不能有例如 3.5 中最大的类型一个结构,但它必须是一个整数?
我猜这就是所谓的padding?有什么方法可以强制结构为 n * sizeof(uint8_t) 即使存在更大的类型?
我知道如何避免这种情况,但它需要不使用 union 和更多代码。有什么方法可以通过最少的代码干预优雅地避免这个问题吗?
不要忘记机器的字节顺序,这就是为什么不推荐这样做的原因。如果您不关心字节序或以其他方式处理它,那么这种方法是可以接受的。
您可以更改对齐方式以消除填充。但是,如何完成取决于编译器:
- Microsoft Visual C++ -
#pragma pack
- gcc -
__attribute__(packed)
, 也支持#pragma pack
其他编译器可能有其他选项或方法来完成同样的事情。