C++ primer Plus系列之 c++之数值类型转换

c++中数据类型转换的时候要注意一下几点:

1.数值较大的浮点类型转换为较小的浮点类型的时候(例如double转化为float), 首先一点精度会降低(也就是有效的数字位数会降低),  其次一点如果数值大于被转化成的数值类型的话结果会出现不确定性

2.将浮点类型转化为整形的时候, 第一.小数部分会丢失,  第二如果原来的数值大于目标类型的取值范围, 最终结果会不确定

3.较大的整型转化为较小的整形例如long转化为char, 当原来的值大于目标的取值返回的时候, 通常会复制右边的字节给目标

4.0赋值为bool类型为false, 非0赋值给bool类型为true.

接下来看下下面这段代码的运行结果:

#include "iostream"
using namespace std;

int main() {
	cout.setf(ios_base::fixed, ios_base::floatfield);
	float three = 3;
	int n_num(1.2345);
	int n_num2(1.9876);
	int n_unknow = 2.345E10;
	
	cout << "three = " << three << endl;
	cout << "n_num = " << n_num << endl;
	cout << "n_num2 = " << n_num2 << endl;
	cout << "n_unknow = " << n_unknow << endl;	
}

程序的运行结果为:

我们看到int值赋给float会自动升级成float类型, 而一个浮点类型(1.2345, 默认是double, 除非指定为1.2345f)赋值给整形时会只取整数部分舍弃小数部分(而不是四舍五入). 而当一个浮点类型超出int的范围后就会产生不确定数(需要看系统). 并且注意看红框里的警告, 会警告我们超出int的取值范围了.

{}列表初始化对数值转换的作用

C++11将使用{}的初始化成为列表初始化(list-initialization), 列表初始化用于给复杂的数据类型提供值列表, 与常规的初始化相比, 它对类型转换的要求更为严格, 我们看下面这个例子:

#include "iostream"
using namespace std;

int main() {
	const int code = 11;
	int x = 22;
	char c1 {123455};
	char c2 = {33};
	char c3 {code};
	char c4 = {x};
	x = 34560;
	char c5 = x;
	char c6 {6.2345};
	
	cout << "c1 = " << (int)c1 << endl;
	cout << "c2 = " << int(c2) << endl;
	cout << "c3 = " << (int)c3 << endl;
	cout << "c4 = " << (int)c4 << endl;
	cout << "c5 = " << (int)c5 << endl;
	cout << "c6 = " << (float)c6 << endl;
}

对应的输出结果为:

从结果可以看出当给char赋值一个超出char类型的取值范围的数值时, 编译器会包警告说超出了范围, 再看c1的结果是64是因为123455的二进制是11110001000111111, 截取了低八位给了c1所以c1是63.

书上说: {}初始化的时候不允许缩窄, 也就是变量的类型可能无法表示赋给它的值(例如:不允许将浮点类型转化为整形), 在不同的整型之间转换或者整型转化为浮点型是可以的, 条件是编译器能够知道目标变量能正确存储赋给它的值(例如:long变量初始化为int值, 因为long总是至少与int一样长, 相反方向也是能允许的, 只要int变量能存储赋给它的long常量)

但是我测试的时候c6也能正常赋值, 只是把整数部分赋给了c6, 没有像书上说的报错, 只是有一个警告说可能超出范围了, 不知道是不是编译环境造成的.

表达式中的类型转换:

在不同类型的数据进行算数运算的时候也会进行一些类型转换, 通常来说当运算涉及多种类型的时候, 是把较小的类型转化为较大的类型. 例如: 3.0/2 结果是double类型的, 会先把2转化为double然后运算.

类型从大->小的排序是:long double, double, float, int.

此外还有:

如果两个操作数都是有符号或无符号的, 且其中给一个操作数比另一个低, 则转换为级别高的类型;

如果一个是有符号的, 另一个是无符号的, 且无符号的操作数比有符号的操作数级别高, 则有符号的操作数转化为无符号的操作数类型;

如果符号类型可表示无符号类型的所有可能取值, 则将无符号的操作数转换为有符号的操作数, 否则两个操作数都转换为有符号类型的无符号版本.

 

强制类型转换:

C++里关于数值的集中强制类型转换方式:

(long) num

long (num)

static_cast<long> (num)

第一种是c语言中的, 第二种是c++的为了使得强制类型转换就像是函数调用一样, 第三种提供了更为严格的转换方式, 下面是简单的例子:

#include "iostream"
using namespace std;

int main() {
	int num1, num2, num3;
	num1 = 19.99 + 11.99;
	num2 = (int) 19.99 + (int)11.99;
	num3 = int (19.99) + int (11.99);
	
	cout << "num1 = " << num1 << endl;
	cout << "num2 = " << num2 << endl;
	cout << "num3 = " << num3 << endl;
	
	char ch = 'a';
	cout << "thd code of " << ch << "is : " << endl;
	cout << int(ch) << endl;
	cout << "yes, the code is : " << endl;
	cout << static_cast<int> (ch) << endl;
	return 0;
}

运行结果为:

num1结果为31是因为先把两个double类型的数值相加后等于31.98, 然后把31.98截取整数部分赋给int型变量num1, 而num2和num3位30的原因是先把19.99和11.99给转化成19和11两个int然后相加赋值给num3的

 

auto声明

c++11增加了一个新的关键字, 能够让编译器自动根据初始值推断出变量的类型例如:

auto a = 1; // a 是int型

auto b = 1.0; // b是double类型

auto c = 1.23e10L // c是long double类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值