Когда вы пишете на языке ассемблера и объявить пространство для персонажа, ассемблер выделяет пространство для одного символа и не более. (Я пишу об общих сборщиках.) Если вы хотите выровнять объекты на языке ассемблера, для этой цели вы должны включить директивы ассемблера.
Когда вы пишете на C, а компилятор переводит его на сборку и/или машинный код, пространство для символа может быть дополнено. Обычно это не делается из-за преимуществ выравнивания для объектов символов, а потому, что у вас есть несколько вещей, объявленных в вашей программе. Например, рассмотрим, что происходит, когда вы объявляете:
char a;
char b;
int i;
char c;
double d;
Наивный компилятор может сделать это:
- Выделяют один байт для
a
в начале соответствующей памяти, что случается, выравниваются по кратное, скажем, 16 байт.
- Выделите следующий байт для
b
.
- Затем он хочет разместить
int i
, которому требуется четыре байта. На этой машине объекты int
должны быть выровнены по краям четырех байтов, или программа, пытающаяся получить к ним доступ, выйдет из строя. Таким образом, компилятор пропускает два байта и затем выделяет четыре байта для i
.
- Выделите следующий байт за
c
.
- Пропустить семь байтов, а затем выделить восемь байтов для
d
. Это делает d
совпадающим с кратным восьми байтам, что выгодно для этой гипотетической машины.
Таким образом, даже с наивным компилятором объект-символ не требует для себя четырех целых байтов. Он может делиться с соседними символьными объектами или другими объектами, которые не требуют большего выравнивания. Но будет пустое пространство.
Умнее компилятор сделает это:
- Сортировать объекты, которые он должен выделить место для в соответствии с их требованиями выравнивания.
- Сначала укажите наиболее ограничительный объект: отложите восемь байтов для
d
.
- Поместите следующий наиболее ограничительный объект: выделите четыре байта для
i
. Обратите внимание, что i
выровнен с кратным четырем байтам, поскольку он соответствует d
, который представляет собой восьмибайтовый объект, выровненный с кратным восьми байтов.
- Поместите наименее ограничительные объекты: Отложите один байт на
a
, b
и c
.
Этот тип переупорядочения позволяет избежать потери пространства, и любой достойный компилятор будет использовать его для памяти, которую он может организовать (например, автоматические объекты в стеке или статические объекты в глобальной памяти).
Когда вы объявляете членов внутри структуры, компилятор должен использовать порядок, в котором вы объявляете членов, поэтому он не может выполнить это переупорядочение, чтобы сэкономить место. В этом случае объявление объектов символов и других объектов может потерять пространство.
Вы пробовали массив символов? – Nemo
Преобразование в байтах зависит от вашего компилятора. На одной платформе это может быть то, что вы сказали, а на другом - что-то другое. – Bgi