C++ - 对象填充的复杂性
C++ - object padding intricacies
我试图深入理解结构和 class 填充,因此我设计了一个我认为比我在有关该主题的教程中找到的许多示例更具挑战性的示例。我在 x64 机器上用 g++ 编译了它,没有启用任何代码优化。我的代码如下:
class Example
{
private:
long double foobar; // 10 bytes + 6 padded bytes as double follows
double barfoo; // 8 bytes + 8 padded bytes
static float barbar; // didn't count as it's a static member
float *fooputs; // 8 bytes + 8 padded bytes
int footsa; // 4 bytes, stored in the padded portion of float
char foo; // 1 byte, stored in the padded portion of float
public:
int function1(int foo) { return 1; }
void function2(int bar) { foobar = bar; }
};
int main()
{
std::cout << sizeof(Example) << std::endl; // 48 bytes
return 0;
}
虽然我看到 Example
的大小是 48 字节,但我预计它是 37 字节。我的期望论证如下:
foobar
需要 10 个字节。如下double
,还需要6个字节来填充。
barfoo
需要 8 个字节,因为它是 double
。不需要填充,因为 mod(16,8) == 0
*fooputs
需要 8 个字节,因为它是 x64 架构中的指针。不需要填充,因为 mod(24,8) == 0
footsa
需要 4 个字节作为 int。不需要填充,因为 mod(32,4) == 0
foo
需要 1 个字节作为一个字符。不需要填充。
由于结果与预期不同,我试图通过注释 class 成员来了解 C++ 如何将 Example
的大小评估为 48 字节。因此,除了 foobar
的论证之外,我假设了我在每个成员的内联评论中所写的理由。
谁能解释一下如何将大小计算为 48 字节,我的理由是否正确?
你忘记了最后的填充。 sizeof
returns 个 number of bytes between two adjacent members in an array。在您的情况下,alignof(long double)
很可能是 16,因此每个 Example
实例都需要位于 16 字节对齐的地址。
因此,如果您在 16 字节对齐地址 A 处有第一个 Example
实例,然后成员需要 37 个字节,则下一个 Example
实例不能存放在A+37字节,需要存放在A+k * 16。满足 k * 16 >= 37 的最小可能 k 是 3。这最终给了你字节数在数组 3 * 16 = 48 中的两个 Example
实例之间,正好是 sizeof(Example)
.
我试图深入理解结构和 class 填充,因此我设计了一个我认为比我在有关该主题的教程中找到的许多示例更具挑战性的示例。我在 x64 机器上用 g++ 编译了它,没有启用任何代码优化。我的代码如下:
class Example
{
private:
long double foobar; // 10 bytes + 6 padded bytes as double follows
double barfoo; // 8 bytes + 8 padded bytes
static float barbar; // didn't count as it's a static member
float *fooputs; // 8 bytes + 8 padded bytes
int footsa; // 4 bytes, stored in the padded portion of float
char foo; // 1 byte, stored in the padded portion of float
public:
int function1(int foo) { return 1; }
void function2(int bar) { foobar = bar; }
};
int main()
{
std::cout << sizeof(Example) << std::endl; // 48 bytes
return 0;
}
虽然我看到 Example
的大小是 48 字节,但我预计它是 37 字节。我的期望论证如下:
foobar
需要 10 个字节。如下double
,还需要6个字节来填充。barfoo
需要 8 个字节,因为它是double
。不需要填充,因为mod(16,8) == 0
*fooputs
需要 8 个字节,因为它是 x64 架构中的指针。不需要填充,因为mod(24,8) == 0
footsa
需要 4 个字节作为 int。不需要填充,因为mod(32,4) == 0
foo
需要 1 个字节作为一个字符。不需要填充。
由于结果与预期不同,我试图通过注释 class 成员来了解 C++ 如何将 Example
的大小评估为 48 字节。因此,除了 foobar
的论证之外,我假设了我在每个成员的内联评论中所写的理由。
谁能解释一下如何将大小计算为 48 字节,我的理由是否正确?
你忘记了最后的填充。 sizeof
returns 个 number of bytes between two adjacent members in an array。在您的情况下,alignof(long double)
很可能是 16,因此每个 Example
实例都需要位于 16 字节对齐的地址。
因此,如果您在 16 字节对齐地址 A 处有第一个 Example
实例,然后成员需要 37 个字节,则下一个 Example
实例不能存放在A+37字节,需要存放在A+k * 16。满足 k * 16 >= 37 的最小可能 k 是 3。这最终给了你字节数在数组 3 * 16 = 48 中的两个 Example
实例之间,正好是 sizeof(Example)
.