– Выравнивание.
– Что?
– Выравнивание!
– ?
– Ну это там где потраченные на ничто байты, порядок, любить его неестественно, полей... Выравнивание!
И всё же у нас "под капотом" всё те же байты. Поэтому посмотрим, как устроены эти самые структуры.
#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