将 double 转换为有符号整数与无符号整数

casting double to signed vs unsigned integer

似乎 MSVC 编译器以不同方式处理有符号和无符号溢出。转换超过最大整数值的双精度值时,结果是可能的最小整数值(始终相同)。转换为 unsigned int 时,转换会按预期产生溢出(最大 unsigned int 值 + 1 产生 0,最大 unsigned int + 2 产生 1,...) 有人可以解释编译器的行为,还是一个错误?

已测试编译器 MSVC 10 和 14

#define BOOST_TEST_MODULE Tests
#include <boost/test/unit_test.hpp>
#include <climits>
#include <iostream>
BOOST_AUTO_TEST_CASE(test_overflow_signed) {
  double d_int_max_1 = INT_MAX + 1.; //2147483647 + 1
  double d_int_max_2 = INT_MAX + 2.; //2147483647 + 2

  BOOST_CHECK((int)(2147483648.) != (int)(2147483649.)); //succeeds (overflows to -2147483648 and -2147483647)
  BOOST_CHECK((int)(d_int_max_1) != (int)(d_int_max_2)); //fails (both values overflow to -2147483648)
  std::cout << "(int)(2147483648.) == " << (int)(2147483648.) << std::endl; //-2147483648
  std::cout << "(int)(2147483649.) == " << (int)(2147483649.) << std::endl; //-2147483647
  std::cout << "(int)(d_int_max_1) == " << (int)(d_int_max_1) << std::endl; //-2147483648
  std::cout << "(int)(d_int_max_2) == " << (int)(d_int_max_2) << std::endl; //-2147483648
}

BOOST_AUTO_TEST_CASE(test_overflow_unsigned) {
  double d_int_max_1 = UINT_MAX + 1.;//4294967295 + 1
  double d_int_max_2 = UINT_MAX + 2.;//4294967295 + 2
  //BOOST_CHECK((unsigned int)(4294967296.) != (unsigned int)(4294967297.)); //compiler fails (!= truncation of constant value)
  BOOST_CHECK((unsigned int)(d_int_max_1) != (unsigned int)(d_int_max_2)); //succeeds (overflows to 0 and 1)
  std::cout << "(unsigned int)(d_int_max_1) == " << (unsigned int)(d_int_max_1) << std::endl; //0
  std::cout << "(unsigned int)(d_int_max_2) == " << (unsigned int)(d_int_max_2) << std::endl; //1
}

[conv.fpint]/1 A prvalue of a floating point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.

强调我的。由于行为未定义,因此任何结果都是正确的。