Там нет никаких правил для этого. Это зависит от используемой вами реализации. Далее он может меняться в зависимости от параметров компилятора. Лучшее, что вы можете сделать, это напечатать адрес каждой переменной. Затем вы можете увидеть, как выглядит макет памяти.
Что-то вроде этого:
int main(void)
{
int num;
char s;
int *ptr;
printf("num: %p - size %zu\n", (void*)&num, sizeof num);
printf("s : %p - size %zu\n", (void*)&s, sizeof s);
printf("ptr: %p - size %zu\n", (void*)&ptr, sizeof ptr);
return 0;
}
Возможный выход:
num: 0x7ffee97fce84 - size 4
s : 0x7ffee97fce83 - size 1
ptr: 0x7ffee97fce88 - size 8
заметить также, что в случае, если вы не принимаете адрес (&
) переменной, компилятор может оптимизировать код так что переменная никогда не помещается в память.
В целом, выравнивание обычно выполняется для получения наилучшей производительности из используемой платформы HW. Это, как правило, означает, что переменные выровнены с их размером или, по меньшей мере, 4 байта выровнены для переменных с размером больше, чем 4.
Обновление:
ОП дает конкретный пример компоновки в обновлении и спрашивает, если этот макет может/когда-либо случится.
Опять ответ: Это зависит от реализации
Так что в принципе это может произойти на какой-то конкретной системе. Тем не менее я сомневаюсь, что это произойдет в любой основной системе.
Существует еще один пример кода, составленный с НКУ -O3
int main(void)
{
short s1;
int i1;
char c1;
int i2;
char c2;
printf("s1: %p - size %zu\n", (void*)&s1, sizeof s1);
printf("i1: %p - size %zu\n", (void*)&i1, sizeof i1);
printf("c1: %p - size %zu\n", (void*)&c1, sizeof c1);
printf("i2: %p - size %zu\n", (void*)&i2, sizeof i2);
printf("c2: %p - size %zu\n", (void*)&c2, sizeof c2);
return 0;
}
Выход из моей системы:
s1: 0x7ffd222fc146 - size 2 <-- 2 byte aligned
i1: 0x7ffd222fc148 - size 4 <-- 4 byte aligned
c1: 0x7ffd222fc144 - size 1
i2: 0x7ffd222fc14c - size 4 <-- 4 byte aligned
c2: 0x7ffd222fc145 - size 1
Обратите внимание, как расположение в памяти отличается от переменных порядка был определен в код. Это обеспечивает хорошее выравнивание.
Сортировка по адресу:
c1: 0x7ffd222fc144 - size 1
c2: 0x7ffd222fc145 - size 1
s1: 0x7ffd222fc146 - size 2 <-- 2 byte aligned
i1: 0x7ffd222fc148 - size 4 <-- 4 byte aligned
i2: 0x7ffd222fc14c - size 4 <-- 4 byte aligned
Итак, еще раз, чтобы ответить на ДОПОЛНЕНО вопрос:
В большинстве систем я сомневаюсь, что вы будете видеть переменную с 4 байт помещаются по адресу xXx2, xxx6 или xxxa , xxxe. Но все же могут существовать системы, где это может произойти.
Указатели также нуждаются в хранении памяти. – ForceBru
Почему, по-вашему, эти переменные хранятся где угодно? Это автоматические переменные, и они могут быть оптимизированы или доступны только в регистрах. Более того, если он когда-либо хранится в памяти, компилятор может переупорядочить их, если он сочтет это полезным и т. Д. – Walter