Размер 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 байтов.

Другие вопросы по тегам