Влияет ли 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
,
Так что я в замешательстве. Кто может сказать мне причину?
3 ответа
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) к этому элементу данных), после него необходимо добавить заполнение.
На самом деле, в стандартном документе C ++ я не нашел упоминания о влиянии на
alignas()
от размера объекта ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf ), но согласно моему эксперименту (по крайней мере, на g ++ 8.3, Amd64) это действительно влияет на это .
struct UnalignedStruct {
int a;
int b;
char c;
};
struct alignas(512) AlignedStruct {
int a;
int b;
char c;
};
int main() {
std::cout << sizeof(UnalignedStruct) << std::endl;
std::cout << sizeof(AlignedStruct) << std::endl;
}
выход
12
512
Как кажется, сказывается
sizeof()
стоимость.
Требование выравнивания влияет на весь объект, для которого оно указано, - в данном случае массив [1024]
чар. Таким образом, весь массив выравнивается до 8 байтов, как будто он был сдвинут на несколько байтов в памяти в целом, но его размер остается 1024 байта.