C中的结构填充

时间:2009-08-01 01:45:36

标签: c optimization structure

我在C中读到了有关结构填充的内容: http://bytes.com/topic/c/answers/543879-what-structure-padding 并且在文章之后写了这段代码,应该打印出'struct pad'的大小,如16字节,'struct pad2'的大小应该是12.-我认为。 我使用gcc编译了这段代码,具有不同的优化级别,即使sizeof()运算符也给我两个16字节。 为什么?

这个信息对我来说是必要的,因为PS3机器的字节边界和对完整dma传输的利用很重要:

#include <stdio.h>
#include <stdlib.h>

struct pad
{
    char  c1;  // 1 byte
    short s1;  // 2 byte
    short s2;  // 2 byte
    char  c2;  // 1 byte
    long  l1;  // 4 byte
    char  c3;  // 1 byte
};

struct pad2
{
    long  l1;
    short s1;
    short s2;
    char  c1;
    char  c2;
    char  c3;
};

int main(void)
{
    struct pad P1;
    printf("%d\n", sizeof(P1));

    struct pad P2;
    printf("%d\n", sizeof(P2));

    return EXIT_SUCCESS;
}

6 个答案:

答案 0 :(得分:4)

有两种技巧可以用来解决这个问题

  1. 使用指令#pragma pack(1)然后#pragma pack(pop) 例如:

    #pragma pack(1)
    
    struct tight{           
       short element_1;       
       int *element_2;
    };
    #pragma pack(pop) 
    
  2. 要在编译期间检查两个结构的大小是否相同,请使用此技巧

    char voidstr[(sizeof(struct1)==sizeof(struct2)) - 1]; //it will return error at compile time if this fail
    

答案 1 :(得分:3)

你的结构每个都包含一个long,你的平台显然需要在一个四字节的边界上。该结构必须至少与其最对齐的成员对齐,因此它必须是4字节对齐的,并且结构的大小必须是其对齐的倍数,以防它进入数组。

需要额外填充才能使long对齐,因此4的最小倍数为16。

两条建议:

  • 您可以按

    计算字段l1的偏移量
     printf("Offset of field %s is %d\n", "l1", offsetof(struct pad, l1);
    

    要获得offsetof宏,您需要#include <stddef.h>(感谢caf!)。

  • 如果您想尽可能密集地打包数据,请使用unsigned char[4]代替longunsigned char[2]代替short,然后进行算术转换


编辑 :: sizeof(struct pad2) 12.您的代码有错误;结构P2声明为struct pad类型。试试这个:

#define xx(T) printf("sizeof(" #T ") == %d\n", sizeof(T))
  xx(struct pad);
  xx(struct pad2);

P.S。我绝对不应该在午夜后回答这些问题。

答案 2 :(得分:1)

在PS3上,不要猜。使用__attribute__((aligned (16)))或类似内容。它不仅保证结构的开始将在适当的边界上对齐(如果是全局的或静态的),它还将结构填充到指定对齐的倍数。

答案 3 :(得分:1)

您的代码未显示您的想法,因为P1和P2都被定义为struct pad的实例。从未使用过struct pad2。

如果我更改了P2的定义以使其成为struct pad2,那么gcc确实决定将其设置为12。

答案 4 :(得分:1)

struct pad P1;
printf("%d\n", sizeof(P1));

struct pad P2;
printf("%d\n", sizeof(P2));

P1和P2具有相同类型的“struct pad”,也许你想对P2使用“struct pad2”。

答案 5 :(得分:1)

所有CPU都希望内置数据类型(如int,float,char,double)以其自然边界存储在内存中,其长度为地址。因此,可以更快地访问内存中的数据。 。 例如, 如果声明了int,它应该在内存中以4的地址出现,如

int的大小是4个字节。

同样,对于double,它以8的倍数驻留在内存中。

如果内存正确对齐,CPU可以更快地运行并高效工作。

对于以下示例,我们假设:

Sizeof(int)= 4字节

Sizeof(float)= 4字节

Sizeof(char)= 1个字节

查找有关BoundsCheck

的详细信息