简单的美食网站模板,陕西住建和城乡建设官网,适合毕设做的简单网站,php 网站发布1.引言
大家在学习C语言的时候#xff0c;有没有遇见过类似于下面这样的代码呢#xff1f;
// 整形转bool
int count 10;
while(count--)
{cout count endl;
}// 指针转bool
int* ptr cur;
while(ptr)
{//……
}
众所周知#xff0c;while循环的判断…1.引言
大家在学习C语言的时候有没有遇见过类似于下面这样的代码呢
// 整形转bool
int count 10;
while(count--)
{cout count endl;
}// 指针转bool
int* ptr cur;
while(ptr)
{//……
}
众所周知while循环的判断是bool类型的变量那为什么整形变量和指针变量可以直接作为 while循环的判断条件呢之所以可以这样直接利用整形变量和指针变量作为while循环的判断条件是不是说明整形类型的变量和指针类型的变量可以转换成bool类型呢没错是的。
大家在学习编程的过程中肯定都有遇到过各种各样的 “神奇的” 类型转换这些类型转换给我们编程带来了很大的方便比如说 上面的整形直接转bool值判断、指针直接转bool值判断等等……下面我们就一起来学习一下C/C中的那些神奇的类型转换。
提醒所有的类型转换之间要有关联没有关联的类型之间即使是强制类型转换也是不能转换的。
2.C语言中的那些类型转换
在C编写C/C代码的时候我们经常会遇到发生类型转换的场景比如 赋值运算符的两个操作数不同、实参和形参类型不同、函数返回值类型和接收返回值的类型不同都会发生类型转换所以在C语言中提供了两种类型转换 —— 隐式类型转换和显示类型转换
隐式类型转换
隐式类型转换是隐式的是我们看不见的比如下面这段代码
double a 1.0;
int b a; // 发生隐式类型转换
隐式的类型转换有以下几种
1.整形和整形之间不同的整形之间是可以发生隐式类型转换的比如charshortintlong 、long long之间char是属于整形家族的哦。2.整形和浮点型之间整形和浮点型数据之间也具有一定的关联性也是可以发生隐式类型转换的比如int 和 doubleint 和 float 类型的数据……3.整形和bool之间因为在编程中我们习惯用0表示假非0表示真所以整形和bool型的数据是可以相互转换的。4.指针和bool之间指针有可以分为空指针和非空指针相当于0和非0所以指针类型的数据也是可以和bool型之间的数据进行转换的。
显示类型转换 显示类型转换式可以看见的是用户显示使用的比如下面这段代码
int main(){int c 0;char* pc (char*)c;return 0;
}
显示的类型转换有以下几种
整形和指针类型之间这两者之间可以转换是因为指针是进程地址空间中字节的编号和整形数据之间还是具有关联性的所以可以互相转换。不同类型的指针变量之间之所以可以互相转换和上面一点是相同道理的但是指针的类型决定了指针解引用之后可以访问的内存地址字节数的大小比如说int*类型的指针解引用之后可以访问四字节的内存空间char*类型的指针解引用之后只能访问1字节的内存空间这是由指针所指向的数据的类型决定的。有了这个点其实所有类型的对象之间都能间接转换了但是解引用之后所能访问的内存空间大小不一样。
3.C中的那些类型转换
为什么C还要改进类型转换呢
我们都知道C是对C的改进和扩充C不仅仅改进了C语言中的错误处理机制还改进了C语言中的类型转换。相信你可能有这样的疑问C语言中的类型转换挺好用的那为什么还要改进呢看下面这段代码
#include iostream
using namespace std; void func(size_t pos)
{int end 10;while (end pos){cout end endl;--end;}
}int main()
{func(0);return 0;
}
大家可以猜一猜上面这段程序运行的结果是什么结果如图
出乎意料吧程序的结果是死循环这是因为end 和 pos是不同类型的数据相互比较时会发生隐式的类型转换范围小的会向范围大的数据类型转换所以end会转换为无符号数无符号数中没有负数所以比较的时候end总是大于pos导致死循环。
从上面这个案例可以看出C语言中的类型转化可视性比较差可能存在难以预料的风险所以C的前辈们觉得有必要对类型转换升级升级了。
C中的类型转换
C语言中引入了面向对象的思想提供了继承机制所以多多少少都会涉及父类和子类之间的转换这是C语言中的类型转换不能很好的解决的问题之一再者C语言中的类型转换可视性较差所以C中为了加强类型转换的可视性和可控性提供了四种类型转换操作符分别是 static_cast、reinterpret_cast、const_cast、dynamic_cast
static_caststatic_cast 操作符对应C语言中的隐式类型转换使用方式如一下代码加强了隐式类型转换的可视性。
int main()
{double a 3.14;int b static_castint(a);return 0;
} reinterpret_castreinterpret_cast 操作符对应C语言中的强制类型转换使用方式如下以前使用强制类型转换的地方就可以这样使用了。
int main()
{int a 0;int* p reinterpret_castint*(a);return 0;
} const_castconst_cast 操作符用于强制类型转换中去掉const属性。去掉变量的const属性的这种强制类型转换存在一定的内存可视化风险虽然强制类型转换也可以去掉const属性但是可视性较差不便于分析程序。 分析上面的代码可以得出a变量并没有被重新赋值但是*p指向的空间被重新赋值了但是*p指向的不就是变量a吗为什么会出现这样的现象呢这是因为编译器认为a是const修饰的是不会改变的变量所以在寄存器上存放了一份a这样一来当需要使用a变量的时候直接就可以去寄存器上面取提高程序的运行效率*p 3改变的是内存空间中a的值打印的时候a是在寄存器中取的值*p是在内存空间中取的值所以两个值不一样。 分析上面代码可以看出给 const 修饰的变量添加volatile关键字答应出的结果在意料之中这是因为volatile关键字表明不把该 const 修饰的变量 a 放在寄存器中所以不会出现上面那种情况。 dynamic_castdynamic_cast操作符用于支持向下转换也就是将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)dynamic_cast会先检查是否能转换成功能成功则转换不能则返回0dynamic_cast只能用于父类含有虚函数的类这是因为dynamic_cast的实现和虚函数表有关要想有虚函数表类中得有虚函数。 如上图左侧所示如果父类的指针指向子类对象该父类的指针是可以转化成子类的指针的因为可以看到本来就属于它的空间如上图右侧所示如果父类的指针指向父类对象该父类的指针是不能转化为子类的指针的因为会导致解引用之后该指针的步长变大访问本来就不属于它的空间。
总结一下就是子类的指针or引用or对象是可以直接转换成父类的指针or引用or对象赋值兼容转换规则但是父类的指针or引用需要通过dynamic_cast操作符类进行转换如果能转换则转换反之则返回0