оператор sizeof возвращает странный результат - PullRequest
1 голос
/ 13 сентября 2011

язык C с компилятором gcc

, если я создаю структуру наподобие

struct test {

    char item_1[2];
    char item_3[4];
    char item_4[2];
    char item_5[2];
    char item_6[4];

};

, и я делаю sizeof (проверка структуры), он возвращает 14 (байт).что является ожидаемым результатом.

, но если я сделаю

struct test {

    int16_t item_1;
    int32_t item_3;
    int16_t item_4;
    int16_t item_5;
    int32_t item_6;

};

sizeof (struct test) вернет что-то странное, например 44. Когда я отлаживаю с помощью gnu ddd, я могу видеть внутри структуры ивидим, что все выглядит нормально и все элементы имеют ожидаемое число байтов.

, так почему же оператор sizeof возвращает неожиданное значение?

Ответы [ 5 ]

3 голосов
/ 13 сентября 2011

Вы смешали 32/16 битных целых.

int16_t item_1[2]; // 2 * 2 = 4
int32_t item_3[4]; // 4 * 4 = 16
int16_t item_4[2]; // 2 * 2 = 4
int16_t item_5[2]; // 2 * 2 = 4
int32_t item_6[4]; // 4 * 4 = 16
                   // sum = 44
1 голос
/ 14 сентября 2011

Проблема выравнивания заключается в том, что современные 32-разрядные процессоры работают с 32-разрядными размерами слов на границах 32-разрядных адресов.Если 32-разрядное слово на 32-разрядной границе содержит 2 16-разрядных значения, это приводит к тому, что для получения правильных 16-разрядных значений требуются дополнительные инструкции (т. Е. Маскирование и сдвиг, так что правильные 16-разрядные значения - это все, что остается),Если 32-разрядное слово разделено на 32-разрядную границу, то для его извлечения требуется еще больше работы.

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

Если у вас есть требованиедля эффективного хранения структур (с затратами на производительность), тогда «#pragma pack» позволяет вам сжать членов пакета, но это приводит к более медленным программам.

http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html

http://www.cplusplus.com/forum/general/14659/

1 голос
/ 13 сентября 2011
Компилятор

требуется для вставки отступов между элементами структуры, чтобы выровнять каждый элемент по границе его типа и упорядочить элементы структуры как написано.Если вы упорядочите их так, чтобы самые большие элементы находились в начале определения структуры, они будут иметь одинаковый размер.Но так как вы пытаетесь сделать это с массивами char, я предполагаю, что у вас нет исходного определения структуры, и вы пытаетесь получить доступ к некоторым внешне определенным и созданным полям объекта.В этом случае я предлагаю вам либо получить правильные заголовки, либо использовать версию char [] и привести char * к тому типу, которым он действительно является.

1 голос
/ 13 сентября 2011

Компиляторы могут вставлять заполнение между элементами структуры или после последнего члена.Обычно это делается для удовлетворения требований выравнивания.Например, для объекта int32_t может потребоваться 4-байтовое выравнивание, поэтому компилятор вставляет 2 байта заполнения между первым и вторым членами.Детали будут различаться в зависимости от платформы.

0 голосов
/ 13 сентября 2011
struct test {
    int16_t item_1[2]; // 2 * 16 +
    int32_t item_3[4]; // 4 * 32 +
    int16_t item_4[2]; // 2 * 16 +
    int16_t item_5[2]; // 2 * 16 +
    int32_t item_6[4]; // 4 * 32
                       // total = 352
}; 

352 бита, разделенные на 8 (8 бит идут в один байт), составляют 44 байта.

...