Spec-Zone.ru › GCC 10

Следующее: Атрибуты типов ARC, Выше: Указание атрибутов типов [Оглавление][Индекс]

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 применяет набор атрибутов, с которыми тип 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, чтобы их отключить.

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) Internals для списка возможных ключевых слов для 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, и возможно, что у этих полей порядок хранения скаляров отличается от порядка хранения скаляров в enclosing типе.

Этот атрибут поддерживается только для целей, которые используют единый порядок хранения скаляров по умолчанию (к счастью, большинство из них), т. е. для целей, которые хранят скаляры либо все в формате big-endian, либо все в формате little-endian.

Для типов с обратным порядком хранения скаляров относительно порядка хранения скаляров целевой платформы применяются дополнительные ограничения:

  • Взятие адреса скалярного поля union или struct с обратным порядком хранения скаляров запрещено и приводит к ошибке.
  • Взятие адреса массива, компонентом которого является скаляр, поля union или struct с обратным порядком хранения скаляров разрешено, но приводит к предупреждению, если не указано -Wno-scalar-storage-order.
  • Взятие адреса union или struct с обратным порядком хранения скаляров разрешено.

Эти ограничения существуют, потому что атрибут порядка хранения теряется при взятии адреса скаляра или адреса массива со скалярным компонентом, поэтому косвенное хранение по этому адресу обычно не работает. Тем не менее, во втором случае разрешено выполнять копирование блока в массив или из массива.

Кроме того, использование punning типов или алиасинга для переключения порядка хранения не поддерживается; то есть, к одному скалярному объекту нельзя получить доступ через различные типы, которые присваивают ему разные порядки хранения.

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, и обработка исключений будет нарушена.

Для указания нескольких атрибутов разделяйте их запятыми в двойных скобках: например, ‘__attribute__ ((aligned (16), packed))’.

Далее: Атрибуты типов ARC, Наверх: Указание атрибутов типов [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Common-Type-Attributes.html

Spec-Zone.ru

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