【问题标题】:Why does c++ assert() falsely call abort() when comparing a negative int to an unsigned int?为什么在将负整数与无符号整数进行比较时,c++ assert() 会错误地调用 abort()?
【发布时间】:2021-10-17 07:31:17
【问题描述】:

我在我的 c++ 程序中发现 assert() 在类似于以下代码 sn-p 的情况下调用 abort():

int a = -1;
unsigned int b = 5;

assert(a < b);

作为一个人类,我可以说 -1 肯定小于 5,而不管一个是 int 而另一个是 unsigned int 的事实。为什么编译器不行?

我已经找到了解决方案,即这个断言是无意义的,因为无符号总是肯定的(我有点忘记了我实际代码中的变量是无符号的),但我只是好奇为什么会这样。

【问题讨论】:

  • 你的编译器应该警告你比较不同有符号的变量。做到了?在比较变量时,最好始终将值转换为相同的有符号或无符号。请注意,这可能会截断值。
  • 人类在这里错了。您在此处比较无符号和有符号,这意味着结果将转换为 unsigned 整数类型,并且由于将 -1 转换为 unsigned 会产生最大可能值,因此您正在应用的第一个参数此转换后的比较更大。顺便说一句,你的编译器很可能会警告你这个问题。
  • 比较intunsigned时,int先转换成unsigned,再比较转换后的值。将-1 转换为unsigned 可以得到unsigned 可以表示的最大值——大于5
  • 在执行比较之前,a 变量被强制转换为(非常大的)无符号整数

标签: c++ integer assert unsigned


【解决方案1】:

当您将有符号整数与无符号整数进行比较时,编译器会将有符号值隐式转换为无符号值,因此本质上是:

int a = -1;
unsigned int b = 5;

assert(a < b);

相当于:

assert(static_cast<unsigned>(-1) < static_cast<unsigned>(5));

现在,由于无符号整数不能保存负值,-1 会由于integer overflow 而返回到UINT_MAX

assert(UINT_MAX < static_cast<unsigned>(5));

这显然是错误的,因为UINT_MAX大于5,所以断言失败。

【讨论】:

  • 数字 -1 环绕到 UINT_MAX 不是 2 补码的结果。
猜你喜欢
  • 1970-01-01
  • 2011-04-17
  • 2022-11-29
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多