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 не вернётся нормально. -
commonnocommon - Атрибут
commonпросит GCC разместить переменную в общем хранилище. Атрибут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- В 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_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.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-битного адреса. Поскольку это охватывает всё адресное пространство, это позволяет модулям не делать предположений о том, где могут храниться переменные. -
ioio (addr) - Переменные с атрибутом
ioиспользуются для адресации периферийных устройств с памятью. Если указан адрес, переменной назначается этот адрес, иначе ей не назначается адрес (предполагается, что некоторый другой модуль назначит адрес). Пример:int timer_count __attribute__((io(0x123)));
-
cbcb (addr) - Переменные с атрибутом
cbиспользуются для доступа к шине управления, используя специальные инструкции.addrуказывает адрес шины управления. Пример:int cpu_clock __attribute__((cb(0x123)));
6.36.5 Атрибуты переменных i386
Для конфигураций i386 в настоящее время определены два атрибута: ms_struct и gcc_struct
-
ms_structgcc_struct - Если
packedиспользуется для структуры или если используются битовые поля, Microsoft ABI может размещать структуру иначе, чем обычно делает GCC. Особенно при перемещении упакованных данных между функциями, скомпилированными с GCC и родным компилятором Microsoft (через вызов функции или как данные в файле), может потребоваться получить доступ к одному из этих форматов.В настоящее время
-m[no-]ms-bitfieldsпредоставляется для компиляторов Microsoft Windows X86 для соответствия родному компилятору Microsoft.Алгоритм размещения структуры Microsoft довольно прост за исключением упаковки битовых полей. Выравнивание и заполнение членов структур и возможность пересечения границы единицы хранения битовыми полями определяются этими правилами:
- Члены структуры хранятся последовательно в том порядке, в котором они объявлены: первый член имеет наименьший адрес памяти, а последний — наибольший.
- Каждый объект данных имеет требование выравнивания. Требование выравнивания для всех данных, кроме структур, объединений и массивов, равно либо размеру объекта, либо текущему размеру упаковки (указанному с помощью атрибута
alignedили директивыpack), что меньше. Для структур, объединений и массивов требование выравнивания — наибольшее требование выравнивания его членов. Каждый объект выделяется смещением таким образом, что: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.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