我使用的编译器是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。?
答案 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;这也处理非常小的正数)。