为什么这个C ++程序返回16个字节?

时间:2014-02-28 07:15:42

标签: c++

使用gcc编译并在32位架构上执行时,以下程序返回16个字节。我想知道它为什么返回,因为它既不使用长的双成员也不是在64位机器上运行,并且没有定义虚拟函数来获取额外的内存字节,并且在计算 double的大小时 int 数据成员,结果大约12个字节。那么为什么这个16字节值?

class A {
public:
     void* data;
};
void* operator new (size_t sz, A& obj) {
     printf("Custom operator new called for %d bytes\n", sz);
     return obj.data;
}
class foo {
public:
     double a;
     int x;
     foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
     A obj;
     obj.data = malloc(sizeof(foo));
     printf("Allocator data: %p\n", obj.data); // Allocator data:  0x4601a8
     foo *f = new (obj) foo; // Custom operator new called for **16 bytes**
                                       // foo constructor called (this=0x4601a8)
     printf("foo allocated at %p\n", f); // foo allocated at 0x4601a8
}

5 个答案:

答案 0 :(得分:4)

4末尾添加

foo个字节作为填充。这通常用于对齐目的 - double与架构上的8字节对齐,因此如果创建foo s的数组,则填充字节保证成员{{ 1}}正确对齐。

在类型中,无法保证大小等于成员大小的总和。通常情况下,它不是。

有一些特殊的编译器相关标志可以防止添加填充字节,您可以查找它们。 (a

答案 1 :(得分:0)

结构对象中可能存在未命名的填充,称为Data_structure_alignment

在你的情况下,double对齐到8个字节,所以sizeof foo应该是8 * N,所以4bytes填充

答案 2 :(得分:0)

当我运行你的代码时,我发现了以下内容:

class A {
public:
     void* data;
};
void* operator new (size_t sz, A& obj) {
     printf("Custom operator new called for %d bytes\n", sz);
     return obj.data;
}
class foo {
public:
     double a;
     int x;
     foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
     A obj;
     obj.data = malloc(sizeof(foo));
     printf("Allocator data: %p\n", obj.data); // Allocator data:  0x991d008
     printf("size of obj: %d\n", sizeof(obj)); // size of obj:  4
     printf("size of foo: %d\n",sizeof(foo)); // size of foo: 12
     foo *f = new (obj) foo; // Custom operator new called for **12 bytes**
                                       // foo constructor called (this=0x991d008)
     printf("foo allocated at %p\n", f); // foo allocated at 0x991d008
} 

我添加了两个额外的打印声明,此处foo的大小为12. double + int

答案 3 :(得分:0)

这是因为编译器应用了内部填充。我们可以通过使用 __ packed 编译器指令来避免这种情况。

您可以参考以下帖子了解有关填充的信息

Structure padding and packing

答案 4 :(得分:0)

考虑data alignment。编译器在oder中对齐对象的数据以将它们存储在内存中,以便CPU可以在一次加载中获取它们 - 这仅适用于对齐的数据。这是硬件方面。