C struct padding

时间:2010-11-08 21:06:04

标签: c

我可以在各种编译器上使用pragma pack来强制结构具有不在其自然对齐上的字段。

这是递归的 - 所以假设struct typedef A包含typedef struct B的字段。如果使用pragma打包A会强制结构B被打包吗?

4 个答案:

答案 0 :(得分:5)

只是不要。丑陋的非标准扩展的确切行为不是你甚至可以在没有指定你正在使用的确切平台/编译器的情况下提出问题。如果您发现自己需要打包结构,那么最好弄明白为什么代码被破坏并修复它。打包的结构是破坏代码的创可贴,无法解决破坏的根本原因。

答案 1 :(得分:5)

你不得不希望!假设你有一个带参数struct A:

的函数
void fn( struct A x ) ;

然后是一个包含struct A作为成员的压缩结构B:

#pragma pack(1)
struct B
{
    struct A a ; 
}

如果将B的成员a传递给fn(),则该函数不知道此实例中的打包,并且会失败。

尽管有其他回答者的结果,我在VC ++ 2010上进行了以下测试:

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:

  • a = 12
  • b = 12
  • c = 12
  • d = 9
  • e = 9

struct C的打包对其struct A成员的大小没有影响。

答案 2 :(得分:4)

在Nathan的帖子之后,我在我的电脑上尝试了同样的事情:

#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 
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 16
sizeof (outer): 40
$ gcc -DPACK_FIRST 4128061.c
$ ./a.out 
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 9
sizeof (outer): 19
$ gcc -DPACK_SECOND 4128061.c
$ ./a.out 
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 16
sizeof (outer): 26
$ gcc -DPACK_BOTH 4128061.c
$ ./a.out 
sizeof (char): 1 (1, of course)
sizeof (double): 8
sizeof (inner): 9
sizeof (outer): 19

显然我的gcc打包从#pragma行出现。

答案 3 :(得分:1)

对于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;
}

gdb打破printf给了我......

(gdb) x/5xw &outer
0x7fffffffe4b0: 0xffff61a0      0xcdef01ff      0x000000ab      0x00000000
0x7fffffffe4c0: 0x00000000

inner.b不是单词对齐的。因此,在GCC 4.4.5的小端64位机器上,如果外部结构被打包,则打包嵌套结构。原谅我的typedef,那些不喜欢它们的人。