Можно ли найти выравнивание структурного типа, если известны выравнивания элементов конструкции?
Например. за:
struct S
{
a_t a;
b_t b;
c_t c[];
};
выравнивание S = max (alignment_of (a), alignment_of (b), alignment_of (c))?
Поискав в Интернете, я обнаружил, что «для структурированных типов наибольшее требование выравнивания любого из его элементов определяет выравнивание структуры» (в Что каждый программист должен знать о памяти), но я не смог найти ничего отдаленно похожего в стандарте (точнее, в последнем проекте).
Отредактировано: Большое спасибо за все ответы, особенно Роберту Гэмблу, который дал действительно хороший ответ на исходный вопрос, и другим участникам.
Короче:
Чтобы обеспечить требования к выравниванию элементов конструкции, выравнивание конструкции должно быть не менее строгим, чем выравнивание самого строгого члена.
Что касается определения выравнивания структуры, было представлено несколько вариантов, и после небольшого исследования я обнаружил:
- c++ std::tr1::alignment_of
- not standard yet, but close (technical report 1), should be in the C++0x
- the following restrictions are present in the latest draft: Precondition:T shall be a complete type, a reference type, or an array of
unknown bound, but shall not be a function type or (possibly
cv-qualified) void.
- this means that my presented use case with the C99 flexible array won't work (this is not that surprising since flexible arrays are not standard c++)
- в последнем проекте C ++ он определен в терминах нового ключевого слова - alignas (оно имеет такое же полное требование типа)
- на мой взгляд, если стандарт С ++ когда-либо будет поддерживать гибкие массивы C99, требование можно было бы ослабить (выравнивание структуры с гибким массивом не должно изменяться в зависимости от количества элементов массива)
- c++ boost::alignment_of
- mostly a tr1 replacement
- кажется специализированным для void и в этом случае возвращает 0 (это запрещено в черновике С ++)
- Примечание разработчиков: строго говоря, вы должны полагаться только на то, что значение ALIGNOF (T) кратно истинному выравниванию T, хотя на практике оно вычисляет правильное значение во всех известных нам случаях.
- Я не знаю, работает ли это с гибкими массивами, он должен (может не работать в целом, это разрешает компилятор, встроенный в мою платформу, поэтому я не знаю, как он будет себя вести в общем случае)
- Andrew Top presented a simple template solution for calculating the alignment in the answers
- this seems to be very close to what boost is doing (boost will additionally return the object size as the alignment if it is smaller than the calculated alignment as far as I can see) so probably the same notice applies
- это работает с гибкими массивами
- use Windbg.exe to find out the alignment of a symbol
- not compile time, compiler specific, didn't test it
- using offsetof on the anonymous structure containing the type
- see the answers, not reliable, not portable with c++ non-POD
- compiler intrinsics, eg. MSVC __alignof
- works with flexible arrays
- Ключевое слово alignof находится в последней версии проекта C ++
Если мы хотим использовать «стандартное» решение, мы ограничены std :: tr1 :: alignment_of, но это не сработает, если вы смешаете свой код c ++ с гибкими массивами c99.
На мой взгляд, есть только одно решение - использовать старую структуру:
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 и c ++ и их растущие различия вызывают сожаление.
Другой интересный вопрос (если мы не можем определить выравнивание структуры переносимым способом), каково самое строгое возможное требование выравнивания. Я могу найти несколько решений:
- boost (внутренне) использует объединение множества типов и использует на нем boost :: alignment_of
- the latest c++ draft contains std::aligned_storage
- The value of default-alignment shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len
- so the
std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value
should give us the maximum alignment - только черновик, еще не стандартный (если когда-либо),
tr1::aligned_storage
не имеет этого свойства
- so the
- The value of default-alignment shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len
Любые мысли по этому поводу также будут оценены.
Я временно снял отметку с принятого ответа, чтобы получить больше информации о новых подвопросах и внести в них свой вклад