我读过关于 C 中结构填充的文章: http://bytes.com/topic/c/answers/543879-what-struct-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;
}
有两个技巧可以用来克服这个问题
使用指令
#pragma pack(push, 1)
,然后使用 #pragma pack(pop)
。
示例:
#pragma pack(push, 1)
struct tight{
short element_1;
int *element_2;
};
#pragma pack(pop)
struct not_tight{
short element_1;
int *element_2;
};
要在编译期间检查两个结构的大小是否相同,请使用此技巧
char voidstr[(sizeof(struct1)==sizeof(struct2)) - 1]; //it will return error at compile time if this fail
您的结构每个都包含一个
long
,您的平台显然要求其位于四字节边界上。该结构必须至少与其最对齐的成员一样对齐,因此它必须是 4 字节对齐,并且结构的大小必须是其对齐的倍数,以防它进入数组。
需要额外的填充来使
long
对齐,因此 4 的最小倍数是 16。
两条建议:
您可以通过
计算字段的偏移量
l1
printf("Offset of field %s is %d\n", "l1", offsetof(struct pad, l1);
要获取
offsetof
宏,您需要 #include <stddef.h>
(感谢咖啡馆!)。如果要尽可能密集地打包数据,请使用
unsigned char[4]
代替 long
,使用 unsigned 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);
附注我绝对应该在午夜之后停止尝试回答这些问题。
在 PS3 上,不要猜测。使用
__attribute__((aligned (16)))
或类似的。它不仅保证结构的开头将在正确的边界上对齐(如果全局或静态),还将结构填充到指定对齐的倍数。
您的代码没有显示您认为的内容,因为 P1 和 P2 都被定义为 struct pad 的实例。 struct pad2 从未被使用过。
如果我更改 P2 的定义,使其成为 struct pad2,gcc 确实决定将其大小设为 12。
struct pad P1;
printf("%d\n", sizeof(P1));
struct pad P2;
printf("%d\n", sizeof(P2));
P1 和 P2 具有相同的类型“struct pad”,也许您想对 P2 使用“struct pad2”。
所有 CPU 都希望将内置数据类型(如 int、float、char、double)存储在内存中其自然边界、其长度地址处。因此,进行结构填充是为了更快地从内存访问数据。 例如, 如果声明了 int,它应该出现在内存中 4 倍地址处,如
int 的大小是 4 个字节。
类似地,对于 double,它以 8 的倍数驻留在内存中。
如果内存正确对齐,CPU 可以运行得更快并高效工作。
对于以下示例,我们假设:
Sizeof(int)=4 字节
Sizeof(float)=4字节
Sizeof(char)=1 字节
上查找详细信息