在 C++(和 C)中进行类型转换时明显不一致

Apparent inconsistency during type casting in C++ (and C)

本文关键字:类型转换 不一致 C++      更新时间:2023-10-16

谁能解释这里的输出?我一直在试图理解为什么类型转换文本的结果与此代码中的类型转换变量不同。

#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  

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

由于双精度值-1.0不能容纳在uint64_t中,这被认为是一个超出范围的转换。 此类转换会调用未定义的行为。 这意味着,除其他事项外,两次转换尝试不一定会产生相同的结果。

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

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

浮点类型的 prvalue 可以转换为 整数类型。转换蹦蹦跳跳;也就是说,小数部分是 丢弃。如果截断的值不能 以目标类型表示。

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

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

61( 当值 整数类型转换为无符号类型不必 当实际浮点类型的值转换为 无符号类型。 因此,可移植实际浮点值的范围为 (−1,Utype_MAX+1(

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

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

对于 C:

printf("uint64_t(intermediate) = %llun", (uint64_t)(int)intermediate);