1

在我的代码中,我执行以下操作:

double a = 3.0;
uint64_t b = static_cast<uint64_t>(a);
double c = static_cast<double>(b);

有趣的是,只要 a 是正数,这就像我所期望的那样工作 (a == c),但如果 a 是负数,c 最终会成为一个任意大的正数。(它一定是包裹在某处或某处。)

我的问题是:

  1. 为什么会这样?
  2. 为什么这段代码不违反严格的别名规则?

注意: double 和 uint64_t 在我的系统上是相同的大小。

4

2 回答 2

3

严格的别名只对指针起作用。就像通过该指针强制double *转换uint64_t *和访问内存一样,因此您不必在这里担心。阅读什么是严格的别名规则?了解更多信息。

同样对于转换,它会尝试将您持有的值转换为doublea 可表示的值uint64_t。Butuint64_t是无符号的,不能表示负值,因此在尝试转换负值时会出现未定义的行为(还有太高且无法表示的正值)。在实践中,您可能会得到一些较高的正数,但您不应该依赖它。


C++ 标准 (N3797)4.9 [conv.fpint]/1说:

浮点类型的纯右值可以转换为整数类型的纯右值。转换截断;也就是说,小数部分被丢弃。如果截断的值不能在目标类型中表示,则行为未定义。[ 注意:如果目标类型是布尔型,请参见 4.12。——尾注]

doubleChris Dodd 在他的评论中所指的明确定义仅适用于整数转换,而不适用于要计算的浮点转换uint64_t

有关更多信息,我还写了一篇博文

于 2014-03-26T05:43:27.390 回答
0

uint64_t means a 64-bit unsigned integer, so when you cast to a uint64_t, if the number is negative it overflows since an unsigned integer cannot store negative numbers.

Try it with an int64_t and it will work as expected.

于 2014-03-26T05:38:46.097 回答