首页 文章

在哪里可以找到任意编译器的对齐要求? [关闭]

提问于
浏览
0

我遇到了这个页面The Lost Art of C Structure Packing,虽然我从来没有必要填写任何结构,但我想学习更多,以便当/如果我也需要 - 我可以 .

它说:

x86或ARM处理器上基本C数据类型的存储通常不会从内存中的任意字节地址开始 . 相反,除char之外的每种类型都有对齐要求;字符可以从任何字节地址开始,但是2字节短路必须从偶数地址开始,4字节整数或浮点数必须从可被4整除的地址开始,8字节长或双精度必须从可被8整除的地址开始签名或未签名没有区别 .

这是否意味着所有32位处理器(x86,ARM,AVR32,PIC32 ......)都具有这种对齐要求?那么16位处理器呢?

如果没有,并且它是特定于设备的,我在哪里可以找到这些信息?我尝试搜索Microchip XC16 Manual,但我找不到对齐要求,说明ints从可被4整除的地址开始 .

我假设信息存在,我不是在寻找正确的关键词 - 如果我在网上搜索更多信息,那么“对齐要求”是什么?

2 回答

  • 1

    这里有两个全球答案 . 是的,所有处理器都有某种对齐惩罚(ARM,MIPS,x86等) . 不,你不能按类型确定 . 所有ARM都没有相同的对齐惩罚,尽管人们认为他们知道旧的ARMv4和ARMv5,你可以以可预测的方式进行未对齐的访问,这种可预测的方式不是我们大多数人所希望的,而你必须启用它 . MIPS和ARM以及其他人可能会对未对齐的传输进行严厉处罚,您将遇到数据错误 . 但由于程序员编程等的性质,至少ARM的默认设置是在某些/更新的内核上禁用该功能 . 您可以根据需要禁用它或启用它 .

    所有处理器都会因未对齐传输而受到损失,性能下降,并且这些命中发生在各个层,有时在核心,核心边缘,每个缓存层以及ram的外层 . 由于设计变化如此广泛,您无法提出单一规则 .

    同样,由于编译器中的对齐是实现定义的,因此您无法编写可移植代码 . 因此,如果您正在处理处理器(可能是ARM,因为那是大多数人被咬过的地方),启用了未对齐的错误,最便携的解决方案,但不是万无一失的,是用64位变量启动结构,然后是32那么16然后是8.编译器倾向于按照你定义它们的顺序放置东西,只要整个结构在该目标的右边界上开始,那么变量将正确地对齐,不需要填充 . 除了不使用结构,或禁用对齐检查并遭受前端性能命中之外,没有全局解决方案 .

    请注意,我们今天通常处理的32位臂使用的是64位AMBA / AXI总线而不是32位,如果启用,它们仍然可以检查传输的所有对齐(16,32,64),但未对齐的性能至少在除非你越过64位对齐边界,否则AMBA / AXI级别不会打你 . 您可能仍会有额外的缓存行命中,但如果您没有AMBA / AXI命中,则不太可能 .

  • 1

    对齐要求有两个注意事项:必需,首选

    必需:示例:某些平台需要各种类型,例如 int 要对齐 . 尝试访问未对齐边界上的 int 的扭曲代码会导致错误 . 编译器通常会自动对齐数据以防止出现此问题 .

    效率:可以允许未对齐访问但导致代码更慢 . 许多编译器,而不是打包数据,将默认为对齐数据以提高速度效率 . 通常,此类编译器允许编译器特定的关键字或编译器选项来打包数据,以提高空间效率 .

    这些问题适用于各种尺寸的不同处理器 . 8位处理器可能具有16位数据总线,并且需要对齐16位类型 . 用于64位处理器的兼容C编译器可能只有64位类型,甚至 char . 可能性很大 .


    C在 <stddef.h> 中提供整数类型 max_align_t . 这可以以各种方式用于确定最小的一般对准要求 .

    ... max_align_t是一种对象类型,其对齐方式与所有上下文中的实现所支持的一致; ......C11§7.192

    C也有 _Alignas() 对变量进行更严格的对齐 .

相关问题