2014-02-28 42 views
0

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

结构物体内可能存在无名填充 – michaeltang

+0

取决于您的默认填充 - 1,2或4个字节的填充,您将得到12.使用8或16字节填充,您将得到16. – cup

回答

4

4字节在foo结束作为填充溶液。这通常是为了对齐目的而完成的 - double在您的体系结构上与8字节对齐,因此如果您创建foo的数组,则填充字节将保证成员a已正确对齐。

在班级类型中,不能保证大小等于成员的大小之和。往往不是,它不是。

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

+0

是 - 双 –

0

8 * N,所以4字节填充

可以有结构对象内无名填充,这是在你的情况称为 Data_structure_alignment

,双对准8个字节,所以的sizeof FOO应

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

+0

填充是系统特定的,所以这不幸没有帮助。该代码将在不同的计算机和编译器上得到不同的结果。 – Lundin

0

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

您可以参考以下的职位的理解有关填充

Structure padding and packing

0

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