Keil: ключевое слово __packed |
![]() |
Добавил(а) microsin |
Квалификатор __packed полезен для содержимого структуры к внешней структуре данных, или для доступа к не выровненным данным. Однако это не всегда целесообразно экономить на памяти с помощью __packed, потому что это приводит к относительно высокой стоимости доступа к не выровненным данным (unaligned access). Квалификатор __packed устанавливает выравнивание в 1 для любого допустимого типа. В результате получается следующее: • Не будет вставляться никаких выравнивающих байтов, чтобы выровнять упакованный объект. Квалификатор __packed применяется ко всем членам (полям) структуры (struct) или объединения (union), когда они декларированы с использованием __packed. После этого между ними, или в конце такой упакованной структуры не будет никаких выравнивающих байт. Все вложенные структуры в упакованную структуру должны быть декларированы с использованием __packed. Целочисленные субполя не упакованной структуры можно упаковать индивидуально. Только упаковка отдельных полей структуры, которая требует упаковки, может снизить количество не выровненных обращений. Примечание: на процессорах ARM, которое не поддерживают аппаратно не выровненный доступ (например pre-ARMv6), доступ к не выровненным данным может быть дорог в контексте размера кода и скорости его выполнения. Доступ к данным через упакованную структуру должен быть минимизирован, чтобы избежать разрастания кода и снижения производительности. Ограничения __packed. На использование __packed накладываются следующие ограничения: • Квалификатор __packed не может использоваться в структурах, которые ранее были декларированы без __packed. Ошибки. Взятие адреса поля в __packed структуре, или адрес поля с квалификатором __packed дает указатель, квалифицированный как __packed. Компилятор сгенерирует ошибку типа (type error), если Вы попытаетесь неявно привести тип (cast) этого указателя к не __packed указателю. Это контрастирует с поведением компилятора для взятия адреса полей структуры, упакованной директивой #pragma packed. [Примеры __packed] Пример 1. Следующий пример показывает, что указатель может указывать на упакованный тип. typedef __packed int* PpI; /* указатель на __packed int */ __packed int *p; /* указатель на __packed int */ PpI p2; /* у 'p2' такой же тип, как и у 'p' */ /* __packed это квалификатор, так же 'const' или 'volatile' */
typedef int *PI; /* указатель на int */ __packed PI p3; /* __packed-указатель на обычный int */ /* -- не тот же тип, что и 'p' или 'p2' */ int *__packed p4; /* у 'p4' такой же тип, что и у 'p3' */ Пример 2. Следующий пример показывает, что при обращении к упакованному объекту через указатель компилятор генерирует код, который работает и не зависит от выравнивания указателя. // Структура из 5 байт, естественное выравнивание = 1:
typedef __packed struct { // Все этой структуры поля наследуют квалификатор __packed: char x; int y; } X; int f(X *p) { return p->y; // приведет к не выровненному чтению (unaligned read) } // Структура из 8 байт, естественное выравнивание = 2:
typedef struct { short x; char y; __packed int z; // упаковано только это поле char a; } Y; int g(Y *p) { return p->z + p->x; // не выровненное чтение только для z } [Ссылки] 1. Keil __packed keyword site:keil.com. |