Spec-Zone.ru › GCC 5

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

Ключевое слово __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 запускает функцию, когда переменная выходит из области видимости. Этот атрибут может быть применён только к переменным в области видимости функции типа auto; он не может быть применён к параметрам или переменным со статической продолжительностью хранения. Функция должна принимать один параметр — указатель на тип, совместимый с переменной. Возвращаемое значение функции (если оно есть) игнорируется.

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

common
nocommon

Атрибут common запрашивает от GCC размещение переменной в хранилище «common». Атрибут 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-битный int (вектор из 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.38.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 — процессор архитектуры Гарвард, и данные и данные только для чтения обычно находятся в памяти данных (ОЗУ).

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

io
io (addr)

Переменные с атрибутом io используются для адресации периферийных устройств с отображением памяти в диапазоне адресов ввода/вывода. Если адрес указан, переменной присваивается этот адрес, а значение интерпретируется как адрес в адресном пространстве данных. Пример:

volatile int porta __attribute__((io (0x22)));

Указанный адрес находится в диапазоне адресов адресного пространства данных.

В противном случае переменной не назначается адрес, но компилятор по-прежнему будет использовать инструкции in/out, если применимо, предполагая, что какой-то другой модуль назначит адрес в диапазоне адресов ввода/вывода. Пример:

extern volatile int porta __attribute__((io));
io_low
io_low (addr)

Это как атрибут io, но дополнительно сообщает компилятору, что объект находится в нижней половине области ввода/вывода, позволяя использовать инструкции cbi, sbi, sbic и sbis.

address
address (addr)

Переменные с атрибутом address используются для адресации периферийных устройств с отображением памяти, которые могут находиться за пределами диапазона адресов ввода/вывода.

volatile int porta __attribute__((address (0x600)));

6.38.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.38.3 Атрибуты переменных H8/300

Эти атрибуты переменных доступны для целей H8/300:

eightbit_data

Используйте этот атрибут для H8/300, H8/300H и H8S, чтобы указать, что указанная переменная должна быть размещена в секции данных с размером 8 бит. Компилятор генерирует более эффективный код для некоторых операций с данными в области данных с размером 8 бит. Обратите внимание, что область данных с размером 8 бит ограничена 256 байтами данных.

Для корректной работы этого атрибута необходимо использовать GAS и GLD из GNU binutils версии 2.7 или более поздней.

tiny_data

Используйте этот атрибут для H8/300H и H8S, чтобы указать, что указанная переменная должна быть помещена в секцию данных «tiny». Компилятор генерирует более эффективный код для загрузки и сохранения данных в секции данных «tiny». Обратите внимание, что область «tiny» ограничена чуть меньше 32 КБ данных.

6.38.4 Атрибуты переменных IA-64

Бэкенд IA-64 поддерживает следующие атрибуты переменных:

model (model-name)

В IA-64 используйте этот атрибут для установки адресации объекта. В настоящее время единственный поддерживаемый идентификатор для model-name — small, указывающий на адресацию через «малые» (22-битные) адреса (так что их адреса можно загружать с помощью инструкции addl). Предупреждение: такая адресация по определению не является независимой от позиции, поэтому этот атрибут нельзя использовать для объектов, определённых разделяемыми библиотеками.

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

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

model (model-name)

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

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

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

6.38.6 Атрибуты переменных 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.38.7 Атрибуты переменных PowerPC

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

Для полной документации по атрибутам struct см. документацию в x86 Атрибуты переменных.

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

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

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

6.38.9 Атрибуты переменных x86

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

ms_struct
gcc_struct

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

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

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

  1. Члены структуры хранятся последовательно в том порядке, в котором они объявлены: первый член имеет наименьший адрес памяти, а последний — наибольший.
  2. Каждый объект данных имеет требование к выравниванию. Требование к выравниванию для всех данных, кроме структур, объединений и массивов, равно либо размеру объекта, либо текущему размеру упаковки (указанному с помощью атрибута aligned или директивы pack pragma), в зависимости от того, какой из них меньше. Для структур, объединений и массивов требование к выравниванию является наибольшим требованием к выравниванию его членов. Каждый объект выделяется с таким смещением, что:
    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.38.10 Атрибуты переменных Xstormy16

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

below100

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

Далее: Атрибуты типов, Предыдущее: Экранирование символов, Наверх: Расширения языка C [Оглавление][Индекс]

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

Spec-Zone.ru

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