假设我有这样的源代码:
#include <stdio.h>
FILE *p;
int main(void) {
p;
}
...,它将编译(使用gcc)而没有任何错误或警告-除非我打开-Wall
,否则将输出statement with no effect
警告。
但是代码是否像这样:
#include <stdio.h>
int main(void) {
stderr;
}
...不论-Wall
,都不会显示警告。
我在这里想念东西吗?
gcc版本9.3.0
答案 0 :(得分:2)
该程序:
$ 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
:
$ 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标题
为在系统头文件中找到的结构打印警告消息。来自的警告 通常假设系统标头通常不抑制系统标头 表示真正的问题,只会使编译器的输出难以阅读。 使用此命令行选项告诉GCC从系统标头发出警告,如下所示: 如果它们出现在用户代码中。 ...
因此,stderr
,stderr
通过在系统中声明而获得诊断豁免
标头<stdio.h>
1 。默认情况下,系统标题中的警告被假定为
虚伪。
但是,在开展业务之前,值得一提的是,对
-Wsystem-headers
的影响以及它的缺失实际上并不能解释
我们观察到的那些效果。诊断失败
stderr; // statement with no effect
在没有-Wsystem-headers
的情况下,第一个程序中的是 not
来自系统标题的警告。它是禁止来自main.c
的警告,
该语句与以下语句完全一样无效:
p; // statement with no effect
-Wsystem-headers
对程序编译的影响不大
GCC开始从系统标头中发出任何先前禁止的警告
好像发生在用户代码中一样。这会导致GCC发出先前被抑制的
一直在用户代码中发生警告。
显然,默认-Wno-system-headers
的实际效果至少包括
在上下文中禁止显示某些警告(无论是否使用用户代码)
... identifier ...
否则会引起警告的包含已声明的identifier
在系统标题中。手册告诉我们如何停止此操作,但仅手势
在解释它。
[1]在文档中,系统头的含义并不明显, 但实验表明,文件只是该文件中的系统头文件 如果它是GCC安装的头文件,则具有适当的意义。
答案 1 :(得分:-1)
是的...并且如果您编写类似的内容:
0;
或
#include <math.h>
int main()
{
cos(2.0*M_PI + 7.0);
}
您将得到相同的结果(什么都不会发生)。原因是语句可以是任何表达式(任何类型),后跟C中的分号;
。表达式值刚刚删除,执行继续执行下一条语句(在您的情况下没有)。在我的示例中,编译器只是删除了表达式的0值或字符串文字"Hello world"
,结果为空。