Spec-Zone.ru › GCC 4

6.36 Указание атрибутов переменных

Ключевое слово __attribute__ позволяет указать специальные атрибуты переменных или полей структуры. Это ключевое слово следует за указанием атрибута в двойных скобках. Некоторые атрибуты в настоящее время определены обобщенно для переменных. Другие атрибуты определены для переменных на конкретных целевых системах. Другие атрибуты доступны для функций (см. Атрибуты функций) и для типов (см. Атрибуты типов). Другие фронтенды могут определять больше атрибутов (см. Расширения языка C++).

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

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

aligned (alignment)
Этот атрибут задаёт минимальное выравнивание для переменной или поля структуры, измеряемое в байтах. Например, объявление:
int x __attribute__ ((aligned (16))) = 0;

приводит к тому, что компилятор выделяет глобальную переменную x на границе 16 байт. На процессоре 68040 это можно использовать совместно с выражением asm для доступа к инструкции move16, которая требует операндов, выровненных по 16 байтам.

Вы также можете задать выравнивание полей структуры. Например, чтобы создать пару полей int, выровненных по двойному слову, можно написать:

struct foo { int x[2] __attribute__ ((aligned (8))); };

Это альтернатива созданию объединения с членом double, что заставляет объединение быть выровненным по двойному слову.

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

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

short array[3] __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));

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

При использовании на структуре или члене структуры атрибут aligned может только увеличить выравнивание; чтобы уменьшить его, также должен быть указан атрибут packed. При использовании в качестве части typedef атрибут aligned может как увеличить, так и уменьшить выравнивание, а указание атрибута packed генерирует предупреждение.

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

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

cleanup (cleanup_function)
Атрибут cleanup выполняет функцию, когда переменная выходит из области видимости. Этот атрибут может быть применён только к переменным авто-функции; он не может быть применён к параметрам или переменным со статическим сроком хранения. Функция должна принимать один параметр — указатель на тип, совместимый с переменной. Значение возврата функции (если есть) игнорируется.

Если -fexceptions включено, то cleanup_function выполняется во время разворачивания стека, которое происходит во время обработки исключения. Обратите внимание, что атрибут cleanup не позволяет поймать исключение, а только выполнить действие. Не определено, что произойдёт, если cleanup_function не вернётся нормально.

common
nocommon
Атрибут common просит GCC разместить переменную в общем хранилище. Атрибут nocommon просит обратное — выделить память для неё непосредственно.

Эти атрибуты переопределяют значение по умолчанию, выбираемое флагами -fno-common и -fcommon соответственно.

deprecated
deprecated (msg)
Атрибут deprecated приводит к появлению предупреждения, если переменная используется где-либо в исходном файле. Это полезно при идентификации переменных, которые ожидается удалить в будущей версии программы. Предупреждение также включает местоположение объявления устаревшей переменной, чтобы пользователи могли легко найти дополнительную информацию о том, почему переменная устарела или что им следует сделать вместо этого. Обратите внимание, что предупреждение появляется только при использовании:
extern int old_var __attribute__ ((deprecated));
extern int old_var;
int new_fn () { return old_var; }

приводит к предупреждению на строке 3, но не на строке 2. Необязательный аргумент msg, который должен быть строкой, отображается в предупреждении, если он присутствует.

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

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

Вы также можете указать режим byte или __byte__ для указания режима, соответствующего целому числу с одним байтом, word или __word__ для режима целого числа с одним словом и pointer или __pointer__ для режима, используемого для представления указателей.

packed
Атрибут packed указывает, что переменная или поле структуры должно иметь наименьшее возможное выравнивание — один байт для переменной и один бит для поля, если вы не укажете большее значение с помощью атрибута aligned.

Вот структура, в которой поле x упаковано, так что оно сразу следует за a:

struct foo
{
  char a;
  int x[2] __attribute__ ((packed));
};

Примечание: Серии GCC 4.1, 4.2 и 4.3 игнорируют атрибут packed для битовых полей типа char. Это было исправлено в GCC 4.4, но изменение может привести к различиям в структуре расположения. См. документацию -Wpacked-bitfield-compat для получения дополнительной информации.

