结构一字节对齐与架构的对齐要求冲突?

2024-01-30

我之前发过一个问题here https://stackoverflow.com/questions/13881487/should-i-worry-about-the-alignment-during-pointer-casting#comment19155923_13881487关于指针转换期间的对齐访问。总而言之,最好不要使用未对齐访问来实现完全可移植,因为某些架构可能会引发异常,或者与对齐访问相比,性能可能会变得相当慢。

然而,有案例 https://stackoverflow.com/questions/4507735/pragma-pack-in-c我想使用一字节对齐,例如,在传输网络数据期间,我不想在结构内部添加额外的填充。所以通常这里所做的是:

#pragma pack (push, 1)
struct tTelegram
{
   u8 cmd;
   u8 index;
   u16 addr1_16;
   u16 addr2_16;
   u8  length_low;
   u8 data[1];
};
#pragma pack (pop)

那么您可能已经知道我的问题:如果我在结构上强制执行一字节对齐,这是否意味着它不能完全可移植,因为结构成员未对齐?如果我既想要无填充又想要便携性怎么办?


首先,未对齐的内存访问是指跨内存中多个字的单条数据。例如:在 32 位系统上,32 位int地址 0、4、8 等处是对齐的,但地址 1、2、3、5、6、7、9 等处则未对齐。

其次,未对齐的数据不会在 C++ 意义上“引发异常”,但可能会在 CPU 级别引发中断/陷阱/异常 - 例如UNIX 上的 SIGBUS,您通常会设置一个信号处理程序来对此做出反应,但如果您需要以可移植的方式解析未对齐的数据,您不会通过捕获信号来实现 - 您需要手动编写打包和打包的步骤跨字边界解包数据。

In your tTelegram结构体中,数据并没有“未对齐”,但是在从寄存器打包/解包数据时进行位移位和屏蔽数据的过程仍然可能比使用占用独立字的数据更慢 - 需要更多的机器代码指令。

关于可移植性 - 所有非玩具编译器都可以选择以您所描述的方式打包,但确切的编译指示会有所不同,多字节值中的字节布局可能仍然是大端或小端(或有些 CPU 允许一些未对齐的数据访问(例如 x86),而其他 CPU 则不允许(例如 Ultrasparc)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

结构一字节对齐与架构的对齐要求冲突? 的相关文章

随机推荐