Spec-Zone.ru › GCC 13

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

Spec-Zone.ru

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