Последовательность спецификаторов атрибутов(с C23)
Вводит определяемые реализацией атрибуты для типов, объектов, выражений и т. д.
Синтаксис
[[атрибут ]] [[атрибут1, атрибут2, атрибут3(аргументы)]] [[префикс-атрибута::атрибут (аргументы)]] Формально, синтаксис выглядит следующим образом:
[[ список-атрибутов ]] | (с C23) |
где список-атрибутов — это отделённая запятыми последовательность нуля или более токенов-атрибутов
| стандартный-атрибут | (1) | |
префикс-атрибута :: идентификатор | (2) | |
стандартный-атрибут ( список-аргументов (необязательно) ) | (3) | |
префикс-атрибута :: идентификатор ( список-аргументов (необязательно) ) | (4) |
где префикс-атрибута — это идентификатор, а список-аргументов — это последовательность токенов, где скобки, квадратные скобки и фигурные скобки сбалансированы (сбалансированная-последовательность-токенов).
Объяснение
Атрибуты предоставляют унифицированный стандартный синтаксис для расширений языка, определяемых реализацией, таких как расширения GNU и IBM __attribute__((...)), расширения Microsoft __declspec(), и т. д.
Атрибут может использоваться практически в любой части программы на C и применяться практически ко всему: к типам, переменным, функциям, именам, блокам кода, целым единицам трансляции, хотя каждый конкретный атрибут действителен только там, где это разрешено реализацией: [[expect_true]] может быть атрибутом, который можно использовать только с if, а не с объявлением класса. [[omp::parallel()]] может быть атрибутом, который применяется к блоку кода или к циклу for, но не к типу int, и т. д. (эти два атрибута — условные примеры, см. ниже стандартные и некоторые нестандартные атрибуты)
В объявлениях атрибуты могут появляться как перед всем объявлением, так и непосредственно после имени объявляемого сущности, в этом случае они объединяются. В большинстве других ситуаций атрибуты применяются к непосредственно предшествующей сущности.
Два последовательных токена левой квадратной скобки ([[) могут появляться только при введении спецификатора атрибута или внутри аргумента атрибута.
Помимо стандартных атрибутов, перечисленных ниже, реализации могут поддерживать произвольные нестандартные атрибуты с поведением, определяемым реализацией. Все неизвестные реализации атрибуты игнорируются без выдачи ошибки.
Каждый стандартный-атрибут зарезервирован для стандартизации. То есть каждый нестандартный атрибут имеет префикс префикс-атрибута, предоставленный реализацией, например [[gnu::may_alias]] и [[clang::no_sanitize]].
Стандартные атрибуты
Только следующие атрибуты определены стандартом C. Каждый стандартный атрибут, имя которого имеет вид attr, также может быть записан как __attr__, и его значение не изменится.
[[deprecated]](C23)[[deprecated("reason")]](C23) | указывает, что использование имени или сущности, объявленной с этим атрибутом, разрешено, но не рекомендуется по некоторым причинам (спецификатор атрибута) |
[[fallthrough]](C23) | указывает, что переход по метке предыдущего case-блока является преднамеренным и не должен диагностироваться компилятором, который предупреждает о переходе по метке (спецификатор атрибута) |
[[nodiscard]](C23)[[nodiscard("reason")]](C23) | рекомендует компилятору выдать предупреждение, если значение возврата отбрасывается (спецификатор атрибута) |
[[maybe_unused]](C23) | подавляет предупреждения компилятора о неиспользуемых сущностях, если таковые имеются (спецификатор атрибута) |
[[noreturn]](C23)[[_Noreturn]](C23)(устаревшее) | указывает, что функция не возвращает значение (спецификатор атрибута) |
[[unsequenced]](C23) | указывает, что функция бессостоятельна, не имеет эффектов, идемпотентна и независима (спецификатор атрибута) |
[[reproducible]](C23) | указывает, что функция не имеет эффектов и идемпотентна (спецификатор атрибута) |
Тестирование атрибутов
__has_c_attribute( токен-атрибута ) |
Проверяет наличие токена атрибута, имя которого задано токен-атрибута.
Для стандартных атрибутов он будет расширяться до года и месяца, в которые атрибут был добавлен в рабочий проект (см. таблицу ниже), наличие атрибутов, специфичных для поставщика, определяется ненулевым целочисленным значением константы.
__has_c_attribute может быть расширен в выражении #if и #elif. Он обрабатывается как определённая макрос #ifdef, #ifndef и defined, но не может использоваться где-либо ещё.
| токен-атрибута | Атрибут | Значение | Стандарт |
|---|---|---|---|
deprecated |
[[deprecated]] |
201904L | (C23) |
fallthrough |
[[fallthrough]] |
201904L | (C23) |
maybe_unused |
[[maybe_unused]] |
201904L | (C23) |
nodiscard |
[[nodiscard]] |
202003L | (C23) |
noreturn_Noreturn |
[[noreturn]][[_Noreturn]] |
202202L | (C23) |
unsequenced |
[[unsequenced]] |
202207L | (C23) |
reproducible |
[[reproducible]] |
202207L | (C23) |
Пример
[[gnu::hot]] [[gnu::const]] [[nodiscard]]
int f(void); // declare f with three attributes
[[gnu::const, gnu::hot, nodiscard]]
int f(void); // the same as above, but uses a single attr
// specifier that contains three attributes
int f(void) { return 0; }
int main(void)
{
}Ссылки
- Стандарт C23 (ISO/IEC 9899:2023):
- 6.7.12 Атрибуты (стр.: TBD)
См. также
| Документация C++ для Последовательность спецификаторов атрибутов |
Внешние ссылки
| 1. | Атрибуты в GCC |
| 2. | Атрибуты в Clang |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/attributes