结构和对齐方式的大小

size of struct and alignment

本文关键字:方式 对齐 结构      更新时间:2023-10-16

根据这篇文章,结构的对齐是特定于实现的,这意味着不同的编译器将以不同的方式对齐结构中的成员,从而在编译器之间提供相同结构的不同大小。

但是,在此视频中,扬声器听起来像以下结构在编译器中的大小必须为 16 和 12:

#include <iostream>
struct C {
uint64_t x;
uint32_t y;
};
struct D {
uint32_t x;
uint32_t y;
uint32_t z;
};
int main() {
std::cout << sizeof(C) << std::endl;
std::cout << sizeof(D) << std::endl;
}

他们确实是 16 岁和 12 岁。

为什么他们必须是 16 岁和 12 岁? 不是 16 岁和 16 岁?

他们确实是 16 和 12。

它们具有此大小,给定:

  • 您使用的编译器(和选项)
  • 您的目标平台
  • 代码中没有与结盟/包装相关的指令

对于您的视频,我想演讲者只是采用了给定的平台/工具链来开发他的示例。但是,一般来说,由于sizeof(T)依赖于编译器/平台,因此std::atomic<T>::is_lock_free()也依赖于编译器/平台。

例子

使用以下结构:

struct C {
uint64_t x;
uint32_t y;
};

不同的编译器和选项

  • GCC 9.1"-M32":sizeof(C) = 12
  • MSVC x86 19.20:sizeof(C) = 16

目标平台

  • 适用于 x86-64 的 GCC 6.2:sizeof(C) = 16
  • 适用于 MSP430 的 GCC 6.2.1:sizeof(C) = 12

对齐/包装指令

  • GCC 9.1 x64 - 默认值:sizeof(C) = 16
  • GCC 9.1 x64 - 包装:sizeof(C) = 12
  • GCC 9.1 x64 - 对齐 128:sizeof(C) = 128

为什么会有这些差异?

编译器可以在结构/类的任何字段之后自由添加未使用的位/字节。他们这样做是出于性能原因:在某些平台上,读/写验证某些对齐属性的多字节int会更快(通常,N字节int的地址必须能被N整除)。

通常,C++编译器在您背后执行低级优化很方便。有时您希望对此功能进行更多控制(原因的非详尽列表):

  • 当您序列化将由其他程序读取的数据时(保存到文件,发送到网络)。
  • 当内存使用比执行速度更重要时。
  • 在多核和多线程程序中,控制CPU缓存行中有多少struct可以限制内核之间的缓存失效,从而提高执行速度。

这就是为什么编译器通常提供实用程序来控制它的原因。

TL;博士

对于给定的Tsizeof(T)"不必"成为任何东西。它依赖于编译器/平台,您通常可以使用特定的编译器指令覆盖它。