Есть ли гарантия относительно размера класса, содержащего массив?

Данный:

template <int N>
struct val2size
{
    char placeholder[N];
};

Есть ли гарантия, что sizeof(val2size<N>) == N?


person uj2    schedule 05.09.2010    source источник
comment
То же самое можно получить от boost::array<char,N> или C ++ 0x std::array.   -  person Potatoswatter    schedule 06.09.2010
comment
Обратите внимание, что в большинстве ответов предполагалось, что вы говорите ТОЛЬКО о содержащем массиве, а не о других членах. Чем больше членов, тем больше вероятность того, что размер объекта превосходит сумму их индивидуальных размеров.   -  person Matthieu M.    schedule 06.09.2010


Ответы (4)


Единственная гарантия заключается в том, что

sizeof(val2size<N>) >= N

В конце структуры может быть безымянный отступ. Не думаю, что там будет безымянный отступ, но это возможно.

person James McNellis    schedule 05.09.2010
comment
Спасибо, я так подозревал. Предполагая, что практически на любой платформе sizeof(int) является естественным размером слова (хотя не уверен, что он определен таким образом), есть ли шанс для заполнения в случае, если это был массив int (с размером тогда N * sizeof(int))? - person uj2; 06.09.2010
comment
@ uj2: из AMD64 ABI x86-64.org/documentation/abi.pdf Массив использует то же выравнивание, что и его элементы, за исключением того, что локальная или глобальная переменная массива длиной не менее 16 байтов или переменная массива переменной длины C99 всегда имеет выравнивание не менее 16 байтов. Похоже, что массив подобъект будет освобожден от этого, но это достаточно просто, чтобы попробовать и увидеть. - person Potatoswatter; 06.09.2010
comment
В более общем плане, для другого ABI, включая векторные типы, было бы разумно расширить такое требование. - person Potatoswatter; 06.09.2010

Нет, Джеймс покрывает это. Но вы можете получить то, что хотите:

template <std::size_t N> // not an int, a negative value doesn't make sense
struct value_to_size
{
    typedef char type[N];
};

sizeof(value_to_size<N>::type) гарантированно будет N. (Этот трюк можно использовать для компиляции утилита -time size-of array.)

person GManNickG    schedule 05.09.2010
comment
@ uj2: Ничто в вашем вопросе ничего не говорит о типе возвращаемого значения. Почему бы не задать реальный вопрос о реальной проблеме, а не о шаге? - person GManNickG; 06.09.2010
comment
@ uj2: ничто не мешает вам использовать val2size в качестве возвращаемого типа. Но чего вы пытаетесь достичь, приравнивая тип к определенному значению? Проверки времени компиляции? - person dirkgently; 06.09.2010
comment
Вы правы. Это частичный вопрос, хотя я чувствовал, что его следует задать отдельно. Комментарий, вероятно, не был слишком полезным, это правильный ответ. - person uj2; 06.09.2010

По умолчанию нет гарантии из-за возможного заполнения. Однако многие компиляторы (по крайней мере, VC ++ и gcc) позволяют устанавливать выравнивание структур с помощью прагмы, например:

#pragma pack(push, 1)
template <int N>
struct val2size
{
    char placeholder[N];
};
#pragma pack(pop)

Установка выравнивания на 1 по существу предотвращает любые дополнительные отступы в конце структуры.

person casablanca    schedule 05.09.2010
comment
Допустимые значения: 1, 2, 4, 8 и 16. Выравнивание элемента будет по границе, которая либо кратна n, либо кратна размеру элемента, в зависимости от того, что меньше. Из msdn.microsoft.com/en-us /library/2e70t5y1%28VS.80%29.aspx - person dirkgently; 06.09.2010
comment
Спасибо, что указали на это, на самом деле я имел в виду 1. Я давно не использовал его. - person casablanca; 06.09.2010

Это зависит от размера N на самом деле и от того, может ли этот размер N char соответствовать мировому уровню. Если память символьного массива выровнена по миру (4 байта для 32-битного и 8-байтового для 64-битного), тогда вы получите sizeof == N, или, если нет, то он добавит отступ, чтобы выделить память для выравнивания по миру и в этом случае это будет> = N.

person Anil Vishnoi    schedule 05.09.2010