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 не вернётся нормально. commonnocommon-
Атрибут
commonзапрашивает от GCC размещение переменной в хранилище «common». Атрибутnocommonзапрашивает обратное — выделение памяти непосредственно для неё.Эти атрибуты переопределяют настройки по умолчанию, выбранные флагами -fno-common и -fcommon соответственно.
deprecateddeprecated (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-
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 Имена адресных пространств для альтернативного способа размещения и доступа к данным в памяти флэш.
ioio (addr)-
Переменные с атрибутом
ioиспользуются для адресации периферийных устройств с отображением памяти в диапазоне адресов ввода/вывода. Если адрес указан, переменной присваивается этот адрес, а значение интерпретируется как адрес в адресном пространстве данных. Пример:volatile int porta __attribute__((io (0x22)));
Указанный адрес находится в диапазоне адресов адресного пространства данных.
В противном случае переменной не назначается адрес, но компилятор по-прежнему будет использовать инструкции in/out, если применимо, предполагая, что какой-то другой модуль назначит адрес в диапазоне адресов ввода/вывода. Пример:
extern volatile int porta __attribute__((io));
io_lowio_low (addr)-
Это как атрибут
io, но дополнительно сообщает компилятору, что объект находится в нижней половине области ввода/вывода, позволяя использовать инструкцииcbi,sbi,sbicиsbis. addressaddress (addr)-
Переменные с атрибутом
addressиспользуются для адресации периферийных устройств с отображением памяти, которые могут находиться за пределами диапазона адресов ввода/вывода.volatile int porta __attribute__((address (0x600)));
6.38.2 Атрибуты переменных Blackfin
В настоящее время для Blackfin определены три атрибута.
l1_datal1_data_Al1_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-битного адреса. Так как это покрывает всё адресное пространство памяти, это позволяет модулям не делать предположений о том, где могут храниться переменные. ioio (addr)-
Переменные с атрибутом
ioиспользуются для адресации периферийных устройств с отображением памяти. Если адрес указан, переменной присваивается этот адрес, в противном случае ей не присваивается адрес (предполагается, что какой-то другой модуль назначит адрес). Пример:int timer_count __attribute__((io(0x123)));
cbcb (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_structgcc_struct-
Если используется
packed, применительно к структуре, или если используются битовые поля, возможно, что Microsoft ABI выстраивает структуру иначе, чем обычно делает GCC. Особенно при перемещении упакованных данных между функциями, скомпилированными с помощью GCC и родным компилятором Microsoft (либо через вызов функции, либо как данные в файле), может потребоваться доступ к одному из этих форматов.В настоящее время для компиляторов Microsoft Windows x86 предоставляется -m[no-]ms-bitfields для соответствия родным компиляторам Microsoft.
Алгоритм расположения структуры Microsoft довольно прост, за исключением упаковки битовых полей. Выравнивание и заполнение членов структур, а также то, может ли битовое поле пересекать границу единицы хранения, определяются следующими правилами:
- Члены структуры хранятся последовательно в том порядке, в котором они объявлены: первый член имеет наименьший адрес памяти, а последний — наибольший.
- Каждый объект данных имеет требование к выравниванию. Требование к выравниванию для всех данных, кроме структур, объединений и массивов, равно либо размеру объекта, либо текущему размеру упаковки (указанному с помощью атрибута
alignedили директивыpackpragma), в зависимости от того, какой из них меньше. Для структур, объединений и массивов требование к выравниванию является наибольшим требованием к выравниванию его членов. Каждый объект выделяется с таким смещением, что:offset % alignment_requirement == 0
- Смежные битовые поля упаковываются в одну единицу размещения 1-, 2- или 4-байта, если целочисленные типы имеют одинаковый размер и если следующее битовое поле помещается в текущую единицу размещения без пересечения границы, накладываемой общими требованиями к выравниванию битовых полей.
MSVC интерпретирует битовые поля нулевой длины следующим образом:
- Если битовое поле нулевой длины вставлено между двумя битовыми полями, которые обычно сливаются, битовые поля не сливаются.
Например:
struct { unsigned long bf_1 : 12; unsigned long : 0; unsigned long bf_2 : 12; } t1;Размер
t1составляет 8 байт с битовым полем нулевой длины. Если поле нулевой длины удалить, размерt1составит 4 байта. - Если битовое поле нулевой длины вставлено после битового поля,
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или, как следствие, на размер структуры.Учитывая это, важно отметить следующее:
- Если битовое поле нулевой длины следует за обычным битовым полем, тип битового поля нулевой длины может повлиять на выравнивание всей структуры. Например,
t2имеет размер 4 байта, так как битовое поле нулевой длины следует за обычным битовым полем и имеет тип short. - Даже если битовое поле нулевой длины не следует за обычным битовым полем, оно все равно может повлиять на выравнивание структуры:
struct { char foo : 6; long : 0; } t4;Здесь
t4занимает 4 байта.
- Если битовое поле нулевой длины следует за обычным битовым полем, тип битового поля нулевой длины может повлиять на выравнивание всей структуры. Например,
- Битовые поля нулевой длины, следующие за членами, не являющимися битовыми полями, игнорируются:
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