c++ - 为什么编译器在 C/C++ 中填充结构?

标签 c++ c struct padding memory-alignment

我正在学习结构填充,并读到结构填充背后的原因是,如果结构的成员未对齐,处理器将无法在一个周期内读取/写入它们。通常,由 N 组成的数据类型的位置字节的地址应该是 N 的倍数.
假设这个结构例如:

struct X
{
    char c;
    // 3 bytes padding here so that i is aligned.
    int i;
};
这里这个结构的大小应该是 8 个字节,c默认是对齐的,因为它只占用1个字节,但是i不是。对于 i ,我们需要在它之前添加 3 个字节的填充,以便它“对齐”并且只能在一个周期内访问。告诉我我是否遗漏了什么。
1 - 对齐如何工作?成员与什么结盟?
2 - CPU 访问 N 有什么好处?位于 N 倍数的地址的字节数据类型?为什么例如,在上面的结构中,如果 i位于地址 XXX3 (以 3 结尾,换句话说,不是 4 的倍数),为什么不从地址 XXX3 开始读取一个单词?为什么一定是4的倍数?大多数 CPU 访问的地址是否仅为字长的倍数?我相信 CPU 可以从任何字节开始从内存中读取一个单词。我错了吗?
3 - 为什么编译器不对成员重新排序以尽可能多地占用空间?排序重要吗?我不确定是否有人使用实际的偏移量来访问成员。这意味着如果有一个结构 X x ,通常成员的访问方式如下:x.i不是 *(&x + 4) .在后一种情况下,排序实际上很重要,但在第一种情况下(我相信每个人都使用),排序应该无关紧要。我必须注意,在这个例子中,这无关紧要,因为如果 i来到 c此外,最后会有一个 3 字节的填充。我问一般为什么?
4 - 我读到这不再重要了,CPU 现在通常可以访问非对齐成员,花费与对齐成员相同的时间。真的吗?如果是,那为什么?
最后,如果有好的地方可以学习更多,我将不胜感激。

最佳答案

  • 它们至少与 _Alignof(type) 对齐.原则上允许实现进一步对齐,但这通常是不可取的,并且没有主要实现这样做。
  • 正如 Eljay 的评论中所指出的(强调我的):

    Alignment is a platform architecture constraint. Misaligned data access can be expensive (up to x16 as expensive in performance) as aligned access on some architectures, and can thwart atomic read/write (only relevant for multithreaded applications), or be unsupported entirely (causing a process fault). Other architectures can handle them without issue, and other architectures can handle them but at a performance penalty (so the compiler errs on the side of performance).


    编写语言标准以允许此类平台约束。
  • 不允许这样做,至少如果结构的地址以一种使表示对应用程序可见的方式获取的话是不允许的。语言规范要求成员有序。这是 6.7.2.1 结构和 union 说明符,¶15:

    Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.


  • 不,这不是真的。高端 CPU 通常会透明地修补未对齐的访问,以允许某些类型的草率代码以及必然未对齐的操作(如 memcpymemmove 通过具有不同对齐方式的缓冲区),但这并没有改变以下事实:这些操作往往更昂贵,并且它们不适用于诸如原子操作之类的某些事情。
  • 关于c++ - 为什么编译器在 C/C++ 中填充结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63294333/

    相关文章:

    c++ - 将二进制流转换为 png 格式

    c++ - 为什么连接多个字符串时性能会有所不同?

    ios - 在 Swift 中使用 C 函数

    c - 线程程序中的段错误

    c - 为什么当我试图找到结构指针的差异时会出现垃圾值?

    c++ - 将具有数组数据成员的结构保存到文件

    c++ - 使用 SHGetPathFromIDList 将 PIDL 转换为文件路径

    c++ - 条件 if 在字符串数组与常量字符上

    c - 动态库加载 : easy way to figure out unresolved symbols runtime

    c++ - 我如何在这里为 union 内的结构赋值?