6.35.1 Атрибуты типов общего назначения
Следующие атрибуты типа поддерживаются на большинстве целевых платформ.
-
aligned aligned (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генерирует предупреждение. -
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— это тип функции, которая, подобно стандартной C-функцииcalloc, возвращает объект, размер которого задаётся произведением аргументов 1 и 2, и чтоmalloc_type, подобно стандартной C-функцииmalloc, возвращает объект, размер которого задаётся первым аргументом функции. -
copy copy (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 { /* … */ }; -
deprecated deprecated (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, который должен быть строкой, выводится в предупреждении, если он присутствует. Контрольные символы в строке будут заменены на последовательности escape, а если опция -fmessage-length установлена в 0 (по умолчанию), то все символы новой строки будут игнорироваться.
Атрибут
deprecatedтакже может использоваться для функций и переменных (см. Объявление атрибутов функций, см. Указание атрибутов переменных.)Сообщение, прикреплённое к атрибуту, зависит от установки опции -fmessage-length.
-
designated_init -
Этот атрибут может быть применён только к типам структур. Он указывает, что любая инициализация объекта этого типа должна использовать обозначенные инициализаторы, а не позиционные. Цель этого атрибута — позволить программисту указать, что структура может измениться, и что, следовательно, полагание на позиционную инициализацию приведёт к будущим проблемам.
GCC по умолчанию выдаёт предупреждения на основе этого атрибута; используйте -Wno-designated-init для их подавления.
-
hardbool hardbool (false_value)hardbool (false_value, true_value)
-
Этот атрибут может быть применён только к целочисленным типам в C для введения защищённых булевых типов. Он преобразует целочисленный тип в булеподобный тип с тем же размером и точностью, который использует указанные значения в качестве представлений для
falseиtrue. Внутри он фактически является перечислением, но его наблюдаемое поведение подобно_Bool, за исключением строгих внутренних представлений, проверенных проверками во время выполнения.Если true_value опущено, используется побитовое отрицание false_value. Если false_value опущено, используется ноль. Названные значения представлений должны быть различны при преобразовании к исходному целочисленному типу. Более узкие битовые поля отклоняются, если представления становятся неразличимыми.
Значения таких типов автоматически распадаются до
_Bool, в этот момент выбранные значения представления сопоставляются с соответствующими_Boolзначениями. Если представленное значение не определено на этапе компиляции, как false_value или true_value, вызов__builtin_trapпроисходит во время выполнения, если это не так. Это то, что делает их защищёнными булевыми типами.При преобразовании скалярных типов к таким защищённым булевым типам, неявно или явно, поведение соответствует преобразованию в
_Bool, за которым следует сопоставлениеfalseиtrueсоответственно с false_value и true_value.typedef char __attribute__ ((__hardbool__ (0x5a))) hbool; hbool first = 0; /* False, stored as (char)0x5a. */ hbool second = !first; /* True, stored as ~(char)0x5a. */ static hbool zeroinit; /* False, stored as (char)0x5a. */ auto hbool uninit; /* Undefined, may trap. */
При инициализации переменной или поля защищённого булевого типа нулём (предположительно хранящегося в статической памяти), неявный инициализатор нулём преобразуется в
_Bool, а затем в защищённый булевый тип, так что начальное значение является защищённым представлением дляfalse. Использование этого значения определено. Это не относится к случаям, когда переменные и поля таких типов не инициализированы (предположительно хранящиеся в автоматической или динамической памяти): их значения неопределённы, и их использование вызывает неопределённое поведение. Их использование может вызвать ошибку или не вызвать, в зависимости от битов, хранящихся в памяти (используемой) для переменной, если таковая имеется, и от оптимизаций, которые может выполнить компилятор, исходя из того, что использование неинициализированных значений вызывает неопределённое поведение.Пользователи -ftrivial-auto-var-init должны понимать, что битовые шаблоны, используемые в качестве инициализаторов, не преобразуются в
hardboolтипы, поэтому использованиеhardboolпеременной, которая неявно инициализируется с помощью -ftrivial-auto-var-init, может вызвать ошибку, если значения представлений, выбранные дляfalseиtrueне совпадают с инициализатором.Поскольку это расширение языка, доступное только в C, взаимодействие с другими языками может вызвать трудности. Оно должно взаимодействовать с булевыми типами Ada, определёнными с тем же размером и эквивалентными предложениями представления, а также с перечислениями или другими целочисленными типами языков, которые соответствуют выбранному целочисленному типу C.
-
may_alias -
Доступ через указатели к типам с этим атрибутом не подпадает под анализ алиасов на основе типов, а вместо этого предполагается, что они могут быть алиасами любых других типов объектов. В контексте раздела 6.5 абзаца 7 стандарта C99 выражение lvalue, разыменовывающее такой указатель, обрабатывается как имеющее тип символа. См. -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 Compiler Collection (GCC) для списка возможных ключевых слов для mode. Вы также можете указать режим
byteили__byte__для обозначения режима, соответствующего однобайтовому целому числу,wordили__word__для режима одного слова целого числа иpointerили__pointer__для режима, используемого для представления указателей. -
objc_root_class (Objective-C and Objective-C++ only) -
Этот атрибут помечает класс как корневой класс и, таким образом, позволяет компилятору устранить любые предупреждения об отсутствующем суперклассе и выполнить дополнительные проверки необходимых методов по мере необходимости.
-
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с обратным порядком хранения скаляров разрешено.
Эти ограничения существуют потому, что атрибут порядка хранения теряется при взятии адреса скаляра или массива со скалярной компонентой, поэтому косвенное хранение через этот адрес, как правило, не работает. Однако второй случай разрешён для возможности выполнения блочного копирования в или из массива.
Кроме того, использование типов пунения или алиасов для переключения порядка хранения не поддерживается; другими словами, если к данному скалярному объекту можно получить доступ через различные типы, которые назначают ему другой порядок хранения, то поведение является неопределённым.
- Взятие адреса скалярного поля
-
strub
-
Этот атрибут определяет свойства очистки стека для функций и переменных, так что функции, которые обращаются к конфиденциальным данным, могут иметь свои кадры стека обнулены при возврате или распространении исключений. Это может быть включено явно, выбрав определенные
strubрежимы для конкретных функций, или неявно с помощьюstrubпеременных.Как атрибут типа, он прикрепляется к типам, даже если указан в объявлениях функций и переменных. При применении к типам функций он принимает необязательный строковый аргумент. При применении к типу указателя на функцию, если необязательный аргумент указан, он передается типу функции.
/* A strub variable. */ int __attribute__ ((strub)) var; /* A strub variable that happens to be a pointer. */ __attribute__ ((strub)) int *strub_ptr_to_int; /* A pointer type that may point to a strub variable. */ typedef int __attribute__ ((strub)) *ptr_to_strub_int_type; /* A declaration of a strub function. */ extern int __attribute__ ((strub)) foo (void); /* A pointer to that strub function. */ int __attribute__ ((strub ("at-calls"))) (*ptr_to_strub_fn)(void) = foo;Функция, связанная с
at-callsstrubрежимом (strub("at-calls"), или простоstrub), претерпевает изменения интерфейса. Ее вызывающие функции корректируются для соответствия изменениям и для очистки (заполнения нулями) пространства стека, используемого вызываемой функцией после возврата. Изменение интерфейса делает тип функции несовместимым с необработанным, но в остальном эквивалентным типом, поэтому каждое объявление и каждый тип, которые могут быть использованы для вызова функции, должны быть связаны с этим режимом очистки.Функция, связанная с
internalstrubрежимом (strub("internal")), сохраняет неизмененный, совместимый с типом интерфейс, но она может быть преобразована в обертку, которая вызывает обернутое тело с помощью пользовательского интерфейса. Обёртка затем очищает пространство стека, используемое обернутым телом. Хотя пространство стека обернутого тела очищается, пространство стека обёртки нет, поэтому аргументы и возвращаемые значения могут оставаться неочищенными даже при вызове такой функции другой функцией, которая включаетstrub. Вот почему при компиляции с -fstrub=strict контекстstrubне допускается вызыватьinternalstrubфункции./* A declaration of an internal-strub function. */ extern int __attribute__ ((strub ("internal"))) bar (void); int __attribute__ ((strub)) baz (void) { /* Ok, foo was declared above as an at-calls strub function. */ foo (); /* Not allowed in strict mode, otherwise allowed. */ bar (); }Автоматически выделенная переменная, связанная с атрибутом
strub, приводит к тому, что функция (непосредственно) окружающая функцию имеетstrubвключённым.Статически выделенная переменная, связанная с атрибутом
strub, заставляет функции, которые считывают ее, через ееstrubтип данных, иметьstrubвключённым. Чтение данных путем разыменования указателя на тип данныхstrubимеет тот же эффект. Примечание: атрибут не переносится от составного типа к типам его компонентов, поэтому ожидаемого эффекта может не быть получено с нескалярными типами.При выборе
strub-включенного режима для функции, которая не явно связана с ним, из-заstrubпеременных или указателей на данные, функция должна удовлетворять требованиям жизнеспособности режимаinternal(см. ниже), даже когдаat-callsрежим также жизнеспособен и, будучи более эффективным, в конечном итоге выбирается в качестве оптимизации./* zapme is implicitly strub-enabled because of strub variables. Optimization may change its strub mode, but not the requirements. */ static int zapme (int i) { /* A local strub variable enables strub. */ int __attribute__ ((strub)) lvar; /* Reading strub data through a pointer-to-strub enables strub. */ lvar = * (ptr_to_strub_int_type) &i; /* Writing to a global strub variable does not enable strub. */ var = lvar; /* Reading from a global strub variable enables strub. */ return var; }Контекст
strub— это тело (в отличие от интерфейса) функции, у которой включеноstrub, будь то явно, черезat-callsилиinternalрежимы, или неявно из-заstrubпеременных или параметров командной строки.Функция типа, связанного с
disabledstrubрежимом (strub("disabled")) не будет иметь своего собственного пространства стека, очищенного. К таким функциям нельзя обращаться изнутри контекстовstrub.Чтобы функция могла быть вызвана изнутри контекстов
strubбез очистки её пространства стека, свяжите её сcallablestrubрежимом (strub("callable")) .Когда функции не присвоен режим
strub, явно или неявно, режим по умолчаниюcallable, за исключением компиляции с -fstrub=strict, которая устанавливает режимstrubпо умолчанию какdisabled.extern int __attribute__ ((strub ("callable"))) bac (void); extern int __attribute__ ((strub ("disabled"))) bad (void); /* Implicitly disabled with -fstrub=strict, otherwise callable. */ extern int bah (void); int __attribute__ ((strub)) bal (void) { /* Not allowed, bad is not strub-callable. */ bad (); /* Ok, bac is strub-callable. */ bac (); /* Not allowed with -fstrub=strict, otherwise allowed. */ bah (); }Типы функций, помеченные
callableиdisabledне являются взаимно совместимыми типами, но базовые интерфейсы совместимы, поэтому безопасно преобразовывать указатели между ними, а также использовать такие указатели или альтернативные объявления для их вызова. Интерфейсы также взаимозаменяемы между ними иinternal(но неat-calls!), но добавлениеinternalк типу указателя не заставит функцию, на которую указывает указатель, выполнять очистку стека.void __attribute__ ((strub)) bap (void) { /* Assign a callable function to pointer-to-disabled. Flagged as not quite compatible with -Wpedantic. */ int __attribute__ ((strub ("disabled"))) (*d_p) (void) = bac; /* Not allowed: calls disabled type in a strub context. */ d_p (); /* Assign a disabled function to pointer-to-callable. Flagged as not quite compatible with -Wpedantic. */ int __attribute__ ((strub ("callable"))) (*c_p) (void) = bad; /* Ok, safe. */ c_p (); /* Assign an internal function to pointer-to-callable. Flagged as not quite compatible with -Wpedantic. */ c_p = bar; /* Ok, safe. */ c_p (); /* Assign an at-calls function to pointer-to-callable. Flaggged as incompatible. */ c_p = bal; /* The call through an interface-incompatible type will not use the modified interface expected by the at-calls function, so it is likely to misbehave at runtime. */ c_p (); }Контексты
Strubникогда не встраиваются в контексты, не являющиесяstrub. Когда функцияinternal-очистки стека разбивается, оболочка часто может быть встроена, но обернутое тело никогда не встраивается. Функция, помеченная какalways_inline, даже если ей явно назначен режим очисткиinternal, не будет обернута, поэтому ее тело встраивается по мере необходимости.inline int __attribute__ ((strub ("at-calls"))) inl_atc (void) { /* This body may get inlined into strub contexts. */ } inline int __attribute__ ((strub ("internal"))) inl_int (void) { /* This body NEVER gets inlined, though its wrapper may. */ } inline int __attribute__ ((strub ("internal"), always_inline)) inl_int_ali (void) { /* No internal wrapper, so this body ALWAYS gets inlined, but it cannot be called from non-strub contexts. */ } void __attribute__ ((strub ("disabled"))) bat (void) { /* Not allowed, cannot inline into a non-strub context. */ inl_int_ali (); }Некоторые параметры командной строки -fstrub=* неявно включают
strubрежимы там, где это возможно. Режимstrubжизнеспособен для функции только если функция подходит для этого режима и если выполняются другие условия, описанные ниже. Если функция не подходит для режима, попытки явного связывания её с этим режимом отклоняются с сообщением об ошибке. Если она подходит, этот режим может быть назначен явно через этот атрибут, но неявное назначение через параметры командной строки может потребовать дополнительных условий жизнеспособности.Функция не подходит для режима
at-callsstrubесли запрошен другой режимstrub, если присутствует атрибутnoipa, или если она вызывает__builtin_apply_args. РежимAt-callsstrub, если он не запрошен через тип функции, жизнеспособен только для подходящей функции, если функция невидима для других единиц трансляции, если её адрес не взят, и если она никогда не вызывается с переопределением типа функции./* bar is eligible for at-calls strub mode, but not viable for that mode because it is visible to other units. It is eligible and viable for internal strub mode. */ void bav () {} /* setp is eligible for at-calls strub mode, but not viable for that mode because its address is taken. It is eligible and viable for internal strub mode. */ void setp (void) { static void (*p)(void); = setp; }Функция не подходит для режима
internalstrubесли запрошен другой режимstrub, или если присутствует атрибутnoipa. Для функцииalways_inlineвыполнение этих требований достаточно для её пригодности. Любая функция, у которой есть атрибутnoclone, которая использует такие расширения, как нелокальные метки, вычисленные переходы, альтернативные интерфейсы передачи аргументов переменной,__builtin_next_arg, или__builtin_return_address, или которая принимает слишком много аргументов (около 64К), не подходит, если только она не являетсяalways_inline. Для режимаinternalstrubвсе подходящие функции жизнеспособны./* flop is not eligible, thus not viable, for at-calls strub mode. Likewise for internal strub mode. */ __attribute__ ((noipa)) void flop (void) {} /* flip is eligible and viable for at-calls strub mode. It would be ineligible for internal strub mode, because of noclone, if it weren't for always_inline. With always_inline, noclone is not an obstacle, so it is also eligible and viable for internal strub mode. */ inline __attribute__ ((noclone, always_inline)) void flip (void) {} -
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); } -
unavailable unavailable (msg)-
Атрибут
unavailableведёт себя так же, как и атрибутdeprecated, но генерирует ошибку вместо предупреждения. Он используется для обозначения того, что тип (возможно, ранееdeprecated) больше не может быть использован.Атрибут
unavailableтакже может быть использован для функций и переменных (см. Объявление атрибутов функций, см. Указание атрибутов переменных.) -
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++, атрибут видимости (см. Объявление атрибутов функций) также может применяться к типам class, struct, union и enum. В отличие от других атрибутов типа, атрибут должен располагаться между ключевым словом и именем типа; он не может появляться после тела типа.
Обратите внимание, что видимость типа применяется к неявным связным сущностям, связанным с классом (vtable, узел typeinfo и т. д.). В частности, если класс выброшен как исключение в одном общем объекте и перехвачен в другом, класс должен иметь стандартную видимость. В противном случае два общих объекта не смогут использовать один и тот же узел typeinfo, и обработка исключений будет нарушена.
-
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.
Для указания нескольких атрибутов разделяйте их запятыми в двойных скобках: например, «__attribute__ ((aligned (16), packed))».
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Type-Attributes.html