代码之家  ›  专栏  ›  技术社区  ›  Zulan

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

  •  2
  • Zulan  · 技术社区  · 7 年前

    请考虑以下有问题的代码:

    #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 回复  |  直到 7 年前
        1
  •  1
  •   NathanOliver    7 年前

    问题是 -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
    

    这会警告你信号不匹配。

        2
  •  1
  •   eerorika    7 年前

    gcc和clang都有一个警告选项-wsign conversion,可以在这种情况下发出警告。

    警告:隐式转换将signedness:“uint64_t”(也称为“unsigned long”)更改为“int64_t”(也称为“long”)[-wsign conversion]

    注意gcc关于-wconversion的文档

    …在C++中默认情况下禁用关于符号和无符号整数之间的转换的警告,除非显式启用了-WSCONE转换。

    还要注意,程序格式良好(因此必须成功编译),没有未定义的行为(因此没有理由触发消毒剂)。在实现定义的值中将不可表示的数字转换为带符号的结果。