Spec-Zone.ru › GCC 4

6.37 Указание атрибутов типов

Ключевое слово __attribute__ позволяет указывать специальные атрибуты типов struct и union при определении таких типов. Это ключевое слово следует за указанием атрибута в двойных скобках. В настоящее время определено семь атрибутов для типов: aligned, packed, transparent_union, unused, deprecated, visibility, и may_alias. Другие атрибуты определены для функций (см. Атрибуты функций) и для переменных (см. Атрибуты переменных).

Вы также можете указать любой из этих атрибутов с помощью «__» перед и после его ключевого слова. Это позволяет использовать эти атрибуты в заголовочных файлах, не беспокоясь о возможном макросе с тем же именем. Например, вы можете использовать __aligned__ вместо aligned.

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

Для типа перечисления, структуры или объединения вы можете указать атрибуты либо между тегом перечисления, структуры или объединения и именем типа, либо сразу после закрывающей фигурной скобки определения. Предпочтительнее использовать первый синтаксис.

См. Синтаксис атрибутов для получения подробной информации о точном синтаксисе использования атрибутов.

aligned (alignment)
Этот атрибут задаёт минимальное выравнивание (в байтах) для переменных указанного типа. Например, объявления:
struct S { short f[3]; } __attribute__ ((aligned (8)));
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 S { short f[3]; } __attribute__ ((aligned));

Всякий раз, когда вы опускаете множитель выравнивания в спецификации атрибута aligned, компилятор автоматически устанавливает выравнивание для типа до максимального выравнивания, которое когда-либо используется для любого типа данных на целевой машине, для которой вы компилируете. Это часто повышает эффективность операций копирования, поскольку компилятор может использовать инструкции копирования больших блоков памяти при выполнении копирования к переменным с типами, которые вы выровняли таким образом.

В приведённом примере, если размер каждого short составляет 2 байта, то размер всего типа struct S равен 6 байтам. Наименьшая степень двойки, которая больше или равна этому, равна 8, поэтому компилятор устанавливает выравнивание для всего типа struct S в 8 байт.

Обратите внимание, что хотя вы можете попросить компилятор выбрать эффективное с точки зрения времени выравнивание для заданного типа и затем объявить только отдельные самостоятельные объекты этого типа, способность компилятора выбирать эффективное с точки зрения времени выравнивание в первую очередь полезна только в случае, если вы планируете создавать массивы переменных с соответствующим (эффективно выровненным) типом. Если вы объявляете или используете массивы переменных с эффективно выровненным типом, то, скорее всего, ваша программа также выполняет арифметические операции с указателями (или индексирование, что фактически то же самое) над указателями на соответствующий тип, и код, генерируемый компилятором для этих операций арифметики указателей, часто более эффективен для эффективно выровненных типов, чем для других типов.

Атрибут aligned может только увеличить выравнивание; но вы можете уменьшить его, указав packed тоже. См. ниже.

Обратите внимание, что эффективность атрибутов aligned может быть ограничена внутренними ограничениями вашего компоновщика. На многих системах компоновщик может только организовать выравнивание переменных до определённого максимального выравнивания. (Для некоторых компоновщиков максимальное поддерживаемое выравнивание может быть очень маленьким.) Если ваш компоновщик может выравнивать переменные только до максимального выравнивания в 8 байт, то указание aligned(16) в атрибуте __attribute__ всё равно обеспечивает только 8-байтовое выравнивание. Для получения дополнительной информации обратитесь к документации вашего компоновщика.

packed
Этот атрибут, присоединённый к определению типа struct или union, указывает, что каждый член (кроме полей шириной ноль) структуры или объединения размещается для минимизации требуемого объёма памяти. При присоединении к определению enum, он указывает, что должен использоваться наименьший целочисленный тип.

Указание этого атрибута для типов struct и union эквивалентно указанию атрибута 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;
  };

Вы можете указать этот атрибут только в определении enum, struct или union, а не в определении typedef, которое не определяет также перечисление, структуру или объединение.

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 не выводит предупреждение для любых переменных этого типа, даже если переменная, похоже, ничего не делает. Это часто бывает с классами блокировки или потоков, которые обычно определяются, а затем не используются, но содержат конструкторы и деструкторы, которые имеют тривиальные функции учёта.
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, который должен быть строкой, выводится в предупреждении, если присутствует.

Атрибут deprecated также может использоваться для функций и переменных (см. Атрибуты функций, см. Атрибуты переменных.)

may_alias
Доступ через указатели на типы с этим атрибутом не подпадает под анализ алиасинга на основе типа, а вместо этого предполагается, что они могут быть алиасами для любых других объектов. В контексте раздела 6.5 абзаца 7 стандарта C99 выражение lvalue, де-реферирующее такой указатель, обрабатывается так, как будто имеет тип символа. См. -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 или более поздних версиях GCC.

visibility
В C++, атрибут видимости (см. Атрибуты функций) также может применяться к классам, структурам, объединениям и перечислениям. В отличие от других атрибутов типов, атрибут должен появляться между начальным ключевым словом и именем типа; он не может появляться после тела типа.

Обратите внимание, что видимость типа применяется к неявным ссылкам, связанным с классом (vtable, узел typeinfo и т.д.). В частности, если класс брошен как исключение в одном общем объекте и перехвачен в другом, класс должен иметь видимость по умолчанию. В противном случае два общих объекта не могут использовать один и тот же узел typeinfo, и обработка исключений будет нарушена.

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

6.37.1 Атрибуты типов ARM

На тех целевых платформах ARM, которые поддерживают dllimport (таких как Symbian OS), вы можете использовать атрибут notshared для указания того, что виртуальная таблица и другие подобные данные для класса не должны экспортироваться из DLL. Например:

class __declspec(notshared) C {
public:
  __declspec(dllimport) C();
  virtual void f();
}

__declspec(dllexport)
C::C() {}

В этом коде C::C экспортируется из текущей DLL, но виртуальная таблица для C не экспортируется. (Вы можете использовать __attribute__ вместо __declspec, если предпочитаете, но большинство кода Symbian OS использует __declspec.)

6.37.2 Атрибуты типов MeP

Многие атрибуты переменных MeP могут применяться и к типам. В частности, атрибуты based, tiny, near, и far могут быть применены к обоим. Атрибуты io и cb не могут быть применены к типам.

6.37.3 Атрибуты типов i386

Для конфигураций i386 в настоящее время определены два атрибута: ms_struct и gcc_struct.

ms_struct
gcc_struct
Если packed используется для структуры или используются битовые поля, то возможно, что Microsoft ABI упаковывает их по-другому, чем GCC. Особенно при перемещении упакованных данных между функциями, скомпилированными с GCC и родным компилятором Microsoft (как через вызов функции, так и как данные в файле), может потребоваться доступ к обоим форматам.

В настоящее время -m[no-]ms-bitfields предоставляется для компиляторов Microsoft Windows X86, чтобы соответствовать родному компилятору Microsoft.

6.37.4 Атрибуты типов PowerPC

Для конфигураций PowerPC в настоящее время определены три атрибута: altivec, ms_struct и gcc_struct.

Для получения полной документации по атрибутам ms_struct и gcc_struct см. документацию в Атрибуты типов i386.

Атрибут altivec позволяет объявлять типы данных векторов AltiVec, поддерживаемые Руководством по программированию AltiVec. Атрибут требует аргумента для указания одного из трех типов векторов: vector__, pixel__ (всегда следует за unsigned short) и bool__ (всегда следует за unsigned).

__attribute__((altivec(vector__)))
__attribute__((altivec(pixel__))) unsigned short
__attribute__((altivec(bool__))) unsigned

Эти атрибуты в основном предназначены для поддержки ключевых слов __vector, __pixel, и __bool AltiVec.

6.37.5 Атрибуты типов SPU

SPU поддерживает атрибут spu_vector для типов. Этот атрибут позволяет объявлять типы данных векторов, поддерживаемые спецификацией расширений языка Sony/Toshiba/IBM SPU. Он предназначен для поддержки ключевого слова __vector.

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

Spec-Zone.ru

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