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вызывает предупреждение. -
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. Другие размеры диагностируются при обнаружении.Например, следующие объявления:
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, возвращает объект, размер которого определяется аргументом 1 функции. -
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, который должен быть строкой, печатается в предупреждении, если он присутствует. Управляющие символы в строке будут заменены на последовательности экранирования, и если опция -fmessage-length установлена в 0 (по умолчанию), то любые символы новой строки будут проигнорированы.
Атрибут
deprecatedтакже может использоваться для функций и переменных (см. Объявление атрибутов функций, см. Указание атрибутов переменных).Сообщение, прикреплённое к атрибуту, зависит от значения опции -fmessage-length.
-
unavailable unavailable (msg)-
Атрибут
unavailableработает так же, как и атрибутdeprecated, но генерирует ошибку вместо предупреждения. Он используется для указания того, что тип (возможно, ранееdeprecated) больше не может использоваться.Атрибут
unavailableтакже может использоваться для функций и переменных (см. Объявление атрибутов функций, см. Указание атрибутов переменных). -
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с обратным порядком хранения скаляров разрешено.
Эти ограничения существуют, потому что атрибут порядка хранения теряется при получении адреса скаляра или адреса массива со скалярным компонентом, поэтому косвенное хранение по этому адресу обычно не работает. Однако второй случай разрешён для возможности выполнения копирования блока из массива или в массив.
Кроме того, использование приведения типов или алиасирования для переключения порядка хранения не поддерживается; другими словами, если к данному скалярному объекту можно получить доступ через различные типы, которые присваивают ему другой порядок хранения, то поведение является неопределённым.
- Получение адреса скалярного поля
-
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 байта, то тип определяет вектор из восьми единиц, каждая по 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, и обработка исключений будет нарушена.
-
objc_root_class (Objective-C and Objective-C++ only) -
Этот атрибут помечает класс как корневой класс и, таким образом, позволяет компилятору исключить любые предупреждения о пропущенном суперклассе и выполнить дополнительные проверки необходимых методов по мере необходимости.
Для указания нескольких атрибутов, разделяйте их запятыми внутри двойных скобок: например, ‘__attribute__ ((aligned (16), packed))’.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-13.3.0/gcc/Common-Type-Attributes.html