shipshape
shipshape

Reputation: 711

C struct padding

I can use pragma pack on various compilers to force structs to have fields which are not on their natural alignments.

Is this recursive - so suppose struct typedef A contains a field of typedef struct B. If use a pragma to pack A will this force struct B to be packed?

Upvotes: 3

Views: 3646

Answers (4)

Clifford
Clifford

Reputation: 93446

You have to hope not! Lets say you have a function that takes a parameter struct A:

void fn( struct A x ) ;

and then a packed struct B that has struct A as a member:

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

If you pass the member a of B to fn(), the function has no knowledge of the packing in this instance, and would fail.

Other answerer's results notwithstanding, I performed the following test on 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) ;
}

Inspection of a, b, c, d and e in main() in the debugger yield:

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

The packing of struct C has no effect on the size of its struct A member.

Upvotes: 6

pmg
pmg

Reputation: 108968

Folowing Nathon's post, I tried about the same thing on my computer:

#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

Apparently my gcc packs from the point where the #pragma line appears.

Upvotes: 4

nmichaels
nmichaels

Reputation: 50943

For the version of GCC I have handy, it looks like yes:

#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;
}

And gdb breaking on the printf gives me...

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

inner.b is not word aligned. So under GCC 4.4.5 on a little endian 64-bit machine, nested structures are packed if the outer structure is packed. Pardon my typedefs, those of you who don't like them.

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215193

Just don't. The exact behavior of an ugly nonstandard extension is not something you can even ask questions about without specifying an exact platform/compiler you're working with. If you find yourself needing packed structs, you'd be better to figure out why your code is broken and fix it. Packed structs are a band-aid for broken code that do nothing to fix the root cause of the brokenness.

Upvotes: 5

Related Questions