tgoop.com/cxx95/132
Last Update:
#jostik
Обзор жостиков C++ sizeof(char)
)
(Предисловие)
Эту картинку я сделал месяц назад, и хотел отправить в WG21 (Working Group 21, он же Комитет C++) как предложение для логотипа
Но вспомнив комитетские приколы, решил не делать
Какой-нибудь товарищ комиссар Рабочей Группы по многообразию не принял бы ее, аргументировав что для репрезентации нужна широкая цветовая палитра, а вместо одного из крестов, например, символ зороастризма
Поэтому это будет новая ава
Теория о них тут, реализация на гитхабе.
Strong-типы это обертки над базовыми типами (int
, double
и пр.), которые не могут конвертироваться в другие типы. Это полезно, чтобы не путать аргументы и понимать цель значения из имени типа.
Например, вместо такого конструктора:
Rectangle(double width, double height);
Можно сделать такой:
Rectangle(Width width, Height height);
Где
Width
и Height
- обертки над double
, и их нельзя перепутать Strong-типам можно придавать разные "скиллы" - например Addable, Comparable, Hashable и прочие, чтобы соответственно работали операции сложения, сравнения или можно было положить тип в хэшмапу.
Эти типы "бесплатные" для рантайма - компилятор выбрасывает шелуху и работает с базовым типом
Раньше я их не принимал (если ты путаешься в параметрах, то вместо 15 параметров нужен builder pattern
Как известно, у типов есть выравнивание:
struct Biba {
uint16_t a; /* 2 bytes */
/* padding 6 bytes */
uint64_t b; /* 8 bytes */
};
static_assert(sizeof(Biba) == 16);
static_assert(alignof(Biba) == 8);
Но во время парсинга пакетов всяких протоколов это может мешать, потому что никаких padding'ов между полями не предусмотрено. Также во время работы с сетью супер важно оптимизировать память. Тогда надо убирать выравнивание (alignment)
Это можно сделать разными способами, самый удобный такой:
#pragma pack(push, 1)
struct Boba {
uint16_t a; /* 2 bytes */
uint64_t b; /* 8 bytes */
};
#pragma pack(pop)
static_assert(sizeof(Boba) == 10);
static_assert(alignof(Boba) == 1);
(Этот pragma pack выглядит странно, потому что у него есть типа внутренний стек)
Команда
pack(push, N)
значит что все типы будут иметь alignment максимум N
байт, а pack(pop)
убирает это.Менее удобный способ (потому что надо ставить каждому классу вручную) это вешать на структуру
__attribute__((packed))
.Это немного по-другому работает внутри компилятора, но итог один - alignment равный единице.
Способ, который не работает - спецификатор alignas, он может только увеличить дефолтный alignment. Оно используется для подгона структуры под кэш-линию (64 байта) или SIMD-инструкции (16/32/64 байта).
А как это работает на уровне ассемблера?
Как оказывается, на x86 никаких сюрпризов нет. Оно всегда поддерживало unaligned access (работающий медленнее чем aligned).
А на других архитектурах может произойти треш - надо беречься
ПРОДОЛЖЕНИЕ В КОММЕНТАРИЯХ