比较无符号与有符号不会发出警告(使用 const)

elc*_*uco 6 c gcc constants

简单:如果我在 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)


Lun*_*din 2

我想说这是-Wsign-compare选项中的编译器错误。

通过使用 编译您的示例进行测试-Wall -Wextra -O3。添加后-O3,警告突然消失const。即使生成的机器代码有或没有const是相同的。这没有任何意义。

当然,const生成的机器代码对 C 操作数的符号性没有任何影响,因此根据类型限定符或优化器设置,警告不应不一致。