2009-05-07 2 views
2

У меня два следующих структур:Почему короткий хранится как 4 байта в структуре в C?

Проблемы заключается в SizeOf (содержимое) возвращает 160. структура состоит из 11 трусов, 6, Интса 76 символов, 7 поплавков, 1 двойные, полностью добавляющих до 158 байт. Я подсчитал три раза, и разница между двумя байтами все еще остается.

typedef struct TIME_T { 
    short year,mon,day; 
    short hour,min,sec; 
} TIME; 

typedef struct { 
    int no; 
    char name[20]; 
    char Code[10]; 
    char DASType[10]; 
    short wlen; 
    float VLtd; 
    int samp; 
    int comp; 
    int locationID; 
    short TranMode; 
    char TranIns[12]; 
    short TimerMode; 
    char ClkType[12]; 
    float ClkErr; 
    float lat; 
    float lon; 
    float alt; 
    float azimuth,incident; 
    short weight; 
    short veloc; 
    int oritype; 
    char seismometer[12]; 
    double sens; 
    TIME start_time; 
    int record_samples; 
} Content; 

Я пишу небольшой кусок кода, чтобы напечатать положение каждой переменной в структуры, и вдруг я нахожу float wlen занимает 4 байта. Мой код выглядит следующим образом:

int main(void) 
{ 
    Content content; 
    printf("Sizeof Content: %d\n", sizeof(content)); 
    printf("Sizeof int content.no: %d\n", (int)&content.name - (int)&content.no); 
    printf("Sizeof char[20] content.name: %d\n", (int)&content.Code - (int)&content.name); 
    printf("Sizeof char[10] content.Code: %d\n", (int)&content.DASType - (int)&content.Code); 
    printf("Sizeof char[10] content.DASType: %d\n", (int)&content.wlen - (int)&content.DASType); 
    printf("Sizeof short content.wlen: %d\n", (int)&content.VLtd - (int)&content.wlen); 
    printf("Sizeof float content.VLtdL %d\n", (int)&content.samp - (int)&content.VLtd); 
    printf("Sizeof int content.samp: %d\n", (int)&content.comp - (int)&content.samp); 
    printf("Sizeof int content.comp: %d\n", (int)&content.locationID - (int)&content.comp); 
    printf("Sizeof int content.locationID: %d\n", (int)&content.TranMode - (int)&content.locationID); 
    printf("Sizeof short content.TranMode: %d\n", (int)&content.TranIns - (int)&content.TranMode); 
    printf("Sizeof char[12] content.TranIns: %d\n", (int)&content.TimerMode - (int)&content.TranIns); 
    printf("Sizeof short content.TimerMode: %d\n", (int)&content.ClkType - (int)&content.TimerMode); 
    printf("Sizeof char[12] content.ClkType: %d\n", (int)&content.ClkErr - (int)&content.ClkType); 
    printf("Sizeof float content.ClkErr: %d\n", (int)&content.lat - (int)&content.ClkErr); 
    printf("Sizeof float content.lat: %d\n", (int)&content.lon - (int)&content.lat); 
    printf("Sizeof floatcontent.lon: %d\n", (int)&content.alt - (int)&content.lon); 
    printf("Sizeof floatcontent.alt: %d\n", (int)&content.azimuth - (int)&content.alt); 
    printf("Sizeof floatcontent.azimuth: %d\n", (int)&content.incident - (int)&content.azimuth); 
    printf("Sizeof floatcontent.incident: %d\n", (int)&content.weight - (int)&content.incident); 
    printf("Sizeof short content.weight: %d\n", (int)&content.veloc - (int)&content.weight); 
    printf("Sizeof short content.veloc: %d\n", (int)&content.oritype - (int)&content.veloc); 
    printf("Sizeof int content.oritype: %d\n", (int)&content.seismometer - (int)&content.oritype); 
    printf("Sizeof char[12] content.seismometer: %d\n", (int)&content.sens - (int)&content.seismometer); 
    printf("Sizeof double content.sens: %d\n", (int)&content.start_time - (int)&content.sens); 
    printf("Sizeof TIME content.start_time: %d\n", (int)&content.record_samples - (int)&content.start_time); 
    printf("Sizeof int content.record_samples: %d\n", sizeof(content.record_samples)); 

    getchar(); 
    return 0; 
} 

Выход следующим образом:

