2015-01-13 32 views
2
#include <iostream> 
using namespace std; 
#pragma pack(push, 4) 
struct Foo 
{ 
    char ch; //1 
    char ch2; //1 
    char ch3; //1 
    char ch4; //1 _4 
    char ch5; //1 
    short num; //2 
    char ch6; //1 _4 
    int num2; //4 _4 
}; 
#pragma pack(pop) 

int main() { 
    cout << sizeof(Foo); 
    return 0; 
} 

为什么输出是16字节?我认为它必须是12,因为:结构中字段对齐的奇怪行为

4 char = 4 bytes 
char + short + char = 4 bytes 
int = 4 bytes 

那么有人可以解释其余4个字节在哪里?

+0

“short”不仅在您的实施方面有两大优势,而且还具有对齐方式2. – Deduplicator

回答

2

这与对齐

总之,如果不同的值在内存中“对齐”,CPU更喜欢。例如,如果你正在处理一个标准的32位整数(4字节),大多数CPU会希望它驻留在一个可以被4除的存储器地址中。因此,内存地址10004将是OK,并且10008将会没问题,但10005不会。

大多数处理未对齐值的CPU会抛出异常并拒绝处理。然而,我们值得信赖的x86是一个例外,它会正确处理它 - 尽管速度要慢很多。在幕后,它将从内存中获取2个对齐的整数,然后旋转这些位以从它们中提取未对齐的整数。 (在其他平台上,我认为编译器会生成额外的指令来完成这项工作,但我不确定)所以你真的不希望发生这种情况,除非你有充足的理由。

这就是为什么你的编译器生成struct成员之间的一些填充字节 - 这样的short将是一个偶地址和int将是由4

#pragma pack可以是divisable地址影响这一点,但只有当你将其设置为小于4。你会得到我之前提到的对齐问题。

+1

“会正确处理它”吗?有时候,原子性可以被破坏。 – Deduplicator

+0

这是真的,没有想到这一点。 –

3

什么你得到的是在内存以下(| S是4字节边界):

|char char char char|char 1bytePadding short|char 3bytesPadding|int| 

short需要对齐到2字节边界,所以填充字节插入前面的后char,以便它可以。同样的,int必须是4字节对齐的,所以必须插入3个字节的填充字符以便可以。如果你正在优化空间的经验法则是从最大到最小的顺序排列成员。如果你这样做,它会是:

|int|short char char| char char char char| 

这将需要12bytes,如您所料。

1

这里是您的结构与偏移:在你的洗车台

struct Foo 
{ 
    0: char ch; //1 
    1: char ch2; //1 
    2: char ch3; //1 
    3: char ch4; //1 
    4: char ch5; //1 
    5: _padding //1 
    6: short num; //2 
    8: char ch6; //1 
    9: _padding //3 
    12: int num2; //4 
    16: 
}; 

作为short有2个字节对​​齐,有num之前加入使它是由2偏移可分1个字节的填充然后有3个字节ch6后以抵消num2除以4。