我可以在不同的编译器上使用“pragma pack”来强制结构体具有不按其自然对齐方式进行对齐的字段。
这个过程是否递归的呢?也就是说,假设结构体typedef A包含typedef struct B的字段。如果使用一个pack pragma对A进行打包,那么会强制打包结构体B吗?
我可以在不同的编译器上使用“pragma pack”来强制结构体具有不按其自然对齐方式进行对齐的字段。
这个过程是否递归的呢?也就是说,假设结构体typedef A包含typedef struct B的字段。如果使用一个pack pragma对A进行打包,那么会强制打包结构体B吗?
希望你不要这么想!假设你有一个函数,它需要一个参数结构体A:
void fn( struct A x ) ;
然后一个包含结构体A成员的紧凑结构体B:
#pragma pack(1)
struct B
{
struct A a ;
}
struct A
{
int a;
char b;
int c ;
} ;
struct B
{
struct A d ;
} ;
#pragma pack(1)
struct C
{
struct A d ;
} ;
#pragma pack(1)
struct D
{
int a;
char b;
int c ;
} ;
#pragma pack(1)
struct E
{
struct D ;
} ;
int main()
{
int a = sizeof(struct A) ;
int b = sizeof(struct B) ;
int c = sizeof(struct C) ;
int d = sizeof(struct D) ;
int e = sizeof(struct E) ;
}
在调试器中检查main()函数中的a、b、c、d和e的值,结果如下:
struct C
的打包对其成员结构体A的大小没有影响。
不要使用。丑陋的非标准扩展的确切行为是您无法在未指定您所使用的平台/编译器的情况下提出问题的。如果您发现自己需要压缩结构体,那么最好找出代码存在的问题并加以修复。压缩结构体只是对破损代码的一种权宜之计,对于破损的根本原因没有任何作用。
#pragma packed
无法解决大小端依赖等问题。应该编写适当的序列化函数。
@user384706说,在除x86以外的任何系统上,读取和写入非对齐字段所需的额外代码量将比在结构体中浪费的几个字节要多得多-特别是如果您调整元素的顺序,使它们自然地对齐而无需填充要求。提示:alignof(type)
对于所有类型都会将sizeof(type)
除以其结果。 - R.. GitHub STOP HELPING ICE__attribute__ ((packed))
在Linux内核头文件中出现了3162次,在其他源代码中出现了444次。 - nmichaels根据Nathon的帖子,我在我的电脑上尝试了类似的事情:
#include <stdio.h>
#if defined PACK_FIRST || defined PACK_BOTH
#pragma pack(1)
#endif
struct inner {
char a;
double b;
};
#if defined PACK_SECOND || defined PACK_BOTH
#pragma pack(1)
#endif
struct outer {
char a;
struct inner b;
char c;
double d;
};
int main(void) {
printf("sizeof (char): %d (1, of course)\n", (int)sizeof (char));
printf("sizeof (double): %d\n", (int)sizeof (double));
printf("sizeof (inner): %d\n", (int)sizeof (struct inner));
printf("sizeof (outer): %d\n", (int)sizeof (struct outer));
return 0;
}
$ gcc 4128061.c $ ./a.out char类型的大小为:1(当然是1) double类型的大小为:8 inner结构体的大小为:16 outer结构体的大小为:40 $ gcc -DPACK_FIRST 4128061.c $ ./a.out char类型的大小为:1(当然是1) double类型的大小为:8 inner结构体的大小为:9 outer结构体的大小为:19 $ gcc -DPACK_SECOND 4128061.c $ ./a.out char类型的大小为:1(当然是1) double类型的大小为:8 inner结构体的大小为:16 outer结构体的大小为:26 $ gcc -DPACK_BOTH 4128061.c $ ./a.out char类型的大小为:1(当然是1) double类型的大小为:8 inner结构体的大小为:9 outer结构体的大小为:19
显然,我的gcc从#pragma
行出现的地方开始进行打包。
根据我手头的GCC版本,看起来是可以的:
#include <stdio.h>
typedef struct
{
char a;
int b;
}inner_t;
#pragma pack(1)
typedef struct
{
char a;
inner_t inner;
} outer_t;
int main()
{
outer_t outer;
outer.inner.a = 'a';
outer.inner.b = 0xABCDEF01;
printf ("outer.inner.a: %c\n", outer.inner.a);
return 0;
}
而且在printf处打断点,gdb会给我...
(gdb) x/5xw &outer
0x7fffffffe4b0: 0xffff61a0 0xcdef01ff 0x000000ab 0x00000000
0x7fffffffe4c0: 0x00000000
inner.b
没有按字对齐。因此,在小端64位机器上的GCC 4.4.5下,如果外部结构是紧凑的,则嵌套结构将被打包。对于那些不喜欢typedef的人,请原谅我。