tags:
- Cpp
Casting in C++ (NC)
我们观察下面的一段代码,思考这两个问题:pi_int
的值是怎么转换成 3 的?直接输出 355/113
为什么是整数 3
?
#include <iostream>
int main(){
int pi_int = 3.14159;
std::cout << pi_int << std::endl; // 3
std::cout << 355/113 << std::endl;// 3
return 0;
}
这两个问题都和 implicit narrowing conversion 有关。当我们运行 int pi_int = pi;
时,由于类型不同,这里会发生 narrow conversion( casting 的一种)。会损失相关的数据和精度,将结果截断到整数个位,损失小数的精度。
在执行 std::cout << 355/113 << std::endl;
时,编译器会先检查除数和被除数的类型。这两种类型都是 int
类型,所以编译器断定商数应该是 int
类型的,在运行这行代码时也会出现截断。要输出正确的值,我们可以将类型显式地告诉编译器或者显式地使用浮点字面量类型。如:
#include <iostream>
int main(){
std::cout << (double)355/(double)113 << std::endl; // 3.14159
// or, explicitly use the float literals
std::cout << 355.0/113.0 << std::endl; // 3.14159
return 0;
}
这种将一种类型变成另一种类型的方式就是我们所说的强制类型转换,这是一种 C-style casting。
上述的这些类型转换我们喜欢么?可能一般,因为它们不一定保证类型安全。除了可能发生的截断之外,编译器解析不同类型的方式也是不一样的,如果你把一个 int
类型值赋给 char
类型变量,输出 char
后你并不会看到一个整型数,而大概率是一个字符。
int val = 65;
char c = val; // implicit conversion
std::cout << c; // prints out 'a'
std::cout << (int)c; // prints out 65
int val2 = 256;
char danger = val2; // undefined behavior
为了类型安全,在 C++11 后引入的列表初始化禁止这种 narrowing conversion。
int pi = 3.14; // okay
int pi{3.14}; // error