"stderr;" 作为声明不抛出警告
"stderr;" as a statement throws no warning
假设我有这样的源代码:
#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;
或
#include <math.h>
int main()
{
cos(2.0*M_PI + 7.0);
}
你会得到相同的结果(什么都不会发生)。原因是语句可以是任何表达式(任何类型)后跟 C 中的分号 ;
。表达式值刚刚被删除,并继续执行下一条语句(在您的情况下有 none).在我的示例中,表达式的 0 值或字符串文字 "Hello world"
只是被编译器丢弃,结果为空。
这个程序:
$ 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;
| ^
我们应该清楚这个免费通行证是由 identifier 携带的
stderr
,与它命名的值不同:-
不能通过使另一个等于 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;
| ^
实际上是stderr
的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
Print warning messages for constructs found in system header files. Warnings from
system headers are normally suppressed, on the assumption that they usually do not
indicate real problems and would only make the compiler output harder to read.
Using this command-line option tells GCC to emit warnings from system headers as
if they occurred in user code.
...
因此,stderr
、stderr
凭借在系统中声明而获得诊断免疫力
header、<stdio.h>
1。来自系统 header 的警告默认假定为
是假的。
然而,在我们开始我们的业务之前,值得赞赏的是记录在案的解释
-Wsystem-headers
的影响及其缺失实际上并不能解释
我们观察到的那些影响。诊断失败
stderr; // statement with no effect
在我们的第一个程序中没有-Wsystem-headers
是不是的压制
来自系统 header 的警告。它是对来自 main.c
的警告的抑制,
其中该语句与以下语句完全一样无效:
p; // statement with no effect
而-Wsystem-headers
对该程序编译的影响不是
GCC 开始从系统发出任何先前抑制的警告 header
就好像它发生在用户代码中一样。它会导致 GCC 发出一个先前被抑制的
用户代码中一直出现的警告。
显然默认 -Wno-system-headers
的实际效果至少包括,
当 context
时,在用户代码中或不在用户代码中抑制某些警告
... identifier ...
否则会引发警告的 identifier
已声明
在系统 header 中。手册告诉我们如何停止这种情况,但只是手势
在解释它时。
[1] 文档中的 system header 是什么意思并不明显,
但是实验表明一个文件只是一个系统header
如果它是由 GCC 安装的 header 文件,则具有适当的意义。
假设我有这样的源代码:
#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;
或
#include <math.h>
int main()
{
cos(2.0*M_PI + 7.0);
}
你会得到相同的结果(什么都不会发生)。原因是语句可以是任何表达式(任何类型)后跟 C 中的分号 ;
。表达式值刚刚被删除,并继续执行下一条语句(在您的情况下有 none).在我的示例中,表达式的 0 值或字符串文字 "Hello world"
只是被编译器丢弃,结果为空。
这个程序:
$ 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;
| ^
我们应该清楚这个免费通行证是由 identifier 携带的
stderr
,与它命名的值不同:-
不能通过使另一个等于 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;
| ^
实际上是stderr
的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
Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read. Using this command-line option tells GCC to emit warnings from system headers as if they occurred in user code. ...
因此,stderr
、stderr
凭借在系统中声明而获得诊断免疫力
header、<stdio.h>
1。来自系统 header 的警告默认假定为
是假的。
然而,在我们开始我们的业务之前,值得赞赏的是记录在案的解释
-Wsystem-headers
的影响及其缺失实际上并不能解释
我们观察到的那些影响。诊断失败
stderr; // statement with no effect
在我们的第一个程序中没有-Wsystem-headers
是不是的压制
来自系统 header 的警告。它是对来自 main.c
的警告的抑制,
其中该语句与以下语句完全一样无效:
p; // statement with no effect
而-Wsystem-headers
对该程序编译的影响不是
GCC 开始从系统发出任何先前抑制的警告 header
就好像它发生在用户代码中一样。它会导致 GCC 发出一个先前被抑制的
用户代码中一直出现的警告。
显然默认 -Wno-system-headers
的实际效果至少包括,
当 context
... identifier ...
否则会引发警告的 identifier
已声明
在系统 header 中。手册告诉我们如何停止这种情况,但只是手势
在解释它时。
[1] 文档中的 system header 是什么意思并不明显, 但是实验表明一个文件只是一个系统header 如果它是由 GCC 安装的 header 文件,则具有适当的意义。