【c/c++】类型转换:隐式类型转换、强制类型转换
目录
前言
一、了解类型转换
二、隐式类型转换
1.适用场景
2.转换规则
三、强制类型转换
适用场景
使用规则
注意事项
前言
类型转换是编程中一个常见的现象。在我们进行编码的时候不经意间就发生了,但却能让整个程序运行得更加流畅。
但是这种不经意,实在过于隐形和丝滑,很可能就给我们带来不少bug。
所以我们需要了解类型转换以及对应得出现场景。
一、了解类型转换
变量的类型间是可以互相转换的,转换又分为自动转换和强制转换。
C/C++中的类型转换主要有四种:隐式类型转换、C风格类型转换、C++的static_cast、const_cast、reinterpret_cast以及dynamic_cast。
这里,我们先了解隐式类型转换和C风格类型转换,然后再介绍C++的四种类型转换操作符。
- 隐式类型转换(Implicit type conversion):编译器在需要的情况下自动进行的类型转换。例如,从较小的整数类型转换为较大的整数类型,或者从整数类型转换为浮点类型。在这种情况下,编译器会生成类型转换的指令,以确保在运行时数据被正确地转换。
char c = 'A';
int i = c + 1; // 'A' 隐式地转换为了它的 ASCII 值 65
- C风格类型转换(C-style type casting):也可以成为强制类型转换。这种类型转换使用类型名作为转换操作符,语法为
(type)expression
。例如,将整数转换为浮点数:float x = (float)int_value;
。C风格类型转换是强制性的,它可能导致一些意想不到的结果,因为它允许将任意类型转换为另一种类型。在底层,C风格类型转换通常通过生成与隐式类型转换相似的指令来实现。
double a = 10.5;
int b = (int)a; //a被强制转为int类型
二、隐式类型转换
1.适用场景
- 自动转换是C++编译器自动完成的类型转换。
- 当两个不同类型的数据进行运算时,编译器会自动将它们转换为相同的类型(优先转换为较高类型计算),以便进行运算。
- 自动转换的特点:简单、方便,无需手动进行类型转换,可以提高编程效率。
- 但是,自动转换也存在一些问题。由于编译器自动进行类型转换,有时候会出现意料之外的结果。例如,当一个整数和一个浮点数相加时,编译器会自动将整数转换为浮点数,但是由于浮点数的精度问题,可能会导致结果出现误差。因此,在进行自动转换时,需要注意精度问题。
自动转换适用于一些简单的类型转换场景,
例如整型和浮点型之间的转换,可以通过自动转换来实现。
2.转换规则
1、若参与运算量的类型不同,为了提高效率,C /C++语言对于不同的两个类型将直接转换成较高类型计算。
int a =5;
double b = 6.6;
cout << a + b << endl; //结果为double类型
类型优先级
2. float、double、long double 类型赋值给整数类型:直接截断小数
#include <stdio.h>
int main() {
float a = 3.8;
int b = a; //进行了一次隐式类型转换
printf("a=%.2f; b=%d", a, b);
return 0;
}
输出结果:
a=3.80; b=3
3. 整数类型赋值给浮点数(float、double、long double)类型:补足有效小数位
对上述代码进行修改:
#include <stdio.h>
int main() {
int a = 8;
float b = a; //进行了一次隐式类型转换
printf("a=%d; b=%f", a, b);
return 0;
}
结果:
a=8; b=8.000000 //%f默认输出6位小数
4. 存储长度较短的类型赋值给存储长度较长的类型:补足有效位,其它位补 0
但是本身数值不改变。
char c = 56;
short num = 67;
int m;
long long int n;
//执行下面得赋值语句
m = ((int)c);
n = ((long long)num);
补0过程
00111000 //Binary of 'c' 00000000 01000011 //Binary of 'num' 00000000 00000000 00000000 00111000 //Binary of 'm' 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01000011 //Binary of 'n'
输出结果:
5. 存储长度较长的类型赋值给存储长度较短的类型:舍弃高位(但保留符号),截断低字节给存储长度较短的类型
#include <iostream>
using namespace std;
int main() {
long long int l = 223372036854775807;
int i = (int)l;
cout << l << endl;
cout << i << endl;
return 0;
}
它们在内存以2进制格式分别存储为:
00000011 00011001 10010011 10101111 00011101 01111011 11111111 11111111 //Binary of 'l' 00011101 01111011 11111111 11111111 //Binary of 'v'
结果:
6. unsigned类型赋值给非unsigned类型:直接传递数值
注意:如果 unsigned 类型储存的量太大,强制类型转换后可能会出现非 unsigned 类型的值的绝对值不等于 unsigned 类型的值的绝对值的情况。
说到 “unsigned 类型储存的量太大”,顺带说一下,虽然 printf 输出 int 和 unsigned int 时可以混用 %d(或%i)和 %u(或%ui),但还是建议输出 int 类型的时候用 %d(或%i),输出 unsigned int 类型时用 %u(或%ui)(其它类型同理<如%ul等>)
看一个例子:
#include <stdio.h>
int main() {
unsigned int x = 4294967295; //这个数字为(2^32)-1, 而int类型最大存储数字的值为(2^31)-1
int y = ((int)x); //x强制转为了 int (unsigned int => int)
printf("signed of x= %d", x); //这里有一次隐式类型转换(unsigned int => int)
putchar('\n');
printf("unsigned of x= %u\n", x);
printf("signed of y= %d", y);
return 0;
}
可是因为隐式类型转换,结果输出为:
-1
4294967295
-1
出现“-1”的这个输出就是因为“unsigned类型储存的量太大(大于了同类型但非unsigned的类型)”
p.s: 不一定都为 -1,具体要看 unsigned 类型的值的 2 进制
7、非 unsigned 类型赋值给 unsigned 类型:直接传递数值
给个小技巧:如果你想“临时”给一个不知道正负的非 unsigned 类型的变量加上绝对值,可以使用abs函数,但利用(unsigned)(非unsigned类型变量名)可以节省一点内存开销
但是也有弊端:可能会出现 unsigned-unsigned 永远大于 0 的情况(不确定)
最后补充一下,强制类型转换只是临时类型转换,并不影响变量本身储存的值,看如下代码:
#include <stdio.h>
int main() {
float a = 6.9;
printf("%.3f", a);
putchar('\n');
((int)a);
printf("%.3f", a);
return 0;
}
输出结果:
6.900
6.900
三、强制类型转换
适用场景
而强制转换适用于一些需要精确控制类型转换的场景,例如将一个浮点数转换为整数,或者将一个指针类型转换为另一种类型时,需要使用强制转换。
在实际编程中,需要根据具体的场景选择适合的类型转换方式。如果不确定应该使用哪种类型转换方式,可以先使用自动转换,然后进行必要的验证和调整。如果需要更精确地控制类型转换的结果,可以使用强制转换,但是需要进行必要的检查和验证,以避免出现错误。
使用规则
强制类型转换是通过类型转换运算来实现的。
其一般形式为:(类型说明符)(表达式)其功能是把表达式的运算结果强制转换成类型说明符所表示的类型.
比如:
#include <iostream> using namespace std; int main() { double a = 10.1; cout << (int)a << endl;//发生了强转,double -> int return 0; }
注意事项
强制类型转换是一种非常强大的工具,它可以将一个变量的类型转换为另一种类型。但是,强制类型转换也存在一些潜在的安全问题,需要特别注意。在介绍强制类型转换时,需要说明类型转换的安全性,并解释如何避免可能的类型转换错误。
1.类型转换失败的可能性
在使用强制类型转换时,可能会出现类型转换失败的情况,例如:
- 当将一个浮点数转换为整数时,可能会出现精度损失的问题。
- 当将一个指针类型转换为另一种类型时,可能会出现指针错误或者内存泄漏的问题。
- 当将一个常量数据进行强制类型转换时,可能会出现未定义行为的问题。
2. 如何避免类型转换错误
为了避免类型转换错误,需要进行必要的检查和验证。具体而言,可以采取以下几个措施:
- 在进行强制类型转换之前,需要对变量进行必要的检查和验证,确保转换是安全的。
- 在将一个浮点数转换为整数时,需要注意精度问题,并进行必要的四舍五入。
- 在将一个指针类型转换为另一种类型时,需要确保指针指向的内存空间是有效的,并且转换后的类型可以正确处理指针的值。
- 在使用const_cast时,需要确保不会更改常量数据,否则会引发未定义行为。如果需要更改常量数据,可以使用其他类型转换方式,例如reinterpret_cast。
需要注意的是,在进行类型转换时,需要保证程序的正确性和安全性。如果不确定类型转换是否安全,可以先进行必要的验证和测试,确保程序运行正确。同时,需要遵循C++的类型转换规则,并严格遵守语言的规范。这样,就可以避免类型转换错误,提高程序的可靠性和安全性。
💗感谢阅读!💗
参考文章:
【C/C++ 类型转换规则】一文了解C/C++ 中的类型转换规则,帮助你更好的编程-阿里云开发者社区
【C++入门到精通】C++类型的转换 | static_cast | reinterpret_cast | const_cast | dynamic_cast [ C++入门 ]-阿里云开发者社区