2014-11-25 2 views
1

Я читал этот ответ: C struct memory layout? и было интересно узнать, почему:Почему эта структура не выравнивается должным образом?

struct ST 
{ 
    long long ll; 
    char ch2; 
    char ch1; 
    short s; 
    int i; 
}; 

до сих пор является размер 24 байт, а не 16. Я Ожидал 2 * символ + короткий + ИНТ, чтобы вписаться в 8 байт. Почему это так?

EDIT:

Извините за сумбур, я бегу на 64-битной системе (Debian) НКУ (Debian 4.4.5-8) 4.4.5. Я уже знаю его из-за заполнения. Мой вопрос был почему? Один из ответов предлагает:

char = 1 byte 
char = 1 byte 
short = 1 byte (why is this 1 and not 2?) 
* padding of 5 bytes 

Мой вопрос, почему это набивка здесь ... почему бы не просто положи в INT сразу после короткого, он все равно будет вписываться в 8 байт.

+2

Вы проверяете это на 64-битной системе? Вы также можете проверить смещения членов, чтобы узнать, где они находятся, используя макрос ['offsetof'] (http://en.cppreference.com/w/c/types/offsetof). Что касается вашей формулировки в названии, выравнивание, выбранное компилятором, безусловно, «правильно» для вашей системы. –

+0

Из-за обивки. – bitcell

+3

Что такое «64-разрядная система»? Какова аппаратная архитектура? В x86_64 ABI размер этой структуры должен быть 16 байтов. Я проверял Ubuntu, MacOS, OpenBSD и Centos. Это не зависит от компилятора, поэтому есть что-то очень неправильное с вашими флагами компиляции, или вы работаете на альфе или что-то странное. – Art

ответ

1

Простой ответ: это не 24 байта. Или вы работаете на 64-битном порту s390 Linux, для которого я не смог найти документацию по ABI. Каждое другое 64-разрядное оборудование, на котором может работать Debian, будет иметь размер этой структуры как 16 байт.

я откопал в документации ABI для связки различных АБИС процессора и все они имеют более или менее эта формулировка (кажется, все они копировали друг от друга):

Структуры и объединения предположим, выравнивание их наиболее строго выровненного компонента. Каждому члену присваивается самое низкое доступное смещение с соответствующим выравниванием. Размер любого объекта всегда кратен выравниванию объекта.

И все архитектуры ABI документы, которые я нашел (MIPS64, ppc64, amd64, ia64, sparc64, arm64) имеют выравнивание полукокса 1, короткий 2, внутр 4 и долго долго 8.

Даже если операционная системам разрешено создавать свои собственные ABI, почти каждая unix-подобная система и особенно Linux следуют System V ABI и их дополнительной документации по ЦП, которая очень хорошо описывает это поведение. И Debian определенно не изменит это поведение, чтобы быть отличным от всех других Linux.

Вот быстрая проверка (все на amd64/x86_64, который является то, что вы, скорее всего, работает):

$ cat > foo.c 
#include <stdio.h> 

int 
main(int argc, char **argv) 
{ 
    struct { 
     long long ll; 
     char ch2; 
     char ch1; 
     short s; 
     int i; 
    } foo; 

    printf("%d\n", (int)sizeof(foo)); 
    return 0; 
} 

MacOS:

$ cc -o foo foo.c && ./foo && uname -ms 
16 
Darwin x86_64 

Ubuntu:

$ cc -o foo foo.c && ./foo && uname -ms 
16 
Linux x86_64 

CentOS:

$ cc -o foo foo.c && ./foo && uname -ms 
16 
Linux x86_64 

OpenBSD:

$ cc -o foo foo.c && ./foo && uname -ms 
16 
OpenBSD amd64 

Там что-то еще не так с вашей компиляции. Или это не та структура, которую вы тестируете, или вы работаете на очень странной аппаратной архитектуре и указав ее как «64-битный», эквивалентно тому, что я говорю «Я управляю этим правительством, и у него очень странное ускорение и двигатель вырезается через 5 минут »и не упоминает, что вы говорите о космическом челноке.

0

Обычно, чтобы минимизировать прокладки, обычная практика заключается в том, чтобы упорядочить участников от самых маленьких до самых маленьких, не могли бы вы попытаться их переупорядочить и посмотреть, что из этого выйдет?

struct ST 
{ 
    long long ll; //8 bytes 
    int i;   //4bytes 
    short s;  //2 bytes 
    char ch2;  //1 byte 
    char ch1;  //1 byte 
}; 

Всего 16 байт

+0

, пожалуйста, проверьте мое редактирование, я использую debian 64bit, gcc not g ++ – sprocket12

1

Это все о набивке. В visual studio (и некоторых других компиляторах) вы можете использовать #pragma push/pack, чтобы выровнять его по своему усмотрению.

#pragma pack(push, 1) 
struct ST 
{ 
    /*0x00*/ long long ll; 
    /*0x08*/ char ch2; 
    /*0x09*/ char ch1; 
    /*0x0a*/ short s; 
    /*0x0c*/ int i; 
    /*0x10*/ 
}; 
#pragma pack(pop) 

Поскольку вы сказали, что подходило как размер 24, я собираюсь предположить, что компилятор совместив вас на 4 байта, делая что-то вроде этого:

struct ST 
{ 
    /*0x00*/ long long ll; 
    /*0x08*/ char ch2; 
    /*0x09*/ char padding1[0x3]; 
    /*0x0c*/ char ch1; 
    /*0x0d*/ char padding2[0x3]; 
    /*0x10*/ short s; 
    /*0x11*/ char padding3[0x2]; 
    /*0x14*/ int i; 
    /*0x18*/ 
}; 

(К сожалению, я подумайте в шестнадцатеричном виде, когда делаете такие вещи. 0x10 равно 16 в десятичной системе, а 0x18 равно 24 в десятичной системе.)

+0

Какой CPU ABI будет указывать на это странное выравнивание и дополнение? Даже альфа, у которой не было инструкций для доступа к одному или двум байтовым значениям, требуется 4-байтное выравнивание для шорт. – Art

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