C struct padding - PullRequest
       5

C struct padding

3 голосов
/ 09 ноября 2010

Я могу использовать прагма-пакет на различных компиляторах, чтобы структуры имели поля, которые не имеют естественного выравнивания.

Является ли это рекурсивным - предположим, что struct typedef A содержит поле typedef struct B. Если для упаковки A используется прагма, будет ли принудительно упаковываться struct B?

Ответы [ 4 ]

5 голосов
/ 09 ноября 2010

Надеюсь, что нет! Допустим, у вас есть функция, которая принимает параметр struct A:

void fn( struct A x ) ;

и затем упакованная структура B, которая имеет структуру A в качестве члена:

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

Если вы передадите элемент a из B функции 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) ;
}

Проверка a, b, c, d и e в main () в отладчике дает:

  • а = 12
  • b = 12
  • с = 12
  • d = 9
  • е = 9

Упаковка struct C не влияет на размер элемента struct A.

5 голосов
/ 09 ноября 2010

Только не надо. Точное поведение некрасивого нестандартного расширения - это не то, о чем вы даже можете задать вопросы, не указав конкретную платформу / компилятор, с которым вы работаете. Если вам понадобятся упакованные структуры, вам лучше выяснить, почему ваш код не работает, и исправить это. Упакованные структуры являются бинтом-помощником для неработающего кода, который ничего не делает для устранения первопричины взлома.

4 голосов
/ 09 ноября 2010

Следуя посту Натона, я попробовал примерно то же самое на моем компьютере:

#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.

1 голос
/ 09 ноября 2010

Для версии 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-разрядном компьютере с прямым порядком байтов вложенные структуры упаковываются, если упаковывается внешняя структура.Прошу прощения, мои typedefs, те из вас, кто не любит их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...