Skip to content

Instantly share code, notes, and snippets.

@savanovich
Created March 5, 2015 10:53
Show Gist options
  • Save savanovich/5e04c9daf17b882295dd to your computer and use it in GitHub Desktop.
Save savanovich/5e04c9daf17b882295dd to your computer and use it in GitHub Desktop.
C: Do not allow structure padding
struct test_t {
int a;
char b;
int c;
} __attribute__((__packed__));
@savanovich
Copy link
Author

http://habrahabr.ru/post/142662/#comment_4777709

Спасаться от лишнего паддинга можно и без pragma pack. Рецепт прост — поля в структуре «сортируются» по размеру. В начале помещаются самые большие (uint64, uint32), в конце — самые маленькие — (uint8). Все вопросы с порядком байт должны (на мой взгляд) решаться в точке сериализации и десериализации данных (ну, например, при отправке в сеть и получения из сети), а сам этот процесс, по хорошему, должен производиться не сразу в структуру, а путём последовательного чтения данных из буфера и размещения в соответствующих полях в специфичном для платформы виде. Может быть это не так «просто» и «изящно» выглядит, зато надёжно, переносимо и расширяемо.

@savanovich
Copy link
Author

http://habrahabr.ru/post/142662/#comment_4777489
Ещё стоит вспомнить, что битовые поля — это thread unsafe штука, про что обычно забывают, и, в отличие от обычных полей структуры, независимо обновлять их из потоков уже не получится.

http://habrahabr.ru/post/142662/#comment_4777616
Ну безопасно обновлять поля структуры можно только со времен c++11, до него битовые поля и поля структуры на одной линии огня. После c++11 проблема осталась только с полями, да.

@savanovich
Copy link
Author

http://habrahabr.ru/post/142662/#comment_4777231
«The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.»
То есть гарантировать, что битовые поля всегда будут на одном и том же месте — нельзя. С другим компилятором/платформой всё может перестать работать, а виноват в этом будет не компилятор.

@savanovich
Copy link
Author

http://habrahabr.ru/post/142662/#comment_4777138
только, наверное, следует сказать, что упакованные структуры работают медленнее, чем неупакованные.

операции с отдельными битовыми полями работают медленнее, чем маски.

@savanovich
Copy link
Author

http://habrahabr.ru/post/142662/#comment_4777709
Это всё, конечно, хорошо. Но, как уже правильно отметили в комментариях, непереносимо, а на некоторых платформах и попросту небезопасно. Из лично известных мне — SPARC весьма щепетильно относится к выравниванию данных, и генерит исключение SIGBUS в случае доступа к неправильно выравненным данным.
Спасаться от лишнего паддинга можно и без pragma pack. Рецепт прост — поля в структуре «сортируются» по размеру. В начале помещаются самые большие (uint64, uint32), в конце — самые маленькие — (uint8). Все вопросы с порядком байт должны (на мой взгляд) решаться в точке сериализации и десериализации данных (ну, например, при отправке в сеть и получения из сети), а сам этот процесс, по хорошему, должен производиться не сразу в структуру, а путём последовательного чтения данных из буфера и размещения в соответствующих полях в специфичном для платформы виде. Может быть это не так «просто» и «изящно» выглядит, зато надёжно, переносимо и расширяемо.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment