获取有关从无符号到有符号的隐式转换溢出的警告

时间:2018-10-22 15:01:03

标签: c++ gcc clang overflow implicit-conversion

考虑以下有问题的代码:

#include <iostream>

void foo(int64_t y) {
    std::cout << y << "\n";
}

int main() {
    uint64_t x = 14400000000000000000ull;
    foo(x);
}

通常打印-4046744073709551616

如何让编译器帮助解决这种类型的转换/溢出问题?我尝试了以下方法:

g++ -g overflow.cpp -fsanitize=undefined -Wall -Wextra -pedantic -Wconversion -Wconversion
clang++ -g overflow.cpp -fsanitize=undefined,integer,implicit-conversion -Wall -Wextra -pedantic

没有一个会给出任何编译或运行时警告。

(clang版本7.0.0,gcc版本8.2.1)

2 个答案:

答案 0 :(得分:2)

这里的问题是-Wconversion仅在值返回给源类型时可能不是同一类型时才会发出警告。例如,如果fooint,则-Wconversion将发出警告,因为您可能无法将int中的值转换回原始uint64_t值。如果有

uint64_t u = some_value;
int64_t s = static_cast<int64_t>(u);
uint64_t check = static_cast<uint64_t>(s)

然后check == u将始终为真(只要int64_t也是两个的称赞),因此-Wconversion将不会发出警告,因为我们将源值取回了。

在这种情况下,您需要的是

-Wsign-conversion

这会警告您信号不匹配。

答案 1 :(得分:1)

GCC和Clang都有警告选项-Wsign-conversion在这种情况下发出警告。

  

警告:隐式转换将签名:'uint64_t'(又名“ unsigned long”)更改为“ int64_t”(又名“ long”)[-Wsign-conversion]

注意GCC关于-Wconversion的文档

  

...默认情况下,除非显式启用-Wsign-conversion,否则在C ++中默认禁用有关有符号和无符号整数之间转换的警告。

还请注意,程序格式正确(因此必须成功编译),并且没有未定义的行为(因此也没有理由触发清理程序)。将无法代表的数字转换为带符号的结果会导致实现定义值。