Подтвердить что ты не робот

Как массив выравнивается в С++ по сравнению с типом?

Предположим, что у меня есть некоторый тип T, который должен быть N байт выровнен. Теперь я объявляю массив типа T:

T array[size];

Будет ли массив иметь те же требования к выравниванию, что и тип T, или у него будут какие-либо другие требования к выравниванию?

4b9b3361

Ответ 1

Да, требования к выравниванию должны быть одинаковыми. Очевидно, что массив из T должен быть выровнен по крайней мере строго как один T, иначе его первый член не будет правильно выровнен. Тот факт, что массив не может быть более строго выровнен, чем его тип элемента, следует из стандартного раздела 8.3.4, в котором говорится, что массивы являются смежными выделенными подобъектами элементов. Рассмотрим этот массив массивов:

T a[2][size];

Независимо от значения size, между двумя массивами a[0] и a[1] не может быть "дополнительного" заполнения, иначе это нарушает вынужденное распределение требований.

Эквивалентно, мы знаем, что (char*)&a[1] == (char*)&a[0] + sizeof(a[0]) и sizeof(a[0]) == sizeof(T[size]) == size * sizeof(T). Поскольку это выполняется для любого size, необходимо разместить массив T по любому адресу, который соответствующим образом выровнен для одного объекта T (с учетом адекватного адресного пространства).

Ответ 2

Полагаю, что требования к выравниванию массива будут идентичны требованиям элементов массива.

Очевидно, что начало массива должно быть выровнено по крайней мере так же строго, как требуется его первому элементу, поэтому его требования к выравниванию не могут быть менее строгими.

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

По индукции последующие элементы ОК, если первые два в порядке, поэтому придание массиву одинаковых требований к выравниванию, поскольку его элементы должны быть точными.

Цитата из спецификации была бы неплохой.

Ответ 3

Правила одинаковы, я полагаю, но интерпретация может быть запутанной.

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

Это может быть правдой в случае тривиального массива, но не для сложных сценариев.

Шаг массива может быть большим, чем размер элемента, т.е. между отдельными элементами могут быть прокладки.

Ниже приведен хороший пример

struct ThreeBytesWide {
    char a[3];
};

struct ThreeBytesWide myArray[100];

источник - шаг wikipedia

Каждый элемент массива ThreeBytesWide может быть выровнен с четырьмя байтовыми границами

Изменить: Как указано в комментариях, упоминание о наличии прокладок между отдельными элементами - это когда сам элемент имеет 3 байта и выровнен по четырем байтам.

Ответ 4

Массив объектов должен быть смежным, поэтому между объектами никогда не набивается, хотя дополнение может быть добавлено к концу объекта (создавая почти тот же эффект). Выделение элементов данных и массивов данных С++

#include <iostream>

__declspec(align(32)) 
struct Str1
{
   int a;
   char c;
}; 

template<typename T>
struct size
{
    T arr[10];
};


int main()
{
    size<Str1> b1;

    std::cout << sizeof(Str1) << std::endl; //  prints 32
    std::cout << sizeof(b1) << std::endl;   //  prints 320

    std::cin.ignore();
    return 0;
}

Литература: