Подтвердить что ты не робот

Применяется ли __attribute__ ко всем переменным в объявлении?

Соответствует ли директива __attribute__ всем членам, объявленным в одной строке?


int a, b, c;

Объявляет три переменные int.


int *a, b, c;

Объявляет переменную "a" как указатель на int, а b и c - как int.


int __attribute__((used)) a, b, c;

Используется ли атрибут used для всех переменных или только для a?

4b9b3361

Ответ 1

От 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.

Ответ 2

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.

Ответ 3

Ссылаясь на документ GCC,

Ключевое слово __attribute__ позволяет вам указывать специальные атрибуты при создании объявления. За этим ключевым словом следует спецификация атрибута внутри двойных скобок. В настоящее время для функций определены девять атрибутов, noreturn, const, format, no_instrument_function, section, конструктор, деструктор, неиспользуемый и слабый. Другие атрибуты, включая раздел, поддерживаются для объявлений переменных (см. Раздел 4.29 "Указание атрибутов переменных" ) и типов (см. Раздел 4.30 "Указание атрибутов типов" ).

Раздел 4.29: Атрибуты переменных

неиспользованный:
Этот атрибут, привязанный к переменной, означает, что переменная должна быть, возможно, не использована. GNU CC не выдаст предупреждение для этой переменной.

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

неиспользованный:
При привязке к типу (включая объединение или структуру) этот атрибут означает, что переменные этого типа должны отображаться, возможно, неиспользуемыми. GNU CC не будет выдавать предупреждение для любых переменных этого типа, даже если переменная, кажется, ничего не делает. Это часто случается с классами блокировки или потока, которые обычно определяются, а затем не упоминаются, но содержат конструкторы и деструкторы, которые имеют нетривиальные функции бухгалтерского учета

Ответ 4

Ответ заключается в том, что атрибут, вероятно, ничего не делает.

$ cat f.c
int foo_f1;
int __attribute__((used)) foo_f2;

main()
{
}

и

$ cat g.c
int foo_g1;
int __attribute__((used)) foo_g2;

построить f как obj, 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)).