Программы
Выравнивание структур

Выравнивание структур

Неочевидная тема. Для многих, кто программировал только на высокоуровневых ЯП, сложно принять, что заботиться нужно даже о порядке полей в структурах

– Выравнивание.
– Что?
– Выравнивание!
– ?
– Ну это там где потраченные на ничто байты, порядок, любить его неестественно, полей... Выравнивание!

И всё же у нас "под капотом" всё те же байты. Поэтому посмотрим, как устроены эти самые структуры.

#include <stdio.h>
#include <math.h>
// Подключаем для memcpy (да, неочевидно, но именно в "строках").
// Как будто qsort должен был быть в stdlib.h...
#include <string.h>

// Ещё немного примеров структур и их определения.
typedef struct Point2d Point2d;
struct Point2d {
  int x;
  int y;
};

typedef struct User {
  unsigned char age;
  unsigned int ip;
  char name[16];
} User;

// Именно с этой структурой мы будем развлекаться.
typedef struct Example {
  char symbol;
  short num1;
  short num2;  // Смотрим содержимое с этим полем и без него
  int some_int;
} Example;

void print_hex(void *a, int size) {
  char *byte = (char *)a;

  for (int i = 0; i < size; ++i) {
    printf("%02hhx ", *(byte + i));
  }

  printf("\n");
}

int main() {
  char buf[100];
  Point2d a = { .y = -1, .x = 1};

  // Ожидаемо, 8 байт (по 4 за каждый int)
  printf("Point2d size: %lu\n", sizeof(a));

  memcpy(buf, &a, 8);
  print_hex(buf, 8);

  User u = { .name = "Ivanov Ivan", .age = 21, .ip = 0x7f000001 };
  // Упс
  printf("User size: %lu (21 expected)\n", sizeof(u));
  memcpy(buf, &u, sizeof(u));
  print_hex(buf, sizeof(u));

  Example e1 = { 'a', 1, 2, -1 };
  printf("Example size: %lu\n", sizeof(e1));
  memcpy(buf, &e1, sizeof(e1));
  print_hex(buf, sizeof(e1));
}

Получаем 24 вместо 21 байта (если sizeof(int) == 4). Если присмотреться к байтам:

15 00 00 00  // age
01 00 00 7f  // ip
49 76 61 6e 6f 76 20 49 76 61 6e 00 00 00 00 00  // name

Результаты с 2 short:

61
00     // ?
01 00
02 00
00 00  // ?
ff ff ff ff

С 1 short:

61
00     // ?
01 00
ff ff ff ff

Можно заметить, что 1-байтовые поля не выравниваются, 2-байтовые — выравниваются на чётные позиции, 4-байтовые — на позиции кратные четырём. Понятнее "листинг" с примером 2-х short полей можно записать так:

00: 61
01: 00     // ?
02: 01 00
04: 02 00
06: 00 00  // ?
08: ff ff ff ff

– где числа до ":" – отступ в байтах от начала структуры. Именно по этому отступу и выравниваются поля структуры.

Самообучение: разобраться с выравниванием в структуре User.

TODO: Дописать объяснение с картинами причин выравнивания, какая оптимизация идёт. Да, я забил на это и в версии 0.02

Также может быть вам интересно:

Структуры и объединения

Базовые структуры в Си. Общие принципы работы с ними

Читать »

Enum - перечисляемый тип данных

Распространённый тип данных во многих языках программирования. Как же он выглядит в Си?

Читать »
Фото Python: Встроенные типы данных (list, set, dict, etc)

Python: Встроенные типы данных (list, set, dict, etc)

В Python есть множество встроенных типов данных. Их использование значительно упрощает жизнь и ускоряет разработку программных продуктов.

Фото Python: типы данных, переменные, логическое ветвление и циклы

Python: типы данных, переменные, логическое ветвление и циклы

Первая часть заметок о Python. О базовых типах, переменных, ветвлении и циклах.

Фото Как сделать свою middleware в Django (с примерами)

Как сделать свою middleware в Django (с примерами)

Middleware или "промежуточное программное обеспечение" - элегантный способ установить общие правила обработки запросов и ответов приложения. Давайте напишем парочку middleware, чтобы понять, как они работают.

Фото Как настроить отправку почты из Django

Как настроить отправку почты из Django

Письма об ошибках, отчёты на почту, восстановление паролей - всё это полезно при работе с сайтом. Django предоставляет удобный способ это сделать с минимумом настроек!

Фото Добавляем постраничную пагинацию на Django сайт

Добавляем постраничную пагинацию на Django сайт

На сайтах часто встречаются многостраничные объекты: список товаров, список заметок и т.д. Поэтому важно уметь добавить навигацию по страницам на Django-проекте.

Фото Новый оператор match-case в Python

Новый оператор match-case в Python

В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

Фото Нет слов, одни... однострочники

Нет слов, одни... однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Фото Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

В Django вы можете передавать данные в шаблоны посредством контекстов. Контекст передаётся из контроллера (view в терминах Django), однако, если одни и те же данные нужны в разных местах, лучше сделать свой контекст-процессор.