【问题标题】:How do the conversions between signed, unsigned and float types work?有符号、无符号和浮点类型之间的转换如何工作?
【发布时间】:2016-02-04 17:52:39
【问题描述】:

我使用的编译器是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.?

【问题讨论】:

  • 程序 3 是唯一一个同时进行常量转换和整数溢出的程序。显然这就是编译器的工作方式。我可以仔细阅读语言规范的文本,试图找出发生这种情况的确切原因,但看起来你比我有更多的时间。如果我猜的话,这可能是未定义的行为,这就是为什么你不首先编写程序 3。
  • 一般来说,依靠一致的溢出行为来进行正确的程序操作可能不是一个好主意,除非您的问题域特别需要这种位旋转。
  • 由于 x86 指令集中的一个怪癖,在从浮点到整数的转换中发生溢出时观察到的行为可能非常令人惊讶。请看blog.frama-c.com/index.php?post/2013/10/09/…

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


【解决方案1】:

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

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

因此,您的 -54.1234 被截断为 -54。由于这不能用无符号表示,因此您会得到未定义的行为。

【讨论】:

    【解决方案2】:

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

    因此,对于 32 位无符号整数,如果 -1

    【讨论】:

    • 说“更小”而不是“更小”会更好地表达意思,因为“更小”也用于表示更小的量级。
    猜你喜欢
    • 2013-04-06
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 2015-07-25
    • 2018-08-14
    相关资源
    最近更新 更多