Читать книгу Ссылки и указатели в C++: от основ к безопасности и современному коду - - Страница 64

Выравнивание и alignof, sizeof vs реальный размер

Оглавление

Давайте нырнём глубже в одну из самых "технических" тем памяти в C++ выравнивание (alignment). Представьте процессор как привередливого читателя: он предпочитает брать данные "пачками" по определённым границам, как книги с полки, выровненные по краю. Если данные не выровнены, чтение замедляется или даже приводит к ошибкам. Выравнивание это правило размещения данных в памяти так, чтобы их адрес был кратен определённому числу (обычно степени 2, как 4, 8, 16 байт). Это оптимизирует доступ CPU, минимизирует циклы кэша и предотвращает hardware-исключения на некоторых архитектурах (например, ARM или старые x86).

Почему выравнивание нужно? Процессоры (x86, ARM, RISC-V) спроектированы для атомарного чтения/записи по словам (word size: 4 байта на 32-bit, 8 на 64-bit). Невыровненный доступ может требовать двух операций вместо одной, замедляя код в 2–10 раз или вызывая bus error/SIGBUS. В C++ стандарт гарантирует естественное выравнивание для встроенных типов: char 1 байт, int обычно 4, double 8. Для пользовательских типов (struct/class) выравнивание максимум из выравниваний полей.

alignof: это оператор (с C++11), возвращающий минимальное требуемое выравнивание для типа в байтах. Например, alignof(int) = 4 на большинстве платформ. Он constexpr, так что полезен в шаблонах и compile-time проверках.

sizeof vs реальный размер: sizeof(T) размер типа в байтах, включая padding (добавочные байты для выравнивания). Padding вставляется компилятором между полями структур, чтобы каждое поле начиналось на своём выравнивании. Общий sizeof структуры кратен её выравниванию. "Реальный" размер сумма размеров полей без padding, но память тратится на padding для эффективности.

Рассмотрим аналогию: структура как вагон поезда. Поля пассажиры разного роста (размера). Выравнивание правило: высокий (int) садится только у окна (кратно 4). Если после короткого (char) нет места добавляем пустые сиденья (padding).

Пример базовый:

#include <iostream>


struct NonAligned {


char c; // 1 байт, alignof=1


int i; // 4 байта, alignof=4 → padding 3 байта после c


};


int main() {


std::cout << "sizeof(NonAligned): " << sizeof(NonAligned) << " (ожидаемо 8)" << std::endl;


std::cout << "alignof(NonAligned): " << alignof(NonAligned) << " (4, как max полей)" << std::endl;


return 0;


}

Здесь sizeof=8 (1+3 padding+4), хотя "реальный" 5 байт. Padding "раздувает" структуру.

Ссылки и указатели в C++: от основ к безопасности и современному коду

Подняться наверх