0

我已经阅读了有关 C 中结构填充的内容:http: //bytes.com/topic/c/answers/543879-what-structure-padding 并在文章之后写了这段代码,应该打印出“结构垫”的大小像 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;
}
4

6 回答 6

4

您的每个结构都包含一个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);

PS 我绝对应该在午夜之后停止尝试回答 SO 问题。

于 2009-08-01T01:52:05.580 回答
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
    
于 2009-08-01T18:29:55.817 回答
1

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

于 2009-08-01T02:17:04.927 回答
1

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

如果我将 P2 的定义更改为 struct pad2,gcc 确实决定将其设置为 12。

于 2009-08-01T02:24:30.940 回答
1
struct pad P1;
printf("%d\n", sizeof(P1));

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

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

于 2009-08-01T02:27:37.113 回答
1

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

int 的大小为 4 字节。

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

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

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

Sizeof(int)=4 字节

Sizeof(float)=4 字节

Sizeof(char)=1 字节

在BoundsCheck上查找详细信息

于 2010-06-29T18:27:11.277 回答