从'size_t'转换为"常量双倍",可能会丢失数据
conversion from 'size_t' to 'const double', possible loss of data
给定一个变量size_t idx
,像double value = idx;
这样的赋值在编译低于64位时会产生以下警告:
'initializing': conversion from 'size_t' to 'double', possible loss of data
这似乎与以下事实有关:size_t
值在 8 位下编译时占用 64 个字节。但是,分配double value = static_cast<double>(idx)
不会生成任何警告。有人可以向我解释为什么前一个作业不起作用而后者不起作用吗?
提前感谢!
当你这样做时
double value = idx;
编译器看着它,然后说:"嘿,idx
可能无法适应value
,让我们告诉程序员以防万一这是一个错误。 这就是您收到警告的原因。
当你这样做时
double value = static_cast<double>(idx)
编译器看着它,然后说:"哦,程序员在这里显式转换,这一定是他们想要的。这意味着它不会出现警告。
static_cast<double>
是你告诉编译器你正在有意识地转换为double
并意识到所有含义的方式。这意味着编译器不应该警告你这些风险,因为你已经明确告诉它你已经知道了这些风险。
在第一种情况下,如果您不使用static_cast
,转换是合法的,但存在失去精度的风险。由于您可能没有注意到这种转换正在发生,因此警告您是有意义的。
这两个作业将"工作",事实上,做完全相同的事情!唯一的区别是,在第二种情况下,double value = static_cast<double>(idx)
,显式强制转换使编译器清楚地知道您"知道自己在做什么",并且您可能会在转换中丢失有效数字。
在第一种情况下,编译器只是警告您,您的转换可能会(无意中(导致数据丢失(在本例中为精度(。
这是一个警告,因为程序员可能没有意识到他们在分配期间丢失了位。
但是,如果你在那里有一个显式的强制转换,编译器会假设程序员知道他们在做什么,因为强制转换就在那里,而且非常在你的脸上。
64 位双精度仅使用 52 位来存储数字,其余用于存储符号(+
或-
(和指数。(注:这是IEEE754实现,double
的实现可能因其他语言标准而异(
一个unsigned int
(又名size_t
(使用所有的64位来存储数字,但没有空间留给指数,因此整数中没有浮点精度
size_t
因此,编译器告诉您,如果 64 位无符号整数大于 64 位double
-type 的尾数可以存储的数量(即大于52 位(,则可能会导致数据丢失,并可能导致之后其余代码中的未定义行为。
做static_cast<double>(idx)
是程序员的断言,告诉编译器不要担心,你会记住上述预防措施。
来源:https://en.wikipedia.org/wiki/Double-precision_floating-point_format
- 防止主数据类型C++的隐式转换
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 如何在C++中序列化结构数据
- 大于65535的C++数组[size]引发不一致的溢出
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 在c代码之间共享数据的最佳方式
- 链表,反向函数,数据结构
- 数据成员SFINAE的C++17测试:gcc vs clang
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 如何对点云数据进行排序
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 从 std::string 到 std::array<char,size> 的 memcopy 额外数据是否是一种未定义的行为?