【问题标题】:Why are all arrays aligned to 16 bytes on my implementation?为什么在我的实现中所有数组都对齐到 16 个字节?
【发布时间】:2020-03-23 05:59:50
【问题描述】:

我的非常简单的代码如下所示

#include <iostream>
#include <stdalign.h>

int main() {
    char array_char[2] = {'a', 'b'};
    float array_float[2] = {1, 2};
    std::cout << "alignof(array_char): " << alignof(array_char) << std::endl;
    std::cout << "alignof(array_float): " << alignof(array_float) << std::endl;
    std::cout << "address of array_char: " << (void *) array_char << std::endl;
    std::cout << "address of array_float: " << array_float << std::endl;
}

这段代码的输出是

alignof(array_char): 1

alignof(array_float): 4

array_char的地址:0x7fff5e8ec580

array_float的地址:0x7fff5e8ec570

alignof运算符的结果在预期中,但是两个数组的真实地址并不一致。不管我试了多少次,地址总是 16 字节对齐的。

我在带有 Intel CORE i5 第 7 代 CPU 的 Ubuntu 16.04 上使用 gcc 5.4.0。

【问题讨论】:

  • "两个数组的真实地址和它们不一致" 是的。仅仅因为某些内容恰好与 16 字节边界对齐并不意味着它也不会与 2 或 1 字节边界对齐。
  • 没有 16 字节对齐 here
  • @Jarod42 根据我的 Godbolt 测试,似乎 gcc 将它们对齐到 16 个字节,直到 gcc 6.3。 (那里有 gcc 9.2。)
  • 编译器可能正在设置 16 字节对齐,以便它可以(可能)对您的数据使用 SSE 指令进行某些操作。

标签: c++ memory-alignment


【解决方案1】:

我找到了this 补丁。

这似乎是 GCC 6.4 中修复的 x86_64 错误。

System V x86-64 ABI 要求聚合类型(例如数组和structs)至少对齐到 16 个字节,如果它们至少有 16 个字节大的话。根据 ABI 规范中的注释,这是为了方便 SSE 指令的使用。

GCC 似乎错误地将该规则应用于大小为 16 位(而不是字节)和更大的聚合。

我建议您将编译器升级到更新的 GCC 版本。


然而,这只是一个优化问题,而不是正确性问题。对变量进行更严格的对齐并没有错,并且(与提到的 SSE 一样)过度对齐在某些情况下可能具有性能优势,超过了浪费堆栈内存的成本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 2013-05-18
    • 2012-04-30
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多