C 属性是否应用于声明中的所有变量?

C 属性是否应用于声明中的所有变量?,c,gcc,C,Gcc,\uuuu attribute\uuu指令是否适用于一行中声明的所有成员 声明三个int变量 将变量“a”声明为指向int的指针,将b和c声明为int used属性是适用于所有变量还是仅适用于a?gcc文档()说明它仅适用于它们出现在其声明符之前的标识符: 在使用单个说明符和限定符列表的多个标识符的声明中,属性说明符列表可能紧跟在以逗号分隔的声明符列表中的声明符(第一个除外)之前。此类属性说明符仅适用于它们出现在其声明符之前的标识符。例如,在 __attribute__((noreturn

\uuuu attribute\uuu
指令是否适用于一行中声明的所有成员


声明三个int变量


将变量“a”声明为指向int的指针,将b和c声明为int



used
属性是适用于所有变量还是仅适用于
a

gcc
文档()说明它仅适用于它们出现在其声明符之前的标识符:

在使用单个说明符和限定符列表的多个标识符的声明中,属性说明符列表可能紧跟在以逗号分隔的声明符列表中的声明符(第一个除外)之前。此类属性说明符仅适用于它们出现在其声明符之前的标识符。例如,在

__attribute__((noreturn)) void d0 (void),
     __attribute__((format(printf, 1, 2))) d1 (const char *, ...),
      d2 (void);
在你的例子中:

int __attribute__((used)) a, b, c;
该属性仅适用于引用

关键字
\uuuuu属性\uuuu
允许您在进行声明时指定特殊属性。该关键字后面是双括号内的属性规范。目前为函数定义了九个属性:noreturn、const、format、no_instrument_函数、section、constructor、destructor、unused和weak。变量声明(参见第4.29节指定变量属性)和类型(参见第4.30节指定类型属性)支持其他属性,包括第节

未使用:
此属性附加到变量,表示该变量可能未使用。GNU CC不会为此变量生成警告

未使用:
当附加到类型(包括联合或结构)时,此属性表示该类型的变量可能未使用。GNUCC不会为该类型的任何变量生成警告,即使该变量看起来没有任何作用。锁类或线程类通常就是这种情况,它们通常被定义,然后不被引用,但包含具有非平凡簿记功能的构造函数和析构函数

发件人:

在使用单个说明符和限定符列表的多个标识符的声明中,属性说明符列表可能紧跟在以逗号分隔的声明符列表中的声明符(第一个除外)之前。此类属性说明符仅适用于它们出现在其声明符之前的标识符。例如,在

__attribute__((noreturn)) void d0 (void),
     __attribute__((format(printf, 1, 2))) d1 (const char *, ...),
      d2 (void);
noreturn
属性适用于所有声明的函数;格式属性仅适用于
d1


更正:正如评论所指出的,我先前的结论是不正确的。除了第一部分,我没有注意到

修改结论:

两者

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

该属性适用于所有a、b和c

但如果是:

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

该属性仅适用于
b

答案是该属性可能没有任何作用

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

main()
{
}

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
中删除所有符号,即使使用
\uuuu属性((已使用))

,您也可以对此进行测试。属性不是C标准的一部分,所以每个编译器都可以做任何他们想做的事情。只需创建一个简单的程序,链接它并转储符号。出于同样的原因,指针声明是模糊的(即
int*a,b;
不将b声明为指针),通常建议每行声明的变量不超过一个。那么就没有歧义了。同样的情况也适用于
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
问题是
\uuuuuuuuuuuuuuuuuu属性是影响类型(左侧)还是变量(右侧)。由于
used
是变量属性[而不是类型属性[它应该只影响变量
a
@MarkLakata,对于我的几乎所有同事来说,很明显b不是指针。我知道它被讨论了太多次,并且是什么参数,但我认为它必须与当地教育有关,而不是“常识”这就是为什么除了周围的小猴子之外,没有人会写出含糊不清的
int*a,b
。无论如何,需要说的是源代码行是不相关的;可能相关的不是“在一行”而是“直到下一个分号”结论是错误的;
\uuuuu attribute\uuuuu int var
int\uuuuu attribute\uuuuuu var
之间没有区别,因为“var”不是“第一个以外的”。我有点震惊地意识到合法的问题这么快就被解决了,而被接受的答案是不正确的(就像这个)对于正确的答案,这说明了为什么这个答案是错误的,请阅读:与Yu Hao的答案一样,因为
a
是列表中的第一个声明符,并且本段仅适用于属性说明符列表紧跟在第一个声明符之前的情况,它不适用于此处,并且此日志ic不正确。请参阅。但这不是
\uuuuuu属性(已使用))
应该这样做。它只控制是否可以从程序集输出中优化未使用的
静态
变量。它对非
静态
变量没有影响,对链接器决定做什么也没有影响。@NateEldredge知道这一点很好,但我只是在处理OP的示例,而不是静止的
int __attribute__((used)) a, b, c;
__attribute__((used)) int a, b, c;
int a, __attribute__((used)) b, c;
$ cat f.c
int foo_f1;
int __attribute__((used)) foo_f2;

main()
{
}
$ cat g.c
int foo_g1;
int __attribute__((used)) foo_g2;
$ 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