【发布时间】: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