从 'size_t' 转换为 'const double',可能会丢失数据

conversion from 'size_t' to 'const double', possible loss of data

给定一个变量 size_t idx,在 64 位下编译时,像 double value = idx; 这样的赋值会产生以下警告:

'initializing': conversion from 'size_t' to 'double', possible loss of data

这似乎与在64位下编译时size_t值占用8个字节有关。但是,赋值 double value = static_cast<double>(idx) 不会产生任何警告。有人可以向我解释为什么前一个作业不起作用而后者起作用吗?

提前致谢!

这是一个警告,因为程序员可能没有意识到他们在赋值过程中丢失了位。

但是,如果您在那里进行了显式转换,编译器会假定程序员知道他们在做什么,因为转换就在那里,而且就在您的面前。

static_cast<double> 是您告诉编译器您正在有意识地转换为 double 并且了解所有含义的方式。这意味着编译器不应该警告您这些风险,因为您已经明确告诉它您已经知道这些风险。

在第一种情况下,您不使用 static_cast,转换是合法的,但存在丢失精度的风险。由于您可能没有注意到这种转换正在发生,因此向您发出警告很有意义。

两项作业都 'work',而且实际上做的是完全一样的事情!唯一的区别是,在第二种情况下,double value = static_cast<double>(idx),你的 explicit 转换让编译器清楚地知道你 "know what you're doing" 并且你可能会丢失有效数字转换。

在第一种情况下,编译器只是警告您您的转换可能(无意中)导致数据丢失(或精度,在这种情况下)。

当你这样做时

double value = idx;

编译器查看它并运行:"Hey, idx might not be able to fit in value, lets tell the programmer in case it was a mistake."。这就是您收到警告的原因。

当你这样做时

double value = static_cast<double>(idx)

编译器查看它并运行:"Oh, the programmer is explicitly casting here, this must be what they want."。这意味着它不会出现警告。

64 位双精度数仅使用 52 位存储数字,其余部分用于存储符号(+-)和指数。 (注意:这是IEEE754的实现,double的实现在其他语言标准中可能有所不同)

unsigned int (a.k.a size_t) 使用所有 64 位来存储数字,但没有为指数留出空间,因此没有 浮点整数精度,如size_t

因此,编译器告诉您,如果您的 64 位无符号整数大于 64 位 double 类型的尾数可以存储的数量(即 更大52 位 ),它可能会导致数据丢失,并可能导致代码的其余部分出现未定义行为。

static_cast<double>(idx)是程序员告诉编译器不要担心的断言,您会牢记上述预防措施。

来源:https://en.wikipedia.org/wiki/Double-precision_floating-point_format