Применяется ли __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 ответа

Решение

Из GCC: Атрибут-синтаксис:

Список спецификаторов атрибутов может появляться непосредственно перед декларатором (кроме первого) в списке деклараторов, разделенных запятыми, в объявлении более чем одного идентификатора с использованием одного списка спецификаторов и квалификаторов. Такие спецификаторы атрибутов применяются только к идентификатору, перед которым они объявлены. Например, в

__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 не выдаст предупреждение для этой переменной.

Раздел 4.30: Атрибуты типов

неиспользованный:
При присоединении к типу (включая объединение или структуру) этот атрибут означает, что переменные этого типа должны казаться возможно неиспользованными. 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)),

Другие вопросы по тегам