Недавно я наткнулся на эту директиву препроцессора #pragma pack(1) и задался вопросом, почему она используется?
Я погуглил об использовании и обнаружил, что у него есть другие параметры, такие как push, pop и т. Д. Кто-нибудь использовал это в своем встроенном приложении?
Я хотел бы узнать несколько примеров того, как/почему вы использовали эту директиву и на каком типе процессора? Каковы плюсы/минусы использования этой директивы?
Спасибо.
#pragma pack(1)
гарантирует, что struct
элементы C упакованы по порядку и на границах байтов. Это может сэкономить оперативную память, которая часто бывает ценна в микроконтроллере.
Упакованные структуры также позволяют выполнять приведение типов непосредственно к буферам памяти для обмена данными:
void f(void *buf)
{
struct ip_header *hdr = (struct ip_header *)buf;
hdr->dst = 0x8000001;
}
Будьте осторожны, где вы используете #pragma pack
. Он имеет глобальную область действия (как и в препроцессоре), поэтому если вы забудете его отключить, это повлияет на любые #include
файлы. Если вы хотите упаковать только определенные структуры, рассмотрите возможность использования GCC __attribute__ ((packed))
.
Однако из-за проблем с выравниванием упакованные структуры могут повлиять на производительность. Например:
При упаковке в байты:
struct
{
uint8_t a;
uint32_t b;
uint8_t c;
uint8_t d:
};
Будет храниться как (без учета порядка байтов):
а, б0, б1, б2, б3, в, г
Однако многие архитектуры требуют, чтобы 32-битные обращения были согласованы с 32-битными адресами. С упакованной структурой машине придется сделать несколько обращений к байтам, а затем снова сшить их вместе.
Столкнувшись с вышеизложенным struct
без включения упаковки, компилятор может реорганизовать его как:
б0, б1, б2, б3, а, в, г
Еще одна причина упаковывать структуры на границах байтов — обеспечить выравнивание членов при передаче данных между разными процессорами.
Мне часто приходится передавать структуры данных между MCU и приложением хост-компьютера. ПК будет упаковывать структуры на 32-битных границах, если только не будет указано упаковывать их на 1-байтовые границы. Микроконтроллер PIC24F будет упаковывать структуры по 16-битным границам, если не будет указано упаковывать их по 1-байтовым границам.
Поручая им обоим упаковывать свои структуры на границах в 1 байт, он гарантирует, что данные находятся в одном и том же месте при доступе к ним на любом конце. Без него вам пришлось бы дополнять структуры резервными байтами, чтобы члены данных правильно выровнялись.
Традиционное использование, где я видел, это использование для чтения информации из файлов. Например, вы можете определить структуру, элементы которой соответствуют элементам заголовка BMP-файла, а затем прочитать весь заголовок за одну операцию быстрого чтения. Итак, BMP может быть не лучшим примером (его заголовок не имеет проблем с выравниванием в 32-битных системах), но вы поняли идею. Я полагаю, что это столь же полезно во встраиваемом мире.
ЗлойEE