【c/c++】类型转换:隐式类型转换、强制类型转换


目录

前言

一、了解类型转换

二、隐式类型转换

1.适用场景

2.转换规则

三、强制类型转换

适用场景

使用规则

注意事项


前言

类型转换是编程中一个常见的现象。在我们进行编码的时候不经意间就发生了,但却能让整个程序运行得更加流畅。

但是这种不经意,实在过于隐形和丝滑,很可能就给我们带来不少bug。

所以我们需要了解类型转换以及对应得出现场景。

一、了解类型转换

变量的类型间是可以互相转换的,转换又分为自动转换和强制转换

C/C++中的类型转换主要有四种:隐式类型转换、C风格类型转换、C++的static_cast、const_cast、reinterpret_cast以及dynamic_cast。

这里,我们先了解隐式类型转换和C风格类型转换,然后再介绍C++的四种类型转换操作符。

  1. 隐式类型转换(Implicit type conversion):编译器在需要的情况下自动进行的类型转换。例如,从较小的整数类型转换为较大的整数类型,或者从整数类型转换为浮点类型。在这种情况下,编译器会生成类型转换的指令,以确保在运行时数据被正确地转换。
char c = 'A';
int i = c + 1;  // 'A' 隐式地转换为了它的 ASCII 值 65
  1. 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++入门 ]-阿里云开发者社区 

  • 24
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值