Sizeof int content.no: 4 
Sizeof char[20] content.name: 20 
Sizeof char[10] content.Code: 10 
Sizeof char[10] content.DASType: 10 
Sizeof short content.wlen: 4 
**Sizeof float content.VLtdL 4** 
Sizeof int content.samp: 4 
Sizeof int content.comp: 4 
Sizeof int content.locationID: 4 
Sizeof short content.TranMode: 2 
Sizeof char[12] content.TranIns: 12 
Sizeof short content.TimerMode: 2 
Sizeof char[12] content.ClkType: 12 
Sizeof float content.ClkErr: 4 
Sizeof float content.lat: 4 
Sizeof floatcontent.lon: 4 
Sizeof floatcontent.alt: 4 
Sizeof floatcontent.azimuth: 4 
Sizeof floatcontent.incident: 4 
Sizeof short content.weight: 2 
Sizeof short content.veloc: 2 
Sizeof int content.oritype: 4 
Sizeof char[12] content.seismometer: 12 
Sizeof double content.sens: 8 
Sizeof TIME content.start_time: 12 
Sizeof int content.record_samples: 4 

Компилятор MSVC8, не UNICODE определен, никакой другой макрос определен. Это x86.

Я попытался скомпилировать тот же код в версии gcc версии 3.4.4, выход такой же. Sizeof short content.wlen: 4

Может кто-нибудь объяснить это мне?

Заранее спасибо.

EDIT: Спасибо, что ответили! У меня есть это сейчас.

+0

См. Здесь: http://stackoverflow.com/questions/713963/why-does-this-c-code-work для макроса, который вычисляет смещение элемента данных. Это было другое обсуждение, но макрос там работает ... –

+0

Вы не должны печатать размеры, возвращаемые sizeof, с% d. Тип si size_t, как правило, typedef unsigned int или unsigned long. Он зависит от формы, поэтому вы должны использовать его, прежде чем использовать формат типа: «% u», (unsigned int) sizeof (...) или «% lu \ n», (unsigned long) sizeof (...). Я считаю, что C99 добавил формат size_t, что делает вещи намного проще. –

ответ

11

Вы не можете работать размер структуры, просто добавляя размеры всех его компонентов - компилятор разрешается вставлять отступы между полями, и часто делает.

3

Вы не вычисляете размер полей, а «расстояние» между ними, поэтому я предполагаю, что вы видите выравнивание слов внутри структуры.

4

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

+0

Но обычно два смежных шорта в структуре будут упаковываться вместе, поскольку обычное правило используется для заполнения, чтобы использовать каждый элемент в своем «естественном» выравнивании. Конечно, вся проблема - это поведение, определяемое реализацией, поэтому ваш пробег будет значительно отличаться. – RBerteig

3

Вносит ли еще один недостаток в структуру, расширяющую размер или сохраняя его одинаково? Моя ставка - это тот же размер.

Оба компилятора работают над тем, чтобы ваша структура была построена на 8 байт (я полагаю), поэтому некоторое поле будет «расширено», чтобы занять дополнительную комнату; фактические операции над этим полем будут вести себя так, как если бы это был «правильный» размер.

+0

Вероятно, он останется того же размера, если и только если новый короткий вставлен рядом с элементом wlen, так что существующие байты заполнения могут быть повторно использованы. Вставка его почти в любое другое место, вероятно, вызовет еще два байта заполнения. – RBerteig

3

Элементы структуры часто выравниваются по 4-байтовым границам, если компилятор считает, что доступ будет более удобным таким образом. Аналогичное поведение наблюдается и с char.

Вы можете попытаться оптимизировать объем памяти вашей структуры, поставив шорты вместе, чтобы два последовательных шорта использовали одно 32-битное слово. Не забудьте дважды проверить результаты компиляции.

2

Согласно стандарту C, каждый родной тип памяти должен быть выровнен по своему размеру, но не имеет прямого отношения к вашей проблеме. То, что вы должны изучать, - это структурированная упаковка.

1

Посмотрите на pahole, для Poke-a-Hole.Это один из инструментов DWARF2, используемых для поиска дыр в структурах, отверстия - это промежутки между членами из-за правил выравнивания, которые могут быть использованы для новых записей структуры или реорганизованы для уменьшения размера.

Подробнее об этом в this LWN article автор программы, Arnaldo Carvalho de Melo.

В сети не так много обучающих программ, но this wiki-page at CERN несколько полезен.

2

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

Это не всегда так, но в большинстве случаев.

Смежные вопросы