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— это тип функции, которая, подобно стандартной C-функцииcalloc, возвращает объект, размер которого определяется произведением аргументов 1 и 2, и чтоmalloc_type, подобно стандартной C-функцииmalloc, возвращает объект, размер которого определяется аргументом 1 функции. copycopy (expression)-
Атрибут
copyприменяет набор атрибутов, с которыми был объявлен тип выражения, к объявлению типа, к которому применяется атрибут. Атрибут предназначен для библиотек, определяющих псевдонимы, которые ожидается будут указывать на тот же набор атрибутов, что и алиасируемые символы. Атрибут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, который должен быть строкой, выводится в предупреждении, если он присутствует. Управляющие символы в строке будут заменены последовательностями escape, и если опция -fmessage-length установлена в 0 (значение по умолчанию), любые символы новой строки будут проигнорированы.
Атрибут
deprecatedтакже может использоваться для функций и переменных (см. Атрибуты функций, см. Атрибуты переменных).Сообщение, прикреплённое к атрибуту, зависит от настроек опции -fmessage-length.
unavailableunavailable (msg)-
Атрибут
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 Compiler Collection (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 байта тип определяет вектор из восьми единиц по четыре байта каждая. Режим переменных типа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))’.
Далее: Атрибуты типов ARC, Назад: Атрибуты типов [Содержание][Указатель]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Common-Type-Attributes.html