6.35.1 Атрибуты типов общего назначения
Следующие атрибуты типов поддерживаются на большинстве целевых платформ.
alignedaligned (alignment)-
Атрибут
alignedзадает минимальное выравнивание (в байтах) для переменных указанного типа. Если задано, alignment должно быть степенью двойки. Отсутствие аргумента alignment подразумевает максимальное выравнивание для целевой платформы, которое часто, но не всегда, составляет 8 или 16 байт. Например, объявления:struct __attribute__ ((aligned (8))) S { short f[3]; }; typedef int more_aligned_int __attribute__ ((aligned (8)));заставляют компилятор обеспечить (насколько это возможно), что каждая переменная, тип которой
struct Sилиmore_aligned_int, выделяется и выравнивается по крайней мере на границе 8 байт. На платформе SPARC выравнивание всех переменных типаstruct Sна границе 8 байт позволяет компилятору использовать инструкцииlddиstd(загрузка и сохранение двойного слова) при копировании одной переменной типаstruct Sв другую, что повышает эффективность работы во время выполнения.Обратите внимание, что выравнивание любого типа
structилиunionсогласно стандарту ISO C должно быть по крайней мере кратным наименьшему общему кратному выравниваний всех членов типаstructилиunionсоответственно. Это означает, что вы можете эффективно настроить выравнивание типаstructилиunionпутем добавления атрибутаalignedк любому члену такого типа, но обозначение, показанное в примере выше, является более очевидным, интуитивно понятным и удобочитаемым способом запросить у компилятора настроить выравнивание всего типаstructилиunion.Как и в предыдущем примере, вы можете явно указать выравнивание (в байтах), которое вы хотите использовать компилятору для данного типа
structилиunion. В качестве альтернативы, вы можете опустить фактор выравнивания и просто попросить компилятор выровнять тип по максимальному полезному выравниванию для целевой машины, для которой вы компилируете. Например, вы можете написать:struct __attribute__ ((aligned)) S { short f[3]; };Всякий раз, когда вы опускаете фактор выравнивания в спецификации атрибута
aligned, компилятор автоматически устанавливает выравнивание для типа по самому большому выравниванию, которое когда-либо используется для любого типа данных на целевой машине, для которой вы компилируете. Это часто делает операции копирования более эффективными, поскольку компилятор может использовать любые инструкции для копирования больших блоков памяти при выполнении копирования в или из переменных с типами, которые вы выровняли таким образом.В примере выше, если размер каждого
shortсоставляет 2 байта, то размер всего типаstruct Sсоставляет 6 байт. Наименьшая степень двойки, которая больше или равна этому, составляет 8, поэтому компилятор устанавливает выравнивание для всего типаstruct Sв 8 байт.Обратите внимание, что хотя вы можете попросить компилятор выбрать эффективное с точки зрения времени выравнивание для данного типа и затем объявить только отдельные самостоятельные объекты этого типа, способность компилятора выбирать эффективное выравнивание в основном полезна только тогда, когда вы планируете создавать массивы переменных с соответствующим (эффективно выровненным) типом. Если вы объявляете или используете массивы переменных с эффективно выровненным типом, то, вероятно, ваша программа также выполняет арифметику указателей (или индексирование, что сводится к тому же) над указателями на соответствующий тип, и код, который генерирует компилятор для этих операций арифметики указателей, часто более эффективен для эффективно выровненных типов, чем для других типов.
Обратите внимание, что эффективность атрибутов
alignedможет быть ограничена присущими ограничениями вашего компоновщика. На многих системах компоновщик может только организовать выравнивание переменных до определенного максимального выравнивания. (Для некоторых компоновщиков максимальное поддерживаемое выравнивание может быть очень-очень маленьким.) Если ваш компоновщик может выравнивать переменные только до максимального выравнивания 8 байт, то указаниеaligned (16)в атрибуте__attribute__по-прежнему обеспечивает только выравнивание на 8 байт. Для получения дополнительной информации см. документацию вашего компоновщика.При использовании на структуре или члене структуры атрибут
alignedможет только увеличить выравнивание; чтобы уменьшить его, также должен быть указан атрибутpacked. При использовании в качестве части typedef атрибутalignedможет как увеличить, так и уменьшить выравнивание, а указание атрибутаpackedгенерирует предупреждение. warn_if_not_aligned (alignment)-
Этот атрибут задает порог для поля структуры, измеряемый в байтах. Если поле структуры выровнено ниже порога, будет выведено предупреждение. Например, объявление:
typedef unsigned long long __u64 __attribute__((aligned (4), warn_if_not_aligned (8))); struct foo { int i1; int i2; __u64 x; };приводит к выводу компилятором предупреждения для
struct foo, например, «предупреждение: выравнивание 4 для 'struct foo' меньше 8». Оно используется для определенияstruct fooтаким образом, чтоstruct fooимеет ту же структуру и поле структурыxимеет то же выравнивание, когда__u64выровнено либо на 4, либо на 8 байта. Выравниваниеstruct fooна 8 байт:struct __attribute__ ((aligned (8))) foo { int i1; int i2; __u64 x; };отключает предупреждение. Компилятор также выводит предупреждение, например, «предупреждение: смещение 'x' 12 в 'struct foo' не выровнено на 8», когда поле структуры имеет невыровненное смещение:
struct __attribute__ ((aligned (8))) foo { int i1; int i2; int i3; __u64 x; };Это предупреждение можно отключить с помощью -Wno-if-not-aligned.
alloc_size (position)alloc_size (position-1, position-2)-
Атрибут типа
alloc_sizeможет применяться к определению типа функции, возвращающей указатель и принимающей как минимум один аргумент целочисленного типа. Он указывает, что возвращаемый указатель указывает на объект, размер которого задается аргументом функции в позиции position-1, или произведением аргументов в позициях position-1 и position-2. Значимые размеры - положительные значения, меньшиеPTRDIFF_MAX. Другие размеры диагностируются при обнаружении. GCC использует эту информацию для улучшения результатов__builtin_object_size.Например, следующие объявления:
typedef __attribute__ ((alloc_size (1, 2))) void* calloc_type (size_t, size_t); typedef __attribute__ ((alloc_size (1))) void* malloc_type (size_t);
указывают, что
calloc_type- это тип функции, которая, как и стандартная функция Ccalloc, возвращает объект, размер которого задается произведением аргументов 1 и 2, и чтоmalloc_type, как и стандартная функция Cmalloc, возвращает объект, размер которого задается первым аргументом функции. copycopy (expression)-
Атрибут
copyприменяет набор атрибутов, с которыми был объявлен тип expression, к объявлению типа, к которому применяется атрибут. Этот атрибут предназначен для библиотек, которые определяют псевдонимы, которые, как ожидается, задают тот же набор атрибутов, что и алиасируемые символы. Атрибутcopyможет использоваться с типами, переменными или функциями. Однако тип символа, к которому применяется атрибут (либо переменная, либо функция), должен совпадать с типом символа, на который ссылается аргумент. Атрибутcopyкопирует только синтаксические и семантические атрибуты, но не атрибуты, влияющие на связь или видимость символа, такие какalias,visibility, илиweak. Атрибутdeprecatedтакже не копируется. См. Общие атрибуты функций. См. Общие атрибуты переменных.Например, предположим, что
struct Aниже определен в заголовке сторонней библиотеки с требованием выравниванияNи для принудительного вывода предупреждения всякий раз, когда переменная типа не выровнена таким образом из-за атрибутаpacked. Указание атрибутаcopyв определении несвязанногоstruct Bимеет эффект копирования всех соответствующих атрибутов из типа, на который ссылается выражение указателя, вstruct B.struct __attribute__ ((aligned (N), warn_if_not_aligned (N))) A { /* … */ }; struct __attribute__ ((copy ( (struct A *)0)) B { /* … */ }; deprecateddeprecated (msg)-
Атрибут
deprecatedприводит к выводу предупреждения, если тип используется где-либо в исходном файле. Это полезно при выявлении типов, которые, как ожидается, будут удалены в будущей версии программы. Если это возможно, предупреждение также включает местоположение объявления устаревшего типа, чтобы пользователи могли легко найти дополнительную информацию о том, почему тип устарел или что им следует сделать вместо этого. Обратите внимание, что предупреждения появляются только при использовании, и только если тип применяется к идентификатору, который сам по себе не объявлен устаревшим.typedef int T1 __attribute__ ((deprecated)); T1 x; typedef T1 T2; T2 y; typedef T1 T3 __attribute__ ((deprecated)); T3 z __attribute__ ((deprecated));
приводит к выводу предупреждения на строках 2 и 3, но не на строках 4, 5 или 6. Предупреждение не выдается для строки 4, потому что T2 не явно устарел. Строка 5 не имеет предупреждения, потому что T3 явно устарел. То же самое для строки 6. Необязательный аргумент msg, который должен быть строкой, печатается в предупреждении, если он присутствует. Управляющие символы в строке будут заменены последовательностями экранирования, а если опция -fmessage-length установлена в 0 (ее значение по умолчанию), то любые символы новой строки будут игнорироваться.
Атрибут
deprecatedтакже может использоваться для функций и переменных (см. Атрибуты функций, см. Атрибуты переменных).Сообщение, прикрепленное к атрибуту, зависит от установки опции -fmessage-length.
designated_init-
Этот атрибут может применяться только к типам структур. Он указывает, что любая инициализация объекта этого типа должна использовать обозначенные инициализаторы, а не позиционные. Цель этого атрибута - позволить программисту указать, что структура может измениться, и что, следовательно, полагание на позиционные инициализаторы приведет к будущим проблемам.
GCC по умолчанию выдает предупреждения на основе этого атрибута; используйте -Wno-designated-init для их подавления.
may_alias
-
Доступ через указатели на типы с этим атрибутом не подпадает под анализ алиасов на основе типов, а вместо этого предполагается, что они могут быть алиасами любого другого типа объектов. В контексте раздела 6.5, пункт 7 стандарта C99, выражение lvalue, разыменовывающее такой указатель, обрабатывается так, как будто имеет тип char. См. -fstrict-aliasing для получения дополнительной информации о проблемах с алиасами. Это расширение существует для поддержки некоторых векторизованных API, в которых указатели на один тип вектора разрешается делать алиасами указателей на другой тип вектора.
Обратите внимание, что объект типа с этим атрибутом не имеет каких-либо особых семантик.
Пример использования:
typedef short __attribute__ ((__may_alias__)) short_a; int main (void) { int a = 0x12345678; short_a *b = (short_a *) &a; b[1] = 0; if (a == 0x12345678) abort(); exit(0); }Если бы вы заменили
short_aнаshortв объявлении переменной, приведенная выше программа аварийно завершалась бы при компиляции с -fstrict-aliasing, что включено по умолчанию в -O2 и выше. mode (mode)-
Этот атрибут задает тип данных для объявления — любой тип, соответствующий режиму mode. Это позволяет запросить целочисленный или с плавающей запятой тип в соответствии с его шириной.
См. Режимы машины в документации по внутреннему устройству GNU Компилятора Коллекции (GCC), для списка возможных ключевых слов для mode. Вы также можете указать режим
byteили__byte__для обозначения режима, соответствующего целому числу длиной один байт,wordили__word__для режима целочисленного значения длиной одно слово, иpointerили__pointer__для режима, используемого для представления указателей. packed-
Этот атрибут, прикрепленный к
struct,union, или C++classопределению типа, указывает, что каждый его член (кроме полей битов шириной ноль) размещается для минимизации занимаемой памяти. Это эквивалентно указанию атрибутаpackedдля каждого из членов.При присоединении к
enumопределению, атрибутpackedуказывает, что должен быть использован самый маленький целочисленный тип. Указание флага -fshort-enums в командной строке эквивалентно указанию атрибутаpackedдля всехenumопределений.В следующем примере, члены
struct my_packed_structупакованы плотно, но внутренняя структура его членаsне упакована — для этогоstruct my_unpacked_structтакже должен быть упакован.struct my_unpacked_struct { char c; int i; }; struct __attribute__ ((__packed__)) my_packed_struct { char c; int i; struct my_unpacked_struct s; };Вы можете указать атрибут
packedтолько при определенииenum,struct,union, илиclass, а не наtypedef, который не определяет перечисление, структуру, объединение или класс. scalar_storage_order ("endianness")-
При присоединении к
unionилиstruct, этот атрибут устанавливает порядок хранения, т.е. порядок байтов, скалярных полей типа, а также полей массивов, компоненты которых являются скалярными. Поддерживаемые порядки байтов —big-endianиlittle-endian. Атрибут не влияет на поля, которые сами являютсяunion,structили массивом, компонента которого являетсяunionилиstruct, и эти поля могут иметь порядок хранения скаляров, отличный от порядка хранения окружающего типа.Этот атрибут поддерживается только для целей, использующих единообразный порядок хранения скаляров по умолчанию (к счастью, большинство из них), т.е. для целей, в которых скаляры хранятся либо в порядке big-endian, либо в порядке little-endian.
Дополнительные ограничения применяются к типам с обратным порядком хранения скаляров относительно порядка хранения скаляров для целевой системы:
- Взятие адреса скалярного поля
unionилиstructс обратным порядком хранения скаляров запрещено и приводит к ошибке. - Взятие адреса поля массива, компонента которого является скалярным,
unionилиstructс обратным порядком хранения скаляров разрешено, но приводит к предупреждению, если не указано -Wno-scalar-storage-order. - Взятие адреса
unionилиstructс обратным порядком хранения скаляров разрешено.
Эти ограничения существуют, потому что атрибут порядка хранения теряется при взятии адреса скаляра или адреса массива со скалярной компонентой, поэтому косвенное хранение по этому адресу, как правило, не работает. Тем не менее, второй случай разрешается для выполнения копирования блока из массива или в массив.
Кроме того, не поддерживается использование type punning или алиасирования для переключения порядка хранения; другими словами, к данному скалярному объекту нельзя получить доступ через различные типы, которые назначают ему разный порядок хранения.
- Взятие адреса скалярного поля
transparent_union-
Этот атрибут, прикрепленный к
unionопределению типа, указывает, что любой параметр функции, имеющий этот тип объединения, приводит к тому, что вызовы этой функции обрабатываются особым образом.Во-первых, аргумент, соответствующий типу прозрачного объединения, может быть любого типа в объединении; преобразование не требуется. Кроме того, если объединение содержит тип указателя, соответствующий аргумент может быть константой нулевого указателя или выражением указателя void; а если объединение содержит тип указателя void, соответствующий аргумент может быть любым выражением указателя. Если тип члена объединения — указатель, квалификаторы, такие как
constдля типа, на который ссылается указатель, должны соблюдаться так же, как и при обычных преобразованиях указателей.Во-вторых, аргумент передается в функцию с помощью правил вызова первого члена прозрачного объединения, а не правил вызова самого объединения. Все члены объединения должны иметь одинаковое машинное представление; это необходимо для правильной работы этой передачи аргумента.
Прозрачные объединения предназначены для функций библиотек, имеющих несколько интерфейсов по соображениям совместимости. Например, предположим, что функция
waitдолжна принимать значение типаint *для соответствия POSIX или значение типаunion wait *для соответствия интерфейсу 4.1BSD. Если бы параметрwaitбылvoid *,waitпринимал бы оба типа аргументов, но он также принимал бы и любой другой тип указателя, что делало бы проверку типа аргумента менее полезной. Вместо этого<sys/wait.h>может определить интерфейс следующим образом:typedef union __attribute__ ((__transparent_union__)) { int *__ip; union wait *__up; } wait_status_ptr_t; pid_t wait (wait_status_ptr_t);Этот интерфейс позволяет передавать аргументы либо типа
int *, либо типаunion wait *, используя соглашение о вызовеint *. Программа может вызватьwaitс аргументами обоих типов:int w1 () { int w; return wait (&w); } int w2 () { union wait w; return wait (&w); }С этим интерфейсом реализация
waitможет выглядеть так:pid_t wait (wait_status_ptr_t p) { return waitpid (-1, p.__ip, 0); } unused-
При присоединении к типу (включая
unionилиstruct) этот атрибут означает, что переменные этого типа могут быть потенциально неиспользуемыми. GCC не выводит предупреждение для переменных этого типа, даже если переменная, кажется, ничего не делает. Это часто происходит с классами блокировки или потоков, которые обычно определяются, а затем не используются, но содержат конструкторы и деструкторы, имеющие функции учёта, которые не являются тривиальными. vector_size (bytes)-
Этот атрибут указывает размер вектора для типа, измеренный в байтах. Тип, к которому он применяется, называется основным типом. Аргумент bytes должен быть положительной степенью двойки, кратной размеру основного типа. Например, следующие объявления:
typedef __attribute__ ((vector_size (32))) int int_vec32_t ; typedef __attribute__ ((vector_size (32))) int* int_vec32_ptr_t; typedef __attribute__ ((vector_size (32))) int int_vec32_arr3_t[3];
определяют
int_vec32_tкак 32-байтовый векторный тип, составленный из единиц размераint. С размеромintв 4 байта, тип определяет вектор из восьми единиц, по четыре байта каждая. Режим переменных типаint_vec32_t—V8SI.int_vec32_ptr_tзатем определяет указатель на такой векторный тип, аint_vec32_arr3_t— массив из трех таких векторов. Подробнее о манипулировании объектами векторных типов см. Векторные расширения.Этот атрибут применим только к целочисленным и с плавающей точкой скалярным типам. В объявлениях функций атрибут применяется к типу возвращаемого значения функции.
Например, следующее:
__attribute__ ((vector_size (16))) float get_flt_vec16 (void);
объявляет
get_flt_vec16как функцию, возвращающую 16-байтовый вектор с базовым типомfloat. visibility-
В C++, атрибут видимости (см. Атрибуты функций) также может быть применён к классам, структурам, объединениям и перечислениям. В отличие от других атрибутов типов, атрибут должен находиться между начальным ключевым словом и именем типа; он не может находиться после тела типа.
Обратите внимание, что видимость типа применяется к сущностям с размытой связью, связанными с классом (vtable, узел typeinfo и т.д.). В частности, если класс выброшен как исключение в одном объекте общего назначения и перехвачен в другом, класс должен иметь видимость по умолчанию. Иначе два объекта общего назначения не смогут использовать один и тот же узел typeinfo, и обработка исключений сломается.
Для указания нескольких атрибутов разделяйте их запятыми внутри двойных скобок: например, ‘__attribute__ ((aligned (16), packed))’.
Далее: Атрибуты типов ARC, Назад: Атрибуты типов [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gcc/Common-Type-Attributes.html