_Alignas для членов структуры с помощью clang и C11

У меня возникли проблемы с -Wpadded с использованием C11 и структур.

Я уже прочитал Выравнивание элементов структуры с помощью _Alignas и просмотрел документы clang и увидел, что он теперь поддерживается.

Кроме того, я использую очень новую версию clang, которую я недавно собрал из ствола.

$ clang --version
clang version 3.3 (trunk 175473)
Target: x86_64-unknown-linux-gnu
Thread model: posix

Проблема, с которой я сталкиваюсь, заключается в следующем:

#include <stdlib.h>
#include <stdalign.h>

struct foo{
   void* a;
   int b;
};

int main() {
   struct foo instance;

   instance.a = NULL;
   instance.b = 2;

   return 0;
}

Что бросает мне это предупреждение:

$ clang -Weverything -std=c11 t.c 
t.c:4:8: warning: padding size of 'struct foo' with 4 bytes to alignment boundary [-Wpadded]
struct foo{
       ^
1 warning generated.

Разве не для этого предназначено _Alignas? Я попытался поместить его перед объявлением члена int, например:

struct foo{
   void* a;
   _Alignas(void*) int b;
};

Но то же самое предупреждение остается. Я также пытался поместить _Alignas в разные места, но безрезультатно. Что мне здесь не хватает?

Я знаю, что могу просто проигнорировать это конкретное предупреждение, и я понимаю, почему отступы важны, поэтому меня не интересуют обходные пути или объяснения того, что такое отступы. Я хочу знать, как изменить мой C переносимым, совместимым со стандартами способом, чтобы предупреждение больше не выдавалось.


person Max DeLiso    schedule 22.02.2013    source источник
comment
Предупреждение сообщает вам, что к структуре было добавлено четыре байта заполнения, чтобы элемент void* был правильно выровнен в массиве (чтобы размер структуры был кратен требованию выравнивания void*). Сообщение компилятору о том, что член int должен быть выровнен как void*, не меняет этого, по-прежнему требуется четыре байта заполнения.   -  person Daniel Fischer    schedule 22.02.2013
comment
@DanielFischer, могу ли я успокоить это с помощью фиктивного битового поля?   -  person Max DeLiso    schedule 22.02.2013
comment
Я был бы крайне удивлен, если бы вы не смогли. Если вы добавите поле int dummy:26; или около того, естественный размер будет 8 + 4 + 4 байт. (На типичной 64-битной платформе с 32-битными ints)   -  person Daniel Fischer    schedule 22.02.2013
comment
@DanielFischer круто, это сработало, но с манекеном: 32. Нет ли более портативного способа статически определить это число, а затем добавить в поле молча, возможно, с помощью препроцессора?   -  person Max DeLiso    schedule 22.02.2013
comment
(выполнение этих тестов на AMD Opteron 6174)   -  person Max DeLiso    schedule 22.02.2013
comment
Портативный - волосатый. Вы можете определить, необходим ли манекен, чтобы отключить предупреждение на шаге конфигурации, но я не знаю, как вы могли бы найти размер void*, используя только препроцессор. Вы можете сделать это массивом struct foo { void* a; int b[(sizeof(void*) + sizeof(int) - 1) / sizeof(int)]; }; и использовать только b[0], но это тоже некрасиво.   -  person Daniel Fischer    schedule 22.02.2013
comment
Благодарю. я рассмотрю этот подход.   -  person Max DeLiso    schedule 22.02.2013


Ответы (1)


-Weverything печатает все диагностические сообщения, требуемые C, а также некоторые диагностические сообщения, не требуемые C. Диагностика, которая печатается здесь, не требуется C: ее цель информативна, и ваша программа уже строго соответствует. C говорит, что реализация может создавать дополнительные диагностические сообщения до тех пор, пока она не прервет трансляцию программы.

person ouah    schedule 22.02.2013
comment
Так какова мотивация для этой конкретной диагностики? Что я мог потенциально каким-то образом изменить структуру, чтобы, если бы у меня были ее массивы, не было бы проблем с производительностью, потому что структура была смещена в памяти? - person Max DeLiso; 22.02.2013
comment
Чтобы сообщить вам, что объект структуры может занимать больше байтов, чем вы могли ожидать? - person ouah; 22.02.2013