Можно ли найти выравнивание типа структуры, если известны выравнивания элементов структуры?
Eg. для:
struct S
{
a_t a;
b_t b;
c_t c[];
};
- выравнивание S = max (alignment_of (a), alignment_of (b), alignment_of (c))?
Поиск в Интернете Я обнаружил, что "для структурированных типов наибольшее требование выравнивания любого из его элементов определяет выравнивание структуры" (в Что каждый программист должен Know About Memory), но я не смог найти ничего подобного в стандарте (последний вариант более точно).
Отредактировано: Большое спасибо за все ответы, особенно Роберту Гэмблу, который дал действительно хороший ответ на исходный вопрос и другие, кто внес вклад.
Короче:
Чтобы обеспечить требования к выравниванию для элементов структуры, выравнивание структуры должно быть не менее строгим, чем выравнивание его самого строгого члена.
Что касается определения выравнивания структуры, было представлено несколько вариантов и с небольшим количеством исследований это то, что я нашел:
- С++ std:: tr1:: alignment_of
- пока не стандартный, но закрыть (технический отчет 1), должен быть в С++ 0x
- в последнем проекте представлены следующие ограничения: Предварительное условие: T должен быть полным типом, ссылочным типом или массивом
неизвестная граница, но не должна быть функциональным типом или (возможно,
cv-qualified) void.
- это означает, что мой представленный прецедент с гибким массивом C99 не будет работать (это не удивительно, поскольку гибкие массивы не являются стандартными С++).
- в последнем проекте С++ определяется в терминах нового ключевого слова - alignas (у этого есть то же полное требование типа)
- на мой взгляд, должен ли стандарт С++ поддерживать гибкие массивы C99, требование может быть ослаблено (выравнивание структуры с гибким массивом не должно меняться в зависимости от количества элементов массива)
- С++ boost:: alignment_of
- в основном замена tr1
- кажется специализированным для void и возвращает 0 в этом случае (это запрещено в черновик С++)
- Примечание разработчиков: строго говоря, вы должны полагаться только на значение ALIGNOF (T), кратное истинному выравниванию T, хотя на практике оно вычисляет правильное значение во всех случаях, о которых мы знаем.
- Я не знаю, работает ли это с гибкими массивами, он должен (возможно, не работать вообще, это разрешает компилятор, основанный на моей платформе, поэтому я не знаю, как он будет вести себя в общем случае)
- Andrew Top представил простое шаблонное решение для расчета выравнивания в ответах
- это кажется очень близким к тому, что делает boost (boost будет дополнительно возвращать размер объекта в качестве выравнивания, если он меньше расчетного выравнивания, насколько я могу видеть), поэтому, возможно, такое же уведомление применяется
- это работает с гибкими массивами
- используйте Windbg.exe, чтобы узнать выравнивание символа
- не компилировать время, компилятор специфичен, не тестировал его
- с использованием offsetof в анонимной структуре, содержащей тип
- см. ответы, не надежные, не портативные с С++ non-POD
- встроенные функции компилятора, например. MSVC __alignof
- работает с гибкими массивами.
- ключевое слово alignof находится в последней версии С++
Если мы хотим использовать "стандартное" решение, мы ограничены std:: tr1:: alignment_of, но это не сработает, если вы смешаете свой код С++ с гибкими массивами c99.
Как я вижу, есть только одно решение - используйте старый struct hack:
struct S
{
a_t a;
b_t b;
c_t c[1]; // "has" more than 1 member, strictly speaking this is undefined behavior in both c and c++ when used this way
};
Расходящиеся стандарты c и С++ и их растущие различия являются неудачными в этом случае (и в каждом другом случае).
Еще один интересный вопрос: (если мы не можем найти выравнивание структуры в переносном режиме), то это самое строжайшее требование выравнивания. Есть несколько решений, которые я могу найти:
- boost (внутренне) использует объединение различных типов и использует boost:: alignment_of на нем
- последний проект С++ содержит std:: aligned_storage
- Значение выравнивания по умолчанию должно быть самым строгим требованием выравнивания для любого типа объекта С++, размер которого не больше, чем Len
- поэтому
std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value
должен дать нам максимальное выравнивание - только черновик (если он когда-либо),
tr1::aligned_storage
не имеет этого свойства
- поэтому
- Значение выравнивания по умолчанию должно быть самым строгим требованием выравнивания для любого типа объекта С++, размер которого не больше, чем Len
Любые мысли об этом также будут оценены.
Я временно отключил принятый ответ, чтобы получить больше видимости и ввода новых подзапросов