В большинстве архитектур базовый доступ должен соответствовать выравниванию данных, к которым осуществляется доступ.
Это означает, что если у вас есть 32-битное значение, вы можете получить к нему эффективный доступ, если оно хранится по адресу, который делится на четыре.
Если вы используете #pragma pack
, расположение переменной может быть любым, и компилятор должен обращаться к элементу по частям и объединять их вместе. Конкретно, ниже приведен сгенерированный код для чтения обычного int
на V850E (популярном микроконтроллере во встроенном мире):
LD.W a[zero],r5
Соответственно, ниже приведен код для доступа к int
в упакованной структуре:
LD.BU g+3[zero],r1
SHL 8,r1
LD.BU g+2[zero],r6
OR r1,r6
SHL 8,r6
LD.BU g+1[zero],r7
OR r6,r7
SHL 8,r7
LD.BU g[zero],r1
OR r7,r1
Другая причина не использовать упакованные структуры состоит в том, что невозможно разыменовать указатель на член упакованной структуры, если архитектура не поддерживает обращения к указателю без выравнивания. Причина этого в том, что тип точки будет простым указателем int
, и компилятор не знает, что он должен обращаться к тому, на что он указывает, по частям.
Я бы настоятельно рекомендовал вам вообще не использовать «#pragma pack», если это не является абсолютно необходимым. Если у вас есть контроль над определением структуры, существуют методы, позволяющие убедиться, что структура структуры не содержит отступов. Если нет, лучшим подходом было бы скопировать любые невыровненные данные в новую, выровненную, структурированную и использовать их в вашем приложении.