4

可能重复:
为什么“sizeof”给出错误的测量值?

我有一个名为 CBUFFER_PEROBJECT 的结构:

struct CBUFFER_PEROBJECT
{
    D3DXMATRIX Final;
    D3DXMATRIX Rotation;
};

在另一堂课中,我这样做:

...
bd.ByteWidth = sizeof(CBUFFER_PEROBJECT); 
...

我发现 D3DXMATRIX 的大小是 64,所以 64+64 = 128(对吗?)。但是我的编译器在和我开玩笑(Visual C++),因为当我调试程序时,bd.ByteWidth 变成了 132,所以我去了即时窗口(Visual Studio),然后输入:

sizeof(D3DXMATRIX) + sizeof(D3DXMATRIX)

结果是:

128

但是 bd.ByteWidth 变成了 132,当我在“立即窗口”中输入以下内容时:

sizeof(CBUFFER_PEROBJECT)

它给了我:

128
4

5 回答 5

6

是的,您很困惑D3DMATRIX并且D3DXMATRIX(注意第二种类型中的额外 X)。第一个是 16 个浮点值的普通矩阵(正好是 64 个字节)。后者是一个类,它显然在结构的某处有 4 个字节的额外数据。也许是一个 vtable 或类似的东西。

如果您将代码编译为 C 而不是 C++,则大小将与提供后者结构的头文件相同typedef D3DMATRIX D3DXMATRIX;

请参阅:D3DXMATRIXD3DMATRIX

编辑:这有点像关于军队的老笑话“如果地图和现实不匹配,那么地图就是正确的”。在这种情况下,如果你不同意编译器,那你就错了。编译器在计算大小时总是正确的。理解为什么编译器得到这个数字,嗯,那是另一回事......通常通过将预期的偏移量与实际发生的情况进行比较来解决,并了解是什么(如果有的话)导致了“差距”。

于 2012-12-27T18:35:09.837 回答
2

您不能仅计算结构的成员大小来计算结构的大小,因为在结构中它还存储了一些额外的信息(程序员不可见)。这就是为什么你得到 132 而不是 128。

于 2012-12-27T18:37:43.090 回答
2

有时,当编译器评估结构声明时,它们会在字段之间添加填充字节。这是因为某些类型在与长度是其长度的倍数的内存地址对齐时表现更好。

我什至会说你很可能不会在即时窗口中看到这种效果。

鉴于这些理由,这是一个重复的问题。您可以在这里得到更深入的答案:为什么结构的 sizeof 不等于每个成员的 sizeof 之和?

于 2012-12-27T18:44:51.617 回答
1

在这种情况下,最好假设编译器是正确的。这很可能意味着CBUFFER_PEROBJECT您的项目中有两个不同的定义,但定义略有不同。编译器认为定义 A 的大小为 132,而调试器正在查看大小为 128 的定义 B。您可以通过sizeof(CBUFFER_PEROBJECT)在每个源文件中创建包含 的值的全局变量来测试这一点。然后,您可以在调试器中检查这些全局变量以查看它显示的内容。

当然,另一种可能性是您的内存被覆盖,而不是由您认为正在设置它的行设置。在这种情况下,像 Purify 或 valgrind 这样的东西可以帮助你找出内存问题。

于 2012-12-27T19:45:32.973 回答
1

您可以使用隐藏的 Visual Studio 编译器开关切换到/d1reportSingleClassLayoutSomeType来告诉您编译器布局是什么。按照链接阅读如何使用开关。

我为您的示例代码尝试了它,但我没有“D3DXMATRIX”类型。我确实有“D3DMATRIX”,所以我尝试了一下,得到了:

1>  class CBUFFER_PEROBJECT size(128):
1>      +---
1>   0  | _D3DMATRIX Final
1>  64  | _D3DMATRIX Rotation
1>      +---

因此,如果您使用开关应该能够告诉您结构的确切布局。

于 2012-12-27T20:47:30.813 回答