C++类型转换
一、整形提升
整型提升是一种隐式类型转换,当涉及到小于int类型的整数(如char、short、bool等)时。整型提升的目的是确保所有的操作数在算术运算或比较操作中具有相同的类型,通常是int类型,如果int不能表示该值,则可能会提升到unsigned int或更大的整数类型。
二、无符号数和带符号数进行运算的原则
如果一个是无符号数,另一个是带符号类型,那么:
1)无符号类型 >= 带符号类型,带符号类型转化为无符号类型。
unsigned int a = 10u;
int b = 5;
cout << a + b << endl;
//b转化为unsigned int
2)无符号类型 < 带符号类型,此时结果依赖于机器。
如果无符号数类型的所有值都能存在该带符号类型中,则无符号类型的运算对象转换成带符号类型。
如果不能,那么带符号类型的运算对象转换成无符号类型。
三、算数转换
bool b;
char c;
short s;
unsigned short us;
int i;
unsigned int ui;
long l;
unsigned long ul;
float f;
double d;
cout << 3.14159L + 'a' << endl;
//此处'a' 先提升至int,然后int转化为long double类型
cout << c + f << endl;
//char先提升为int,然后该int转化为float
cout << s + c << endl;
//short和char都提升为int
cout << us + i << endl;
//根据unsigned short和int所占空间大小进行整型提升
cout << ui + l << endl;
//同上
四、显示转换
C++中类型强制转换的形式如下:
cast_name<type>(expr);
1、static_cast
1)不含底层const的均可使用
const char* c = "hello";
string s = static_cast<char *>(c); //error,不能为底层const
cout << s << endl;
char* const c = "hello"
string s = static_cast<char *>(c); //right,const为顶层const
cout << s << endl;
2)不能用于高风险转换。
指针和非指针类型
不同类型的指针之间
不同类型的引用之间
3)将一个大的算术类型赋值给小的算数类型
double d = 3.14159;
int i = static_cast<double>(d);
cout << i << endl;
4)编译器无法自动执行类型转换时
2、const_cast
const_cast
只针对指针、引用
,当然,this指针也是其中之一。
const_cast可以用来移除常量性
。移除后再对常量进行修改,编译器不会进行阻止。
1)用于指针
const char *cp;
char *p = const_cast<char *>(cp);
2)用于引用
int a = 0;
const int &b = a;
int &c = const_cast<int &>(b);
c = 10;
const_cast只能改变常量属性,并不能更改基础类型
。
只能改变常量属性
const char *c = "hello";
string *s = const_cast<string *> c;
//error:不能改变基础类型
3、reinterpret_cast
reinterpret_cast提供了最低级别的转换
,将一个指针或整数类型转换为另一个指针或整数类型,而不进行任何类型检查或转换
。它基本上是对位模式的重新解释,这意味着它不会改变值,只是改变了编译器如何解释这个值
。
reinterpret_cast 是一个非常强大但也非常危险的工具,因为它允许程序员绕过 C++ 的类型系统。
以下是它的一些常见用法和注意事项:
1)指针到指针的转换:
reinterpret_cast 允许你将一个类型的指针转换为另一个类型的指针,而不考虑这两个类型是否兼容。
int* int_ptr = new int(42);
// 使用reinterpret_cast将int*转换为char*
char* char_ptr = reinterpret_cast<char*>(int_ptr);
但是,这样做通常是不安全的,除非你确切知道你在做什么(例如,处理内存映射文件或低级硬件操作)。
`
2)整数到指针的转换:
在某些情况下,你可能需要将整数(通常是地址)转换为指针。虽然 static_cast 在这种情况下不起作用,但 reinterpret_cast 可以。
int a = 10;
char *p = reinterpret_cast<char *>(a);
*p = 'a';
cout << a << endl;
3)函数指针的转换:
reinterpret_cast 也允许你转换函数指针的类型。但是,除非你知道目标类型的函数签名与源类型的函数签名完全匹配,否则这样做是非常危险的。
四、隐式转换
1)在大多数表达式中,比int小的整型值先提升为较大的整数类型。
2)在条件中,非布尔值转换为布尔值。
3)初始化过程中,初始值转换为变量的类型;
int main()
{
// 整数字面量隐式转换为int类型
int a = 42;
// 浮点数字面量隐式转换为double类型(如果变量是double)
double b = 3.14;
// char字面量隐式转换为int类型(char在C++中实际上是小的整型)
char c = 'A'; // ASCII值65
// 窄整型转换为宽整型(如果赋值给宽整型变量)
short s = 10;
int i = s; // s隐式转换为int
// 转换也可能导致精度损失或截断(如果目标类型不能容纳原始值)
int j = 3.14; // 3.14被截断为3
return 0;
}
4)在赋值语句中,右侧运算对象转换成左侧运算对象。
int main() {
int x = 10;
double y = 20.0;
// 右侧是int,左侧是double,int隐式转换为double
y = x; // x的值被隐式转换为double类型,然后赋值给y
// 右侧是double,左侧是int,double转换为int(可能丢失精度)
x = y; // y的值被截断为int类型,然后赋值给x
return 0;
}
5)如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。
//整数提升
//当较小的整数类型(如char、short)与较大的整数类型(如int、long)进行算术运算时,较小的类型通常会被提升为较大的类型。
short s = 10;
int i = 20;
int sum = s + i; // s 被提升为 int,然后与 i 相加
//整数与浮点数的运算
//当整数与浮点数进行算术运算时,整数通常会被提升为浮点数。
int i = 10;
double d = 3.14;
double product = i * d; // i 被提升为 double,然后与 d 相乘
//浮点数运算
//当两种不同精度的浮点数(如float和double)进行运算时,通常较低精度的类型会被提升为较高精度的类型。
float f = 3.14f;
double d = 2.71;
double result = f + d; // f 被提升为 double,然后与 d 相加
6)函数调用也会发生类型转换