Размер 64-битной структуры Windows зависит от типа данных?
У меня есть две разные структуры данных, которые в принципе должны иметь одинаковый размер, и мне интересно, почему они этого не делают.
struct pix1 {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
unsigned char y[2];
};
struct pix2 {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
unsigned short y;
};
Затем я сгруппировал четыре из этих пикселей вместе, как таковой:
struct pix4 {
pix1 pixels[4]; // or pix2 pixels[4]
unsigned char mask;
};
... но оказывается, что размер такой группировки изменяется, в зависимости от размера (pix4), в зависимости от того, использую ли я pix1 или pix2. Размер sizeof(pix1) == sizeof(pix2), поэтому я не понимаю, почему группировка квартетов пикселей меняет размер. Я забочусь, потому что легче писать программы с коротким, чем с двумя неподписанными символами, но это стоит мне 0,25 байта на пиксель.
Я не уверен, специфична ли эта архитектура, так как я не тестировал другие типы машин. Может ли это быть выравнивание? Это то, что мне нужно беспокоиться, или я могу приступить к короткой реализации?
Заранее благодарны за Вашу помощь.
3 ответа
Размер структур одинаков, но требования к их выравниванию разные.
Выравнивание структуры является максимумом выравнивания всех ее членов. Так pix1
имеет выравнивание 1, потому что он имеет только символы, но pix2
имеет выравнивание 2 от короткого члена. Выравнивание pix4
затем получает выравнивание от pixels
член, так что это 1 в первом и 2 во втором случае.
Теперь, чтобы убедиться, что все элементы массива правильно выровнены, размер структуры округляется до следующего кратного его выравнивания. В обоих случаях размер pixels
24, но есть 1 байт mask
, В первом случае выравнивание равно 1, поэтому число 25 кратно sizeof(pix4)
25, но во втором выравнивание 2, так sizeof(pix4)
должно быть округлено до следующего четного числа, 26.
Это одинаково на всех платформах.
Да, это связано с выравниванием. Компилятор хочет выровнять переменные по естественным границам, поэтому короткий будет выровнен по 16 бит (2 байта). И, следовательно, структура, которая содержит короткое замыкание, также будет выровнена по 16-битной границе.
Тот же эффект на 32-битной Linux.
Это связано с отступами для выравнивания.
Если вы используете struct pix1
, у вас есть только символы и, следовательно, struct pix4
можно оставить как есть. Но если вы используете struct pix2
коротко. Таким образом, вся структура должна быть выровнена, что даже в массиве struct pix4
каждый элемент выровнен для чистого доступа к y
,
Более многословно: A strict pix4
массив с 2 элементами будет иметь такую форму:
+----- [0] -----+++----- [1] -----+
First version: rgbayyrgbayyrgbayyrgbayyMrgbayyrgbayyrgbayyrgbayyM
Second version: rgbayyrgbayyrgbayyrgbayyM rgbayyrgbayyrgbayyrgbayyM
---------25--------------+ <- +1
Зачем? Поскольку ---
Часть ed составляет 25 байтов, что является нечетным числом. Это не проблема для первой версии - 2-й элемент может успешно начинаться с нечетного адреса - но для 2-й версии. Там yy всегда должен быть на четном (выровненном) адресе, поэтому struct pix4
сделано 26 байтов.