signed,unsigned和float类型之间的转换如何工作?

时间:2016-02-04 17:52:39

标签: c++11 floating-point casting type-conversion warnings

我使用的编译器是g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4.

我使用以下命令编译程序:

g++ -std=c++11 -pedantic -Wall program.cpp

程序编号。 1:

#include <iostream>
using namespace std;

int main() {
  unsigned int b;
  b = -54;
  cout << b << endl;
  return 0;
}

程序打印4294967242,这是我期望的值,因为当我们将一个超出范围的值分配给无符号类型的变量时,就是这种情况,因此结果是模除法的余数。

程序编号。 2:

#include <iostream>
using namespace std;

int main() {
  unsigned int b;
  b = 54.1234;
  cout << b << endl;
  return 0;
}

程序打印54,这也没关系,因为存储的值是小数点之前的部分,并且截断了法定部分。

程序编号。 3:

#include <iostream>
using namespace std;

int main() {
  unsigned int b;
  b = -54.1234;
  cout << b << endl;
  return 0;
}

在编译期间,我收到警告“隐式常量转换溢出”。

程序打印0.为什么会这样?我认为它会截断小数部分(如程序2),然后存储模数除法的结果(如程序1)。

但如果我写程序没有。 4:

节目编号。 4。

#include <iostream>
using namespace std;

int main() {
  unsigned int b;
  float k = -54.1234;
  b = k;
  cout << b << endl;
  return 0;
}

然后我没有得到任何警告,我得到的结果(由我预期)4294967242,这是模数除法的结果。

如果有人能向我解释,我将不胜感激。

为什么程序没有。 3表现得像程序号。 4?编译程序号时为什么不收到警告。 1,但编译程序编号时我得到一个。 3。?

2 个答案:

答案 0 :(得分:4)

根据标准(§[conv.fpint])。

  

浮点类型的prvalue可以转换为整数类型的prvalue。转换截断;也就是说,丢弃小数部分。 如果截断的值无法在目标类型中表示,则行为未定义。

所以,你的-54.1234被截断为-54。由于无法用无符号表示,因此会出现未定义的行为。

答案 1 :(得分:1)

将浮点数转换为整数时,C和C ++将浮点数舍入为零。然后,舍入结果必须可在目标类型中表示。

结果,对于32位无符号int,如果-1 <1,则保证转换得到正确的结果。 x&lt; 2 ^ 32。对于较小的数字,没有任何保证。由于-1和0之间的数字必须舍入为零,而数字-1和更小的数字没有要求,如果编译器检查x是否为0,则不会出错。在这种情况下,0结果为0。 (编译器可能会检查x <1并给出结果为0;这也处理非常小的正数)。