В языке C структуры (struct) могут включать другие структуры и различные типы данных. Однако расположение полей внутри структуры может влиять на её размер и выравнивание. Компилятор добавляет дополнительные байты (padding) для соблюдения выравнивания (alignment) по наиболее крупному полю. Это важно для производительности и корректной работы процессора.
Если структура содержит вложенные структуры, выравнивание применяется рекурсивно:
#pragma pack в MSVC или атрибут __attribute__((packed)) в GCC/Clang).Пример:
#include <stdio.h> struct Inner { char c; int x; }; struct Outer { char a; struct Inner b; short s; }; int main() { printf("sizeof(struct Inner) = %zu ", sizeof(struct Inner)); printf("sizeof(struct Outer) = %zu ", sizeof(struct Outer)); return 0; } // sizeof(struct Inner) = 8 (на 64-бит), sizeof(struct Outer) = 16 или 24
Использование pack и packed уменьшает размер за счёт игнорирования выравнивания, но это может снизить производительность или вызвать ошибки на некоторых платформах (ARM, DSP и др.).
Вопрос: Можно ли гарантировать одинаковый размер одной и той же структуры на всех платформах?
Ответ: Нет! Стандарт C не гарантирует одинаковое выравнивание, порядок байтов (endian), и может "добавить" padding между полями и в конце структуры. Для бинарной совместимости структур используйте ручное управление выравниванием и всегда явно тестируйте sizeof под каждой целевой платформой.
Пример:
struct Data { char c; int x; }; // sizeof(Data) обычно 8 на 64-бит, 5 или 8 на 32-бит
История
При обмене структурой между микроконтроллером (ARM) и ПК через бинарный протокол пришедшие с ARM данные не совпадали с ожиданиями на ПК — из-за разного padding и порядка байтов. Из-за этого декодировались неверные параметры, что приводило к физическим ошибкам управления устройством.
История
В сетевом протоколе для ускорения отправки данных добавили packed-структуры, но не учли, что на платформе без выравнивания отдельные поля не работали (процессор не поддерживал мисс-алайнед доступ). Итог: аппаратные исключения при работе с сетевыми пакетами.
История
Сервер работал с внешним файлом, состоящим из записей структуры. После обновления компилятора размер структуры изменился (другое выравнивание). Старые данные в файле перестали правильно считываться, часть информации стала "битой".