简单:如果我在 GCC 中测试有符号变量与无符号变量,编译时-Wall我会收到警告。
使用此代码:
#include <stdio.h>
int main(int argc, char* argv[])
{
/* const */ unsigned int i = 0;
if (i != argc)
return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我收到此警告:
<source>: In function 'int main(int, char**)':
<source>:6:8: warning: comparison of integer expressions of different signedness: 'unsigned int' and 'int' [-Wsign-compare]
6 | if (i != argc)
| ~~^~~~~~~
Compiler returned: 0
Run Code Online (Sandbox Code Playgroud)
但是,如果我取消注释const- 编译器很高兴。我几乎可以在每个 GCC 版本上重现这一点(参见https://godbolt.org/z/b6eoc1)。这是 GCC 中的错误吗?
小智 5
我认为您缺少的是编译器优化。如果没有 const,该变量就是变量,这意味着它可以更改。由于它是一个无符号整型,这意味着它确实可以大于整数。
const unsigned int i = 2147483648;
Run Code Online (Sandbox Code Playgroud)
如果您将大于 int 最大值的值分配给该无符号 int,您将收到错误。
然而,如果它是const,编译器知道它的值,它知道它不会改变,并且比较不会有问题。
如果你看一下程序集,你会发现没有 const,它实际上需要变量的值来比较:
movl $0, -4(%rbp)
movl -20(%rbp), %eax
cmpl %eax, -4(%rbp)
Run Code Online (Sandbox Code Playgroud)
现在,如果它是 const,它根本不会关心变量,它只需要值:
movl $0, -4(%rbp)
cmpl $0, -20(%rbp)
Run Code Online (Sandbox Code Playgroud)
我想说这是-Wsign-compare选项中的编译器错误。
通过使用 编译您的示例进行测试-Wall -Wextra -O3。添加后-O3,警告突然消失const。即使生成的机器代码有或没有const是相同的。这没有任何意义。
当然,const生成的机器代码对 C 操作数的符号性没有任何影响,因此根据类型限定符或优化器设置,警告不应不一致。