Применяется ли __attribute__ ко всем переменным в объявлении?
Ли __attribute__
Директива распространяется на всех членов, объявленных в одной строке?
int a, b, c;
Объявляет три переменные типа int.
int *a, b, c;
Объявляет переменную "a" как указатель на int, а b и c как int.
int __attribute__((used)) a, b, c;
Ли used
атрибут применяется ко всем переменным или только к a
?
4 ответа
Список спецификаторов атрибутов может появляться непосредственно перед декларатором (кроме первого) в списке деклараторов, разделенных запятыми, в объявлении более чем одного идентификатора с использованием одного списка спецификаторов и квалификаторов. Такие спецификаторы атрибутов применяются только к идентификатору, перед которым они объявлены. Например, в
__attribute__((noreturn)) void d0 (void), __attribute__((format(printf, 1, 2))) d1 (const char *, ...), d2 (void);
noreturn
атрибут применяется ко всем объявленным функциям; атрибут формата применяется только кd1
,
Согласно этому в вашем примере:
int __attribute__((used)) a, b, c;
Атрибут применяется только к a
,
Но если бы это было
__attribute__((used)) int a, b, c;
Атрибут применяется ко всем a
, b
, а также c
,
gcc
В документации ( 6.36 Синтаксис атрибутов) говорится, что он применяется только к идентификатору, перед которым они объявлены:
Список спецификаторов атрибутов может появляться непосредственно перед декларатором (кроме первого) в списке деклараторов, разделенных запятыми, в объявлении более чем одного идентификатора с использованием одного списка спецификаторов и квалификаторов. Такие спецификаторы атрибутов применяются только к идентификатору, перед которым они объявлены. Например, в
__attribute__((noreturn)) void d0 (void), __attribute__((format(printf, 1, 2))) d1 (const char *, ...), d2 (void);
Итак, в вашем примере:
int __attribute__((used)) a, b, c;
атрибут относится только к a
,
Ссылаясь на документ GCC,
Ключевое слово
__attribute__
позволяет указывать специальные атрибуты при оформлении декларации. За этим ключевым словом следует спецификация атрибута в двойных скобках. Девять атрибутов, noreturn, const, format, no_instrument_function, section, конструктор, деструктор, неиспользуемые и слабые в настоящее время определены для функций. Другие атрибуты, включая section, поддерживаются для объявлений переменных (см. Раздел 4.29 "Задание атрибутов переменных") и для типов (см. Раздел 4.30 "Указание атрибутов типов").
Раздел 4.29: Атрибуты переменных
неиспользованный:
Этот атрибут, прикрепленный к переменной, означает, что переменная, возможно, не используется. GNU CC не выдаст предупреждение для этой переменной.
неиспользованный:
При присоединении к типу (включая объединение или структуру) этот атрибут означает, что переменные этого типа должны казаться возможно неиспользованными. GNU CC не будет выдавать предупреждение для любых переменных этого типа, даже если переменная, кажется, ничего не делает. Это часто имеет место с классами блокировки или потоков, которые обычно определяются, а затем не ссылаются, но содержат конструкторы и деструкторы, которые имеют нетривиальные функции учета
Ответ в том, что атрибут, вероятно, ничего не делает.
$ cat f.c
int foo_f1;
int __attribute__((used)) foo_f2;
main()
{
}
а также
$ cat g.c
int foo_g1;
int __attribute__((used)) foo_g2;
строить f
как объект, g
как библиотека
$ gcc -c -o g.o g.c
$ ar rs libg.a g.o
$ gcc -O3 f.c -lg
$ objdump.exe -t a.exe | grep foo
[532](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000100 _foo_f1
[599](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000104 _foo_f2
По сути, компоновщик не удалил никаких символов из f.c
и удалил все из g.c
даже с __attribute__((used))
,