Соответствует ли alignas значение sizeof?

#include <iostream>
using namespace std;

int main()
{
    alignas(double) unsigned char c[1024];   // array of characters, suitably aligned for doubles
    alignas(16) char d[100];            // align on 16 byte boundary
    cout<<sizeof(c)<<endl;
    cout<<sizeof(d)<<endl;
    constexpr int n = alignof(int);     // ints are aligned on n byte boundarie
    cout<<n<<endl;
}

Вот код, для alignas(double) unsigned char c[1024];, это означает, что c должен быть выровнен по значению double, а double - 8. Поэтому я думаю, что sizeof(c) должен быть 1024*8 байтами, но консольный вывод 1024.

Так что я смущен. Кто может сказать мне причину?

Ответы

Ответ 1

Ключевое слово alignas может использоваться для диктовки требований к выравниванию. alignas(double), например, заставляет переменную иметь те же требования к выравниванию, что и double. На моей платформе это будет означать, что переменная выровнена на 8 байтовых границах.

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

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

#include <iostream>
#include <cstddef>

struct Test
{
    char a;
    alignas(double) char b;
};

int main(int argc, char* argv[])
{
    Test test;
    std::cout << "Size of Struct: " << sizeof(Test) << std::endl;
    std::cout << "Size of 'a': " << sizeof(test.a) << std::endl;
    std::cout << "Size of 'b': " << sizeof(test.b) << std::endl;
    std::cout << "Offset of 'a': " << (int)offsetof(struct Test, a) << std::endl;
    std::cout << "Offset of 'b': " << (int)offsetof(struct Test, b) << std::endl;
    return 0;
}

Вывод:

Size of Struct: 16
Size of 'a': 1
Size of 'b': 1
Offset of 'a': 0
Offset of 'b': 8

Размер этой структуры составляет 16 байт на моей платформе, хотя оба элемента имеют только 1 байт в каждом размере. Таким образом, b не стало больше из-за требования к выравниванию, но после a есть дополнительное дополнение. Вы можете увидеть это, посмотрев размер и смещение отдельных членов. a имеет размер всего 1 байт, но b, из-за наших требований к выравниванию, начинается после 8-байтового смещения.

И размер структуры должен быть кратным его выравниванию, иначе массивы не работают. Поэтому, если вы установили требование выравнивания, которое должно было начинаться больше, чем целая структура (например, структура, содержащая только один короткий, и вы применяете alignas (double) к этому элементу данных), после этого должно быть добавлено дополнение.

Ответ 2

Требование выравнивания влияет на весь объект, для которого он указан, - в этом случае массив [1024] от char. Таким образом, весь массив получает значение 8 байтов, например, он смещается на несколько байтов в памяти в целом, но его размер остается 1024 байта.