C++ 为我的结构提供意外结果的大小

C++ 为我的结构提供意外结果的大小,c++,memory,alignment,sizeof,memory-alignment,C++,Memory,Alignment,Sizeof,Memory Alignment,我的代码中有以下结构: struct BlockDescriptor { struct BlockDescriptor * pNext; bool _isFree; }; 我倾向于相信它的大小是4+1=5(指针为4,bool为1),但出于某种原因sizeof(struct BlockDescriptor)返回8!有人能告诉我为什么吗 是否因为包装问题,5被四舍五入为4的倍数(因为32位是大多数计算机最熟悉的),是否有某种方法迫使它使用真实尺寸(如果这是真实尺寸)?发布答案:Lu

我的代码中有以下结构:

struct BlockDescriptor
{
    struct BlockDescriptor * pNext;
    bool _isFree;
};
我倾向于相信它的大小是4+1=5(指针为4,bool为
1
),但出于某种原因
sizeof(struct BlockDescriptor)
返回8!有人能告诉我为什么吗


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

发布答案:Luka Rahne和cnicutar


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


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

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

第一个数据成员是指针,在您的情况下,它需要4字节的内存。然后,尽管另一个成员是只需要1字节内存的
char
,但有一个高达4的倍数的填充,但原因并非如您所说的“32位是大多数计算机最适合的”,而是因为
4
是最大数据成员的大小

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

有关更多信息,请查看相关问题:




或者甚至默认情况下,
struct
的数据成员正在对齐。这些数据成员之间可能存在填充,最后一个数据成员之后也可能存在填充。在您的情况下,填充最有可能在最后

第一个数据成员是指针,在您的情况下,它需要4字节的内存。然后,尽管另一个成员是只需要1字节内存的
char
,但有一个高达4的倍数的填充,但原因并非如您所说的“32位是大多数计算机最适合的”,而是因为
4
是最大数据成员的大小

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

有关更多信息,请查看相关问题:




甚至

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

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

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


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

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

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

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


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

填充。您可以通过特定于编译器的机制强制执行“打包”。将#pragma pack(1)放在结构定义之前。为什么对您来说,
sizeof(struct BlockDescriptor)
返回的内容很重要?@LukaRahne感谢struct:bool;结构*;您可能会得到5个字节,但这是编译器特定的填充,介于
pNext
\u isFree
之间。您可以通过特定于编译器的机制强制执行“打包”。将#pragma pack(1)放在结构定义之前。为什么
sizeof对您很重要(