1

我的代码中有这个结构:

struct BlockDescriptor
{
    struct BlockDescriptor * pNext;
    bool _isFree;
};

我倾向于相信它的大小是 4 + 1 = 5 (4 代表指针和1bool,但由于某种原因sizeof(struct BlockDescriptor)返回 8 !有人能告诉我为什么吗?

是因为包装问题,5 被四舍五入为 4 的倍数(因为 32 位是大多数计算机最熟悉的),是否有某种方法可以强制它使用真实大小(如果这实际上是真实的尺寸) ?

4

3 回答 3

1

的数据成员struct默认对齐。这些数据成员之间可能存在填充以及最后一个数据成员之后的填充。在您的情况下,填充最有可能在最后。

第一个数据成员是一个指针,在您的情况下需要 4 个字节的内存。然后虽然另一个成员是char只需要1个字节的内存,有一个填充到4的倍数,但原因并不是你说的“32位是大多数计算机最舒服的”,而是因为4是最大数据成员的大小。

通常有一个 pragma 指令允许您指定可用的自定义对齐方式。在 Visual Studio 中,有#pragma pack, 在这种情况下可能会对您有所帮助。只要确保你知道你在做什么。尽管您将最小化内存使用量,但它可能会对代码的性能产生负面影响。

有关更多信息,请查看相关问题:
如何最小化结构类型的内存使用?
sizeof 如何计算结构的大小 结构
的大小是否必须是该结构对齐的精确倍数?
甚至确定 C/C++ 结构相对于其成员的对齐方式

于 2013-03-17T22:23:35.440 回答
0

发布答案:Luka Rahne 和 cnicutar

pNext 和 _isFree 之间有 Padding。您可以通过特定于编译器的机制强制“打包”,将 #pragma pack(1) 放在结构定义之前

于 2013-03-17T22:10:12.417 回答
0

当 CPU 访问内存以获取数据项(或结构成员)时,它实际上向内存控制器发送了一个请求,内存控制器执行一些技巧以使 DRAM 看起来是一个结构良好的数据存储。实际上,DRAM 是一堆单元,排列成 M 行,每行 N 位(其中 N 可能是一千左右)。

知道大多数体系结构一次处理 4、8、16 或 32(或有时更大)位,内存控制器针对从 4 的倍数地址中提取进行了优化。当您从地址 abcd1002 中提取单个字节时会发生什么?嗯,内存控制器从地址 abcd1000 获取四个字节,然后它们移动以获得第三个字节(记住,它是 0、1、然后是 2),并给你你糟糕的非对齐字节。因此,从对齐的地址获取总是比从非对齐的地址获取更快。

意识到这一事实,编译器通过填充数据结构积极优化速度,以便它们以内存友好的方式布局。

希望能为这个问题提供一个重要的计算机体系结构视角。我没有在当前的任何回复中看到这一点,因此我想添加我的 0.02 美元。

于 2013-03-17T22:47:45.953 回答