微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决比较无符号与有符号不会发出警告使用 const

简单:如果我在 GCC 中测试有符号变量与无符号变量,在编译 -Wall 时我会收到警告。

使用此代码

#include <stdio.h>

int main(int argc,char* argv[])
{
    /* const */ unsigned int i = 0;
    if (i != argc)
        return 1;
    return 0;
}

我收到此警告:

<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

但是,如果我取消注释此 const - 编译器很高兴。我几乎可以在每个 GCC 版本上重现这一点(参见 https://godbolt.org/z/b6eoc1)。这是 GCC 中的错误吗?

解决方法

我认为您缺少的是编译器优化。如果没有 const,该变量就是一个变量,这意味着它可以改变。由于它是一个无符号整数,这意味着它确实可以大于一个整数。

const unsigned int i = 2147483648;

如果您将一个大于 int 的最大值的值分配给该 unsigned int,您将得到您的错误。

但是如果它是const,编译器知道它的值,它知道它不会改变,比较不会有问题。

如果你看一下程序集,你会发现没有const,它实际上是拿变量的值来比较:

movl    $0,-4(%rbp)
movl    -20(%rbp),%eax
cmpl    %eax,-4(%rbp)

现在,如果它是const,它根本不会打扰变量,它只需要取值:

movl    $0,-4(%rbp)
cmpl    $0,-20(%rbp)
,

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

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

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

,

只需使用 -Wall -Wextra,您就会收到警告。

我建议使用 -Wall -Wextra -pedantic 编译器选项

https://godbolt.org/z/TvqeKn

编辑

作为对非常不友好和不友好的 OP 评论的澄清。 -Wextra 启用以下警告包括 OP 想要的警告

enter image description here

warning: comparison of integer expressions of different signedness:
 'unsigned int' and 'int' [-Wsign-compare]
    9 |     if (i != argc)
,

问题被标记为 C,但链接到 C++ Godbolt 示例。以下是显示警告何时发出的表格:1

C 非常量 C 常量 C++ 非常量 C++ const
默认警告 没有 没有 没有 没有
-Wall 没有 没有 没有
-Wall -Wextra 没有

因此,在 C 中,无论 -Wextra 限定如何,GCC 都会在 const 中提供警告。

在 C++ 中,GCC 在 -Wall 中提供警告,但将 const 限定对象视为可以取消警告的已知值。

GCC documentation 表示,对于 -Wsign-compare

当有符号值转换为无符号值时,有符号值和无符号值之间的比较可能会产生不正确的结果时发出警告。在 C++ 中,此警告也由 -Wall 启用。在 C 中,它也由 -Wextra 启用。

请注意,当有符号值和无符号值之间进行比较时,它并没有说它会发出警告,而是在这种比较可能会产生不正确的结果时发出警告。因此,当对象的定义使得比较不会产生不正确的结果时不提供警告不是错误。

“可以”这个词为编译器“知道”对象的内容留下了余地。未能确定 C const 情况不会产生不正确的结果可以被描述为错误,尽管将其描述为缺点可能更好。

脚注

1 表中的“Const”专门用于使用const限定的对象,其值可通过可见定义立即供编译器使用。例如,我没有测试这样的情况,例如,为 const 限定的对象声明了标识符,但其定义在另一个翻译单元中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。