【问题标题】:Getting warnings for implicit conversion overflow from unsigned to signed获取从无符号到有符号的隐式转换溢出的警告
【发布时间】:2018-10-22 15:01:03
【问题描述】:

考虑以下有问题的代码:

#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 版)

【问题讨论】:

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


    【解决方案1】:

    这里的问题是-Wconversion 只会在值转换回源类型时发出警告,可能不是同一类型。例如,如果foo 将采用int,则-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
    

    这将警告您标志不匹配。

    【讨论】:

    • 我不认为check == u 保证是真的。不过,在 2 的补码系统上也是如此。
    【解决方案2】:

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

    警告:隐式转换更改符号:“uint64_t”(又名“unsigned long”)到“int64_t”(又名“long”)[-Wsign-conversion]

    注意 GCC 关于 -Wconversion 的文档

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

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

    【讨论】:

    • 我希望用“实现定义的值”填充变量会触发消毒剂。
    猜你喜欢
    • 2016-08-13
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多