【问题标题】:Warnings on sign conversion when assigning from the result of unsigned division从无符号除法的结果分配时出现符号转换警告
【发布时间】:2020-10-26 18:06:29
【问题描述】:

我用-Wsign-conversion编译了以下代码:

int main() 
{
  unsigned int a = 8;
  int b = a + 8u;  // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
  int c = a - 8u;  // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
  int d = a * 8u;  // warning: implicit conversion changes signedness: 'unsigned int' to 'int'
  int e = a / 8u;  // gcc warns, but no warning in clang
}

从无符号除法的结果进行赋值时,Clang 不会发出警告,但 gcc 会。

为什么在这一特殊情况下会有所不同?

【问题讨论】:

  • 这是因为unsigned int 不一定适合int 而不会溢出。也许clang有一个不同的标志,或者它足够聪明,知道那些不会溢出。尝试使用合适的值。
  • “对”是什么意思,就C++而言,代码是可以的。警告只是编译器让你知道你可能没有做你正在做的事情的方式
  • 另外,除非除数是1,否则任何除数都会使结果适合int
  • @NathanOliver 'right' 如 - 除法是否还引入了改变符号的隐式转换?如果是这样 - 与其他 3 个操作不同,是否有理由忽略它?
  • 我不确定为什么这个问题被否决了。在一种特定情况下,想知道为什么一个编译器发出警告而不是另一个编译器发出警告是完全合理的。

标签: c++ clang++


【解决方案1】:

Clang 只是有点聪明:无符号整数除以大于或等于 2 的无符号整数意味着无符号整数结果将始终适合有符号整数对应物(除法表达式中分子类型的结果) )。但是,如果您除以值为 1 的无符号整数,则不再保证结果适合有符号整数对应物,并且 Clang 确实会发出警告:

#include <cstdint>

int main()  {
  uint8_t a = 240;    // '240 / 1' will not fit in int8_t
  int8_t e = a / 2u;  // No warning in clang
  int8_t f = a / 1u;  // warning: implicit conversion changes signedness: 'unsigned int' to 'int8_t' (aka 'signed char') [-Wsign-conversion]
}

人们也可能会争辩说,Clang 应该能够省略对乘以 0 的类似特殊情况的警告;但是 Clang 不会,而 GCC 会:

// Clang warns, no warning in GCC.
int8_t g = a * 0u;

Clang 特别聪明,在这种情况下,w.r.t.部门和 GCC w.r.t.乘法。


最后,请注意,Clang 在除法期间发出此警告的门控似乎只有在除以 1 时才会发出,因为如果除以 0u,您将不会得到相同的 -Wsign-conversion;可以说它已被更相关(在这种情况下)-Wdivision-by-zero 警告覆盖:

int8_t h = a / 0u;
warning: division by zero is undefined [-Wdivision-by-zero]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多