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

时间:2012-12-17 00:03:14

标签: c++ c alignment

我之前发布了一个关于指针转换过程中对齐访问的问题here。总而言之,最好不要将未对齐访问用于完全可移植,因为某些体系结构可能会抛出异常,或者与对齐访问相比,性能可能会变慢。

但是,there are cases我想使用单字节对齐,例如,在传输网络数据期间,我不希望在结构内部添加额外的填充。所以通常在这里做的是:

#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)

然后你可能已经知道我的问题:如果我在我的结构上强制执行一个字节的对齐,这是否意味着它不能完全可移植,因为struct成员没有对齐?如果我想要没有填充和可移植性怎么办?

2 个答案:

答案 0 :(得分:3)

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

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

在你的tTelegram结构中,数据没有"未对齐",但是当从寄存器中打包/解包数据时,位移和屏蔽数据的过程仍然可能更慢 - 需要更多的机器代码指令 - 而不是使用占用独立单词的数据。

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

答案 1 :(得分:2)

在不同计算机之间传输数据时,您始终希望格式化数据。请注意,数据格式不必是可读的,但它很可能是二进制的。二进制格式将包括每个数据项的确切位置,其类型,多字节数据,字节出现的顺序,大小或确定大小的方式等。不使用定义的格式将咬,可能比后面。

换句话说,虽然我已经看到了你所描述的方法,但我不认为它们是正常的,当涉及到不同实体之间的定义格式时肯定不正常(公司肯定,也可能是不同部门和/或团体)。在我接收和发送数据的地方,确实定义了确切的格式。如果定义的格式可以与struct中的数据布局匹配,它肯定也用于解码数据,但是已知它不是可移植的,并且可移植的代码不会尝试使用这样的设施。相反,它使用一些东西来读/写相关记录并对其进行适当的解码/编码。通常,解码/编码代码是从某种描述精确数据布局的元格式生成的。