2016-08-12 3 views
2

В C++, кажется, что для всех целых типов (int, long long int, std::uint16_t, ...) и для типов с плавающей точкой, всегда sizeof(T) == alignof(T).Выравнивание и размер примитивных типов C++

Является ли этот компилятор/конкретный платформой или гарантированно будет правдой? Может ли быть платформа, где int32_t s не нужно выровнять по 32-битной границе (если они не перекрываются)?

+0

Компилятор/платформа. И да, есть * платформы, где 32-битное целое не требуется для размещения на 32-битном выравнивании. На самом деле, возможны платформы, где 'int32_t' даже не существует *. – DevSolar

+0

Единственным исключением из этого, что я видел в прошлом, является 'sizeof (double) == 8', но' alignof (double) == 4' (я считаю, что это распространено на 32-битных платформах, возможно, не так много сейчас, 64 бит становится нормой.) –

+1

@PaulR: Норма * для чего *? Вы знаете, что для каждого 64-битного настольного/серверного процессора есть * тысячи * встроенных 8/16 бит процессоров? – DevSolar

ответ

9

Для основных типов alignof(T) == sizeof(T) подходит для большинства современных ABI, но это не гарантируется. Стандарт C++ оставляет выравнивание в основном определяется реализацией, с учетом только этих ограничений (см [basic.align] и [basic.fundamental] в C++ 11):

  • alignof(T) <= sizeof(T). Это не является явным в стандарте, но между элементами массива никогда не было прокладки, поэтому независимо от выравнивания первого элемента T t[2] элемент второй не может иметь выравнивание больше sizeof(T), и, следовательно, это максимальное выравнивание для тип T. Обратите внимание, что выравнивание переменной может быть больше, например, если на нем используется alignas.

  • alignof(T) <= alignof(std::max_align_t), за исключением, возможно, в присутствии alignas. Определяется ли определение alignas «чрезмерное выравнивание» (с большей степенью детализации, чем max_align_t).

  • char, signed char и unsigned char все имеют одинаковое требование выравнивания (а именно: 1, так как sizeof(char) == 1 по определению).

  • Все неподписанные целые типы имеют то же требование выравнивания, что и соответствующий тип подписки.

  • wchar_t, char16_t и char32_t имеют одинаковые требования к выравниванию как их «базовых» целочисленных типов.

Там есть были исторического АБИС, где основные типы не были приведены в соответствие с их размерами. Одним из хорошо известных примеров является double и long double в исходной системе V ABI для 80386, которые были выровнены только с 4-батной детализацией, несмотря на то, что они были 8 и 12 байтами соответственно. Это было связано с тем, что указатель стека был гарантирован только согласованностью с 4-батовой степенью детализации, и больно согласовывать элементы в записи активации с большей степенью детализации, чем указатель стека.

В настоящее время эта же проблема выравнивания стека может иметь типы векторов; например, на x86-64 указатель стека гарантированно выравнивается с 16-байтовой границей, но теперь аппаратное обеспечение поддерживает до 512-bit (64-byte) vectors.

Это единственные контрпримеры, о которых я лично знаю.Однако меня не удивило бы узнать, что ABI для встроенной среды с ограниченным объемом памяти нет выравнивание для ничего (то есть alignof(T) == 1 для всех T). Процессору это не так сложно обрабатывать, как раньше, особенно если нет виртуализации памяти.


Fun факт: C++ стандарт не требуют реализации, чтобы стек вызова функции. Это требует поддержки для рекурсии, и есть что-то, называемое «раскручивание стека», которое происходит, когда выбрасываются исключения, но все тщательно написано так, чтобы вы могли реализовать его с помощью чего-то другого, кроме линейных стеков, с которыми мы все знакомы.

Смежные вопросы