Упаковка структуры с использованием __attribute__((__packed__)) в GNU GCC

Мы знаем, что _attribute__((__packed__)) означает (скорее всего) «не вставлять отступы, чтобы ускорить работу», а также может означать «не вставлять никаких выравниваний, чтобы сохранить выравнивание».

struct structure2
{
   int id1 __attribute__((__packed__));
   char name __attribute__((__packed__));
   int id2 __attribute__((__packed__));
   char c __attribute__((__packed__));
   float percentage __attribute__((__packed__));
};
struct structure2 b;
printf("   \n\nsize of structure2 in bytes : %d\n", sizeof(b));// output = 20

Почему не удаляются все отступы (выход = 14)?


person Animesh Kumar Paul    schedule 04.01.2016    source источник
comment
Пожалуйста, всегда прочитайте документацию перед использованием расширения поставщика. В нем четко сказано, что атрибут может быть присоединен только к типам struct, union и enum.   -  person Kerrek SB    schedule 04.01.2016
comment
Вы хотите, чтобы были упакованы struct, а не отдельные поля (которые уже упакованы, поскольку они являются скалярными типами).   -  person too honest for this site    schedule 04.01.2016
comment
Я видел этот тип структуры на сайте grok2.tripod.com/structure_packing.html.   -  person Animesh Kumar Paul    schedule 04.01.2016


Ответы (2)


Пытаться:

struct __attribute__((__packed__)) structure2
{  //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   int id1;
   char name;
   int id2;
   char c;
   float percentage;
};

Нет смысла упаковывать одно поле. Как вы сами сказали, заполнение связано с отношением между полями, поэтому атрибут принадлежит самой структуре, а не ее полям.

person Kerrek SB    schedule 04.01.2016
comment
@dragosht, struct __attribute__((__packed__)) structure2, все в порядке, но на выходе все равно 20 - person Animesh Kumar Paul; 04.01.2016
comment
@AnimeshKumarPaul: не могу воспроизвести, у меня работает. - person Kerrek SB; 04.01.2016
comment
@AnimeshKumarPaul Какой версией gcc вы компилируете? - person dragosht; 04.01.2016
comment
@dragosht, версия gcc 4.7.1 (tdm-1) - person Animesh Kumar Paul; 04.01.2016
comment
__attribute__((packed)) также может быть помещен между закрывающими } и ;, таким образом: struct structure2 { ... } __attribute__((packed)) ; - person Clifford; 04.01.2016
comment
@AnimeshKumarPaul: проверьте Wandbox, даже в GCC 4.7.3 это работает, как и ожидалось. - person Kerrek SB; 04.01.2016
comment
@AnimeshKumarPaul: Для какой платформы это? Wandbox работает только на x86-64, и доступность упаковки может зависеть от аппаратного обеспечения. Могут быть архитектуры, на которых не могут быть реализованы упакованные макеты. - person Kerrek SB; 04.01.2016

Мне кажется баг...

Используя ваш компилятор ((tdm64-1) 4.7.1) и соответствующий атрибут packed, я получаю такое же поведение - см. разборку main ниже:

0000000000401500 <main>:
  401500:       55                      push   %rbp
  401501:       48 89 e5                mov    %rsp,%rbp
  401504:       48 83 ec 40             sub    $0x40,%rsp
  401508:       e8 a3 11 00 00          callq  4026b0 <__main>
  40150d:       ba 14 00 00 00          mov    $0x14,%edx <-- your sizeof here
  401512:       48 8d 0d 07 7b 00 00    lea    0x7b07(%rip),%rcx        # 409020 <.rdata>
  401519:       e8 b2 60 00 00          callq  4075d0 <printf>
  40151e:       b8 00 00 00 00          mov    $0x0,%eax
  401523:       48 83 c4 40             add    $0x40,%rsp
  401527:       5d                      pop    %rbp
  401528:       c3                      retq
  ...

Используя gcc (GCC) 4.9.3 в cygwin, я получаю:

00000001004010e0 <main>:
   1004010e0:   55                      push   %rbp
   1004010e1:   48 89 e5                mov    %rsp,%rbp
   1004010e4:   48 83 ec 30             sub    $0x30,%rsp
   1004010e8:   e8 33 00 00 00          callq  100401120 <__main>
   1004010ed:   ba 0e 00 00 00          mov    $0xe,%edx <-- your sizeof here
   1004010f2:   48 8d 0d 37 1f 00 00    lea    0x1f37(%rip),%rcx        # 100403030 <.rdata>
   1004010f9:   e8 32 00 00 00          callq  100401130 <printf>
   1004010fe:   b8 00 00 00 00          mov    $0x0,%eax
   100401103:   48 83 c4 30             add    $0x30,%rsp
   100401107:   5d                      pop    %rbp
   100401108:   c3                      retq
   ...

Итак, по какой-то причине используемый вами компилятор игнорирует атрибут. Однако вы можете попробовать более новую версию - кажется, что самая новая версия этого TDM-GCC - 5.1.0.

person dragosht    schedule 04.01.2016
comment
Поддерживает ли глючный компилятор также синтаксис OP для каждого поля? Недавний GCC этого не делает (он не разрешает атрибут, скажем, в поле char). - person Kerrek SB; 04.01.2016
comment
Ага. Я только что увидел, что ОП копирует код из внешнего документа, поэтому мне было интересно, поддерживался ли он когда-то GCC. Впрочем, неважно. - person Kerrek SB; 04.01.2016