结构的大小和对齐方式

size of struct and alignment

根据此post,struct 的对齐是特定于实现的,这意味着不同的编译器将以不同的方式对齐 struct 中的成员,从而在不同的编译器中给出相同结构的不同大小。

但是,在这个 video 中,演讲者听起来像是以下结构在编译器中的大小必须为 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 吗?

And they are indeed 16 and 12.

他们是这个尺寸,给定:

  • 您使用的编译器(和选项)
  • 你的目标平台
  • 代码中缺少与 aligment/packing 相关的指令

对于你的视频,我想演讲者只是用给定的 platform/toolchain 来发展他的例子。但是一般来说,由于 sizeof(T) 是 compiler/platform 相关的,因此 std::atomic<T>::is_lock_free() 也是 compiler/platform 相关的。

例子

使用以下结构:

struct C {
    uint64_t x;
    uint32_t y;
};

不同的编译器和选项

目标平台

Alignment/packing 指令

为什么会有这些差异?

编译器可以在 structure/class 的任何字段后自由添加未使用的 bits/bytes。他们这样做是出于性能原因:在某些平台上,read/write a multi-byte int 验证某些对齐属性(通常是 N 字节的地址int 必须能被 N 整除)。

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

  • 当您序列化将由不同程序读取的数据时(保存到文件,发送到网络)。
  • 当内存使用比执行速度更重要时。
  • 在多核&多线程程序中,控制内核之间CPU cache line can limit cache invalidations个数struct,提高执行速度。

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

TL;DR

对于给定的 Tsizeof(T) 不会 "have" 成为任何东西。它是 compiler/platform 相关的,您通常可以使用特定的编译器指令覆盖它。