section ("section-name")
Обычно компилятор помещает сгенерированные объекты в секции, такие как data и bss. Однако иногда вам нужны дополнительные секции или вам нужно, чтобы определённые переменные появлялись в специальных секциях, например, для сопоставления со специальным оборудованием. Атрибут section указывает, что переменная (или функция) находится в определённой секции. Например, эта небольшая программа использует несколько специфичных имён секций:
struct duart a __attribute__ ((section ("DUART_A"))) = { 0 };
struct duart b __attribute__ ((section ("DUART_B"))) = { 0 };
char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };
int init_data __attribute__ ((section ("INITDATA")));

main()
{
  /* Initialize stack pointer */
  init_sp (stack + sizeof (stack));

  /* Initialize initialized data */
  memcpy (&init_data, &data, &edata - &data);

  /* Turn on the serial ports */
  init_duart (&a);
  init_duart (&b);
}

Используйте атрибут section со глобальными переменными, а не с локальными переменными, как показано в примере.

Вы можете использовать атрибут section с инициализированными или неинициализированными глобальными переменными, но линкер требует, чтобы каждый объект был определён один раз, за исключением того, что неинициализированные переменные предварительно помещаются в секцию common (или bss) и могут быть многократно «определены». Использование атрибута section изменяет секцию, в которую попадает переменная, и может привести к ошибке линкера, если неинициализированная переменная имеет несколько определений. Вы можете принудительно инициализировать переменную с флагом -fno-common или атрибутом nocommon.

Некоторые форматы файлов не поддерживают произвольные секции, поэтому атрибут section недоступен на всех платформах. Если вам нужно сопоставить всё содержимое модуля с определённой секцией, воспользуйтесь возможностями линкера.

shared
В Microsoft Windows, помимо размещения определений переменных в именованной секции, секция также может быть разделена между всеми запущенными копиями исполняемого файла или DLL. Например, эта небольшая программа определяет общие данные, помещая их в именованную секцию shared и отмечая секцию как разделяемую:
int foo __attribute__((section ("shared"), shared)) = 0;

int
main()
{
  /* Read and write foo.  All running
     copies see the same value.  */
  return 0;
}

Вы можете использовать атрибут shared только вместе с атрибутом section с полностью инициализированным глобальным определением из-за работы линковщиков. См. атрибут section для получения дополнительной информации.

Атрибут shared доступен только в Microsoft Windows.

tls_model ("tls_model")
Атрибут tls_model задаёт модель локального хранилища потоков (см. Локальное хранилище потоков) конкретной __thread переменной, переопределяя параметр командной строки -ftls-model= на основе каждой переменной. Аргумент tls_model должен быть одним из global-dynamic, local-dynamic, initial-exec или local-exec.

Не все целевые платформы поддерживают этот атрибут.

unused
Этот атрибут, прикреплённый к переменной, означает, что переменная потенциально может быть неиспользуемой. GCC не выдает предупреждение для этой переменной.
used
Этот атрибут, прикреплённый к переменной со статическим хранением, означает, что переменная должна быть выведена даже если кажется, что на неё нет ссылок.

При применении к статическому члену данных шаблона C++ класса атрибут также означает, что член будет инстанцирован, если сам класс будет инстанцирован.

vector_size (bytes)
Этот атрибут задаёт размер вектора для переменной, измеряемый в байтах. Например, объявление:
int foo __attribute__ ((vector_size (16)));

приводит к тому, что компилятор устанавливает режим для foo, в 16 байт, разделённых на единицы размера int. Предполагая 32-битное целое число (вектор из 4 единиц по 4 байта), соответствующий режим foo — V4SI.

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

Агрегаты с этим атрибутом недопустимы, даже если они имеют тот же размер, что и соответствующий скаляр. Например, объявление:

struct S { int a; };
struct S  __attribute__ ((vector_size (16))) foo;

недопустимо, даже если размер структуры такой же, как размер int.

selectany
Атрибут selectany приводит к тому, что инициализированная глобальная переменная имеет семантику «link-once». Когда компоновщик встречает несколько определений переменной, он выбирает первое и отбрасывает остальные. Следуя использованию в компиляторе Microsoft, компоновщик не будет предупреждать о различиях в размере или содержимом нескольких определений.

Хотя основное использование этого атрибута относится к типам POD, этот атрибут также может применяться к глобальным объектам C++, которые инициализируются конструктором. В этом случае код статической инициализации и уничтожения объекта выводится в каждом переводе, определяющем объект, но вызовы конструктора и деструктора защищены переменной-сторожем «link-once».

Атрибут selectany доступен только для целей Microsoft Windows. Вы можете использовать __declspec (selectany) в качестве синонима для __attribute__ ((selectany)) для совместимости с другими компиляторами.

weak
Атрибут weak описан в Атрибутах функций.
dllimport
Атрибут dllimport описан в Атрибутах функций.
dllexport
Атрибут dllexport описан в Атрибутах функций.

6.36.1 Атрибуты переменных AVR

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

Этот атрибут работает аналогично атрибуту section, но добавляет дополнительные проверки. Обратите внимание, что, как и атрибут section, атрибут progmem влияет на расположение данных, но не на то, как эти данные доступны.

Для чтения данных, расположенных с помощью атрибута progmem (встроенный) необходимо использовать ассемблер.

/* Use custom macros from AVR-LibC */
#include <avr/pgmspace.h>

/* Locate var in flash memory */
const int var[2] PROGMEM = { 1, 2 };

int read_var (int i)
{
    /* Access var[] by accessor macro from avr/pgmspace.h */
    return (int) pgm_read_word (& var[i]);
}

AVR — это процессор с архитектурой Гарвард, и данные и данные только для чтения обычно находятся в памяти данных (RAM).

См. также раздел Имена адресных пространств AVR для альтернативного способа размещения и доступа к данным во флэш-памяти.

6.36.2 Атрибуты переменных Blackfin

В настоящее время для Blackfin определены три атрибута.

l1_data
l1_data_A
l1_data_B
Используйте эти атрибуты на Blackfin для размещения переменной в L1 Data SRAM. Переменные с атрибутом l1_data помещаются в определенную секцию с именем .l1.data. Переменные с атрибутом l1_data_A помещаются в определенную секцию с именем .l1.data.A. Переменные с атрибутом l1_data_B помещаются в определенную секцию с именем .l1.data.B.
l2
Используйте этот атрибут на Blackfin для размещения переменной в L2 SRAM. Переменные с атрибутом l2 помещаются в определенную секцию с именем .l2.data.

6.36.3 Атрибуты переменных M32R/D

В настоящее время для M32R/D определён один атрибут.

model (model-name)
Используйте этот атрибут на M32R/D для задания адресации объекта. Идентификатор model-name может быть small, medium или large, представляя каждый из моделей кода.

Объекты малой модели находятся в нижних 16 МБ памяти (чтобы их адреса можно было загрузить с помощью инструкции ld24).

Объекты средней и большой моделей могут находиться где угодно в 32-битном адресном пространстве (компилятор генерирует инструкции seth/add3 для загрузки их адресов).

6.36.4 Атрибуты переменных MeP

Целевой процессор MeP имеет ряд режимов адресации и шин. Пространство near охватывает первые 16 мегабайт стандартного адресного пространства (24 бита). Пространство far охватывает всё 32-битное адресное пространство. Пространство based — это область размером 128 байт в адресном пространстве, адресованная относительно регистра $tp. Пространство tiny — это область размером 65536 байт относительно регистра $gp. В дополнение к этим областям памяти целевой процессор MeP имеет отдельную 16-битную шину управления, которая задаётся атрибутами cb.

based
Любая переменная с атрибутом based назначается в секцию .based и обращается относительно регистра $tp.
tiny
Аналогично, атрибут tiny назначает переменные в секцию .tiny, относительно регистра $gp.
near
Переменные с атрибутом near предполагают, что их адреса помещаются в 24-битный режим адресации. Это стандарт для больших переменных (-mtiny=4 — значение по умолчанию), но этот атрибут может переопределить -mtiny= для малых переменных или переопределить -ml.
far
Переменные с атрибутом far адресованы с использованием полного 32-битного адреса. Поскольку это охватывает всё адресное пространство, это позволяет модулям не делать предположений о том, где могут храниться переменные.
io
io (addr)
Переменные с атрибутом io используются для адресации периферийных устройств с памятью. Если указан адрес, переменной назначается этот адрес, иначе ей не назначается адрес (предполагается, что некоторый другой модуль назначит адрес). Пример:
int timer_count __attribute__((io(0x123)));
cb
cb (addr)
Переменные с атрибутом cb используются для доступа к шине управления, используя специальные инструкции. addr указывает адрес шины управления. Пример:
int cpu_clock __attribute__((cb(0x123)));

6.36.5 Атрибуты переменных i386

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

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

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

Алгоритм размещения структуры Microsoft довольно прост за исключением упаковки битовых полей. Выравнивание и заполнение членов структур и возможность пересечения границы единицы хранения битовыми полями определяются этими правилами:

  1. Члены структуры хранятся последовательно в том порядке, в котором они объявлены: первый член имеет наименьший адрес памяти, а последний — наибольший.
  2. Каждый объект данных имеет требование выравнивания. Требование выравнивания для всех данных, кроме структур, объединений и массивов, равно либо размеру объекта, либо текущему размеру упаковки (указанному с помощью атрибута aligned или директивы pack), что меньше. Для структур, объединений и массивов требование выравнивания — наибольшее требование выравнивания его членов. Каждый объект выделяется смещением таким образом, что:
    offset % alignment_requirement == 0
  3. Смежные битовые поля упаковываются в единицу размещения размером 1, 2 или 4 байта, если целочисленные типы имеют одинаковый размер и следующее битовое поле помещается в текущую единицу размещения без пересечения границы, наложенной общими требованиями выравнивания битовых полей.

MSVC интерпретирует нулевые битовые поля следующим образом:

  1. Если нулевое битовое поле вставлено между двумя битовыми полями, которые обычно сливаются, битовые поля не сливаются.

    Например:

    struct
     {
       unsigned long bf_1 : 12;
       unsigned long : 0;
       unsigned long bf_2 : 12;
     } t1;

    Размер t1 составляет 8 байтов с нулевым битовым полем. Если бы нулевое битовое поле было удалено, размер t1 составлял бы 4 байта.

  2. Если нулевое битовое поле вставлено после битового поля, foo, и выравнивание нулевого битового поля больше, чем члена, который следует за ним, bar, bar выравнивается как тип нулевого битового поля.

    Например:

    struct
     {
       char foo : 4;
       short : 0;
       char bar;
     } t2;
    
    struct
     {
       char foo : 4;
       short : 0;
       double bar;
     } t3;

    Для t2, bar размещается со смещением 2, а не со смещением 1. Соответственно, размер t2 составляет 4. Для t3, нулевое битовое поле не влияет на выравнивание bar или, как следствие, на размер структуры.

    Учитывая это, важно отметить следующее:

    1. Если нулевое битовое поле следует за обычным битовым полем, тип нулевого битового поля может повлиять на выравнивание структуры в целом. Например, t2 имеет размер 4 байта, так как нулевое битовое поле следует за обычным битовым полем и имеет тип short.
    2. Даже если нулевое битовое поле не следует за обычным битовым полем, оно всё равно может повлиять на выравнивание структуры:
      struct
       {
         char foo : 6;
         long : 0;
       } t4;

      Здесь t4 занимает 4 байта.

  3. Нулевые битовые поля, следующие за членами, не являющимися битовыми полями, игнорируются:
    struct
     {
       char foo;
       long : 0;
       char bar;
     } t5;

    Здесь t5 занимает 2 байта.

6.36.6 Атрибуты переменных PowerPC

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

Для получения полной документации по атрибутам структуры, пожалуйста, обратитесь к документации в Атрибуты переменных i386.

Для получения документации по атрибуту altivec обратитесь к документации в Атрибуты типов PowerPC.

6.36.7 Атрибуты переменных SPU

SPU поддерживает атрибут spu_vector для переменных. Для получения документации по этому атрибуту обратитесь к документации в Атрибуты типов SPU.

6.36.8 Атрибуты переменных Xstormy16

В настоящее время для конфигураций xstormy16 определен один атрибут: below100.

below100
Если переменная имеет атрибут below100 (также допускается BELOW100), GCC помещает переменную в первые 0x100 байтов памяти и использует специальные инструкции для доступа к ней. Такие переменные размещаются в секции .bss_below100 или в секции .data_below100.

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

Spec-Zone.ru

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