这个程序:
$ cat main.c
#include <stdio.h>
int main(void)
{
FILE *p;
42; // statement with no effect
p; // statement with no effect
stderr; // statement with no effect
return 0;
}
可能会引出 3 个statement with no effect
每当它引起任何诊断。但正如你所发现的,
在gcc 的手中,这不是真的。
$ gcc --version
gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0
...
$ gcc -Wall -c main.c
main.c: In function ‘main’:
main.c:6:5: warning: statement with no effect [-Wunused-value]
6 | 42;
| ^~
main.c:7:5: warning: statement with no effect [-Wunused-value]
7 | p;
| ^
stderr - 表示FILE *,如p - 具有隐含的免费通行证
评估无效。
众所周知,-Wall真的不会启用所有警告。但是这个免费
通行证可以达到诊断严格的惯常限制:
$ gcc -Wall -Wextra -pedantic -c main.c
main.c: In function ‘main’:
main.c:6:5: warning: statement with no effect [-Wunused-value]
6 | 42;
| ^~
main.c:7:5: warning: statement with no effect [-Wunused-value]
7 | p;
| ^
我们应该清楚,这个免费通行证是由 identfier 携带的
stderr,与它命名的值不同:-
通过使另一个FILE *等于stderr,它不能转移到另一个FILE *:
$ cat main.c; gcc -Wall -c main.c
#include <stdio.h>
int main(void)
{
FILE *p = stderr;
42;
p;
return 0;
}
main.c: In function ‘main’:
main.c:6:5: warning: statement with no effect [-Wunused-value]
6 | 42;
| ^~
main.c:7:5: warning: statement with no effect [-Wunused-value]
7 | p;
| ^
FILE * 不喜欢它实际上 stderr,如果我们不将其引用为stderr。
$ cat main.c; gcc -Wall -c main.c
#include <stdio.h>
int main(void)
{
FILE **p = &stderr;
42;
*p; // a.k.a `stderr`
return 0;
}
main.c: In function ‘main’:
main.c:6:5: warning: statement with no effect [-Wunused-value]
6 | 42;
| ^~
main.c:7:5: warning: statement with no effect [-Wunused-value]
7 | *p; // a.k.a `stderr`
| ^~
但另一方面,即使stderr 被称为stderr,
如果该标识符小于
评估无效的整个上下文:
$ cat main.c; gcc -Wall -c main.c
#include <stdio.h>
int main(void)
{
stdout; // Undiagnosed
stderr; // Undiagnosed
stderr, stdout; // Diagnosed once
42, stderr; // Diagnosed twice
stderr - stdout; // Diagnosed once
(stderr); // Diagnosed once
return 0;
}
main.c: In function ‘main’:
main.c:7:11: warning: left-hand operand of comma expression has no effect [-Wunused-value]
7 | stderr, stdout; // Diagnosed once
| ^
main.c:8:7: warning: left-hand operand of comma expression has no effect [-Wunused-value]
8 | 42, stderr; // Diagnosed twice
| ^
main.c:8:5: warning: statement with no effect [-Wunused-value]
8 | 42, stderr; // Diagnosed twice
| ^~
main.c:9:12: warning: statement with no effect [-Wunused-value]
9 | stderr - stdout; // Diagnosed once
| ^
main.c:10:5: warning: statement with no effect [-Wunused-value]
10 | (stderr); // Diagnosed once
| ^
在这里,我假设stderr 的情况也一样
对于stdout,这是正确的。这是一个值得注意的细节,虽然42, stderr;
被诊断为无效语句,stderr, stdout; 不是。
可以这么说,gcc 在自然和自然方面并不自信
它想要扩展到stderr 的诊断免疫限制,类似地
合格的标识符。这也许是可以理解的,当我们探索
除了与编译器隔离之外,没有人编写的那种代码的后果。
尽管如此,我们还是希望清楚这一诊断的动机
免疫并知道是否可以告诉gcc 撤销它,例如所有的
我在程序中编写的无效语句将被诊断为此类。
第二个分数的答案是肯定的:
$ cat main.c; gcc -Wall -Wsystem-headers -c main.c
#include <stdio.h>
int main(void)
{
FILE *p;
42; // statement with no effect
p; // statement with no effect
stderr; // statement with no effect
return 0;
}
main.c: In function ‘main’:
main.c:6:5: warning: statement with no effect [-Wunused-value]
6 | 42; // statement with no effect
| ^~
main.c:7:5: warning: statement with no effect [-Wunused-value]
7 | p; // statement with no effect
| ^
In file included from main.c:1:
main.c:8:5: warning: statement with no effect [-Wunused-value]
8 | stderr; // statement with no effect
| ^~~~~~
和:
$ cat main.c; gcc -Wall -Wsystem-headers -c main.c
#include <stdio.h>
int main(void)
{
stdout;
stderr;
stderr, stdout;
42, stderr;
stderr - stdout;
(stderr);
return 0;
}
In file included from main.c:1:
main.c: In function ‘main’:
main.c:5:5: warning: statement with no effect [-Wunused-value]
5 | stdout;
| ^~~~~~
main.c:6:5: warning: statement with no effect [-Wunused-value]
6 | stderr;
| ^~~~~~
main.c:7:11: warning: left-hand operand of comma expression has no effect [-Wunused-value]
7 | stderr, stdout;
| ^
In file included from main.c:1:
main.c:7:5: warning: statement with no effect [-Wunused-value]
7 | stderr, stdout;
| ^~~~~~
main.c:8:7: warning: left-hand operand of comma expression has no effect [-Wunused-value]
8 | 42, stderr;
| ^
main.c:8:5: warning: statement with no effect [-Wunused-value]
8 | 42, stderr;
| ^~
main.c:9:12: warning: statement with no effect [-Wunused-value]
9 | stderr - stdout;
| ^
main.c:10:5: warning: statement with no effect [-Wunused-value]
10 | (stderr);
| ^
还有documentation of -Wsystem-headers
提供激励理由:
-Wsystem-headers
打印在系统头文件中找到的构造的警告消息。来自的警告
系统标头通常被抑制,假设它们通常不
表明真正的问题,只会使编译器输出更难阅读。
使用这个命令行选项告诉 GCC 从系统头文件发出警告
如果它们出现在用户代码中。
...
所以,stderr、stderr 通过在系统中声明而获得诊断豁免权
标题,<stdio.h>1。默认情况下,系统标头的警告假定为
是假的。
然而,在我们开展业务之前,值得赞赏的是,记录在案的解释
-Wsystem-headers 的影响,以及它的缺席,实际上并不能解释
我们观察到的那些影响。诊断失败
stderr; // statement with no effect
在我们的第一个程序中没有-Wsystem-headers是不是的压制
来自系统标头的警告。是来自main.c的警告的抑制,
其中该声明与以下内容完全一样无效:
p; // statement with no effect
而-Wsystem-headers对那个程序编译的影响不是
GCC 开始从系统标头发出任何先前抑制的警告
好像它发生在用户代码中。它会导致 GCC 发出先前抑制的
用户代码中一直出现的警告。
显然,默认-Wno-system-headers 的实际效果至少包括:
在上下文时抑制某些警告,无论是否在用户代码中
... identifier ...
否则会引发警告的包含声明的identifier
在系统头文件中。手册告诉我们如何阻止这种情况,但只有手势
在解释它。
[1] 文档中的 system header 是什么意思并不明显,
但实验表明文件只是一个系统头
如果它是GCC安装的头文件,则适当的感觉。