2012-08-09 110 views
2
typedef struct structc_tag 
{ 
    char  c; 
    double  d; 
    int   s; 
} structc_t; 

我在博客中读取,这将取数据的24个字节:混乱在结构成员对齐

的sizeof(char)的+ 7字节的填充+的sizeof(双)+的sizeof(int)的+ 4字节填充= 1 + 7 + 8 + 4 + 4 = 24字节。

我的问题是为什么7字节的填充,为什么我们不能在那里使用3字节的填充,并利用接下来的8字节来加倍?最后4个字节需要什么?

+1

'double'实体应该对齐到可被8整除的地址,否则当试图从内存加载值时,FPU可能会变得不快乐。在这种情况下,必须发出非常慢的未对齐负载(并且某些平台根本不支持未对齐的访问)。在x64 CPU上的64位模式下尤其如此,其中数学主要使用SSE完成。最后四个字节用于保证在堆叠多个这样的结构时(例如,在一个'struct_t'数组中),正确对齐。 – 2012-08-09 17:41:21

+1

通常很难确切知道实际实现中结构或对象的大小,因为它在您使用的每个平台上都会发生变化。您通常只需依靠编译器尽其所能地完成必要的字段和填充以获得最佳性能。这就是为什么人们在检查对象使用的字节数时使用'sizeof()'的原因 - 即使是像int这样的基本类型。 – Pyrce 2012-08-09 17:43:17

+0

如果你愿意,只需根据它们的大小对字段进行排序,就你的情况而言,这可能对大多数平台有所帮助 – 2012-08-09 18:25:57

回答

3

你需要考虑,如果你分配这些结构的阵列malloc()了,会发生什么:

structc_t *p = malloc(2 * sizeof *p); 

考虑一个平台,让sizeof(double) == 8sizeof(int) == 4和所需的double对齐8 malloc()总是返回地址正确对齐用于存储任何C类型 - 因此在这种情况下,a将被8字节对齐。填充要求然后自然脱落:

  • 为了a[0].d为8字节对齐,因此必须有7个字节的填充a[0].c后;

  • 为了使a[1].d为8字节对齐,整个结构尺寸必须是8的倍数,因此在a[0].s之后必须有4个字节的填充。

如果重新排序struct从最大到最小:

typedef struct structc_tag 
{ 
    double  d; 
    int   s; 
    char  c; 
} structc_t; 

...那么唯一需要的填充是.c后3个字节,使结构尺寸8的倍数。这导致结构的总大小为16,而不是24.

2

它取决于平台,但它取决于double与哪个对齐。如果它对齐到8个字节,看起来是这种情况,3个字节的填充不会将其剪切。

如果double被对齐到4个字节,你会是正确的,将使用3个字节的填充。

+0

对于OP,有时可以通过使用杂注来覆盖默认对齐选项。例如对于gcc,使用#pragma pack(1)来使用1字节对齐,#pragma pack(4)等等。你必须看看你的编译器支持什么。请注意,未对齐的内存访问速度可能会比浪费空间慢得多,并让编译器使用目标机器的首选对齐方式。 – 2012-08-09 17:53:52