Ответ 1
Причина вышеописанного поведения - выравнивание структуры данных и добавление. В принципе, если вы создаете 4 байтовую переменную, например. int, он будет выровнен с границей в четыре байта, то есть он начнется с адреса в памяти, который будет кратен 4. То же самое относится к другим типам данных. 2 байта должны начинаться с четного адреса памяти и т.д.
Следовательно, если у вас есть 1 байтовый символ, объявленный перед int (предположим, 4 байта здесь), между ними останется 3 свободных байта. Общий термин, используемый для них, - "padded"
Еще одно хорошее иллюстрированное объяснение
Причина выравнивания
Заполнение позволяет более быстрый доступ к памяти, то есть для процессора, доступ к областям памяти, которые выровнены быстрее, например. чтение 4-байтового выровненного целого числа может принимать однонаправленный вызов, где, как если бы целое число находилось в некорректированном диапазоне адресов (например, адрес 0x0002 - 0x0006), тогда потребовалось бы двух считываний памяти, чтобы получить это целое число.
Один из способов заставить компилятор избегать выравнивания (зависит от gcc/g++), чтобы использовать ключевое слово "упакованное" с атрибутом структуры. упакованное ключевое слово Также ссылка указывает, как обеспечить выравнивание по определенной границе вашего выбора (2, 4, 8 и т.д.), используя выровненное ключевое слово.
Лучшая практика
Всегда полезно структурировать свой класс/структуру таким образом, чтобы переменные уже были выровнены с минимальным заполнением. Это уменьшает размер класса в целом плюс уменьшает объем работы, выполняемой компилятором, т.е. Никакой перегруппировки структуры. Также всегда нужно обращаться к переменным-членам по их именам в коде, а не пытаться прочитать конкретный байт из структуры, предполагая, что значение будет находиться в этом байте.
Еще один полезный SO вопрос о преимуществах производительности выравнивания
Для завершения следующего размера по-прежнему будет иметь размер 8 байт в вашем сценарии (32-разрядная машина), но он не улучшится, так как теперь заняты все 8 байтов, и нет прокладки.
class temp
{
public:
int i;
short s;
char c;
char c2;
};