为什么在C ++中,如果数字为常数,则static_cast <unsigned>为负数会有所不同


28

等于equalfalse的C ++规则是什么?鉴于:

float f {-1.0};
bool equal = (static_cast<unsigned>(f) == static_cast<unsigned>(-1.0));

例如https://godbolt.org/z/fcmx2P

#include <iostream>

int main() 
{
          float   f {-1.0};
    const float  cf {-1.0};

    std::cout << std::hex;
    std::cout << " f" << "=" << static_cast<unsigned>(f) << '\n';
    std::cout << "cf" << "=" << static_cast<unsigned>(cf) << '\n';

    return 0;
}

产生以下输出:

 f=ffffffff
cf=0

6
祝您投票愉快:有关不确定行为,您经常被遗忘的规则所困扰!
Bathsheba

您期望将负浮点数转换为无符号数有什么结果?
Amadeus

1
@Amadeus可能是我们在转换负整数时得到的通常环绕。我不得不检查那是UB,因为这让我感到惊讶。
AProgrammer19年

1
@Amadeus,更多的是了解差异。我在几周前修复了一个错字错误... const-float被显式强制转换为unsigned(错误),然后隐式地恢复为signed(作为一个签名函数参数)。后来我思考为什么原始的bug导致该函数的值为零。测试表明这是因为浮点数是常量。显式强制转换为无符号然后隐式转换为有符号的非常量浮点数不会产生相同的行为-两次强制转换的非常量具有原始值和期望值。
GreyMattR

Answers:


26

程序的行为是不确定的:C ++标准未定义浮点类型unsigned类型的转换。

(请注意,熟悉的环绕行为仅适用于负整数类型。)

因此,尝试解释程序输出毫无意义。


1
是否定义了是否将float-> int-> unsigned转换?
Yksisarvinen

5
@Yksisarvinen:仅当float处于范围内时int
Bathsheba

我接受UB是正确的答案,因此应该以UB结尾。等效(UB)输出?
GreyMattR

5
@GreyMattR如果编译器可以证明在强制转换时该值肯定为负,则它可以保留强制转换的结果未初始化,将其设置为零或执行其他任何操作。如果编译器无法证明这一点,则它必须生成代码以执行强制转换。为此,它可以重用代码以将其转换为有符号整数类型(如果转换为UB,则结果只会是“错误的”,这意味着它实际上并不是错误的)。通过更积极的优化,在非const情况下也不会发出强制类型转换。
布莱恩

@Brian,感谢您的有用解释。
GreyMattR
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.