首页 > 解决方案 > 在 C++(和 C)中进行类型转换时出现明显的不一致

问题描述

任何人都可以在这里解释输出吗?我一直试图理解为什么类型转换文字的结果与此代码中的类型转换变量不同。

#include <iostream>
#include <cstdint>

using namespace std;

int main()
{
    double intermediate;
    intermediate = -1.0;
    cout << "intermediate = " << intermediate << endl;
    cout << "uint64_t(intermediate) = " << uint64_t(intermediate) << endl;
    cout << "uint64_t((double)(-1)) = " << uint64_t((double)(-1)) << endl;

    return 0;
}

我得到的输出是:

intermediate = -1                                                                                                                                   
uint64_t(intermediate) = 18446744073709551615                                                                                                       
uint64_t((double)(-1)) = 0  

标签: c++casting

解决方案


您正在执行从浮点类型到整数类型的超出范围的转换。

由于 double 值-1.0不能放入 a 中uint64_t,因此这被认为是超出范围的转换。这种转换会调用未定义的行为。这意味着,除其他外,两次转换的尝试不需要产生相同的结果。

请注意,这不同于有符号整数到无符号整数的转换,这在所有情况下都有明确定义。

这是由C++17 标准的 7.10p1 规定的:

浮点类型的纯右值可以转换为整数类型的纯右值。转换截断;也就是说,小数部分被丢弃。如果截断的值不能在目标类型中表示,则行为未定义。

C11 标准的第 6.3.1.4p1 节有类似的语言:

当实浮点类型的有限值转换为除 以外的整数类型_Bool时,小数部分被丢弃(即,该值被截断为 0)。如果整数部分的值不能用整数类型表示,则行为未定义。61)

...

61) 将整数类型的值转换为无符号类型时执行的求余运算不需要在将实浮点类型的值转换为无符号类型时执行。因此,可移植实浮点值的范围是 (−1,Utype_MAX+1)

要获得一致的结果,您首先需要转换为有符号整数类型,然后是无符号类型。

cout << "uint64_t(intermediate) = " << 
        static_cast<uint64_t>(static_cast<int>(intermediate)) << endl;

对于 C:

printf("uint64_t(intermediate) = %llu\n", (uint64_t)(int)intermediate);

推荐阅读