Spec-Zone.ru › GCC 12

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. Другие размеры распознаются как диагностические. 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 функции.

copy
copy (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 { /* … */ };
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.

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 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API