В большинстве архитектур базовый доступ должен соответствовать выравниванию данных, к которым осуществляется доступ.
Это означает, что если у вас есть 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', за исключением случаев крайней необходимости. Если у вас есть контроль над определением структуры, существуют методы, позволяющие убедиться, что макет структуры не содержит отступов. Если нет, лучшим подходом будет копирование любых невыровненных данных в новую, выровненную структуру и использование ее в вашем приложении.
19.10.2011