C语言类型转换

在C语言里用到的类型转换方式,一般都是用强制类型转换,语法:(类型说明符)(表达式),例如: (float)a 把a转换为实型,(int)(x+y) 把x+y的结果转换为整型。
C语言这种赋值时的类型转换形式可能会使人感到不精密和不严格,因为不管表达式的值怎样,系统都自动将其转为赋值运算符左部变量的类型。

C++类型转换

const_cast,字面上理解就是去const属性。
static_cast,命名上理解是静态类型转换。如int转换成char。
dynamic_cast,命名上理解是动态类型转换。如子类和父类之间的多态类型转换。
reinterpret_cast,仅仅重新解释类型,但没有进行二进制的转换。

const_cast:

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

#include <stdio.h>using namespace std;struct Data{int value;
};int main(int argc, _TCHAR* argv[])
{const Data data1 = {10};//data1.value = 15; //error C3892: “data1”: 不能给常量赋值Data &data2 = const_cast<Data &>(data1);data2.value = 20;printf("data1.value = %d data2.value = %d\n",data1.value,data2.value);const int a = 10;int *b = const_cast<int*>(&a);*b = 20;printf("a = %d b == &a is %d\n",a,b == &a);system("pause");return 0;
}

dynamic_cast
有条件转换,动态类型转换,运行时类型安全检查(转换失败返回NULL):
1. 安全的基类和子类之间转换。
2. 必须要有虚函数。
3. 相同基类不同子类之间的交叉转换。但结果是NULL。

class BaseClass {
public:
int m_iNum;
virtualvoid foo(){}; //基类必须有虚函数。保持多台特性才能使用dynamic_cast
};class DerivedClass: public BaseClass {
public:
char*m_szName[100];
void bar(){};
};BaseClass* pb =new DerivedClass();
DerivedClass *pd1 = static_cast<DerivedClass *>(pb); //子类->父类,静态类型转换,正确但不推荐
DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb); //子类->父类,动态类型转换,正确

BaseClass* pb2 =new BaseClass();
DerivedClass *pd21 = static_cast<DerivedClass *>(pb2); //父类->子类,静态类型转换,危险!访问子类m_szName成员越界
DerivedClass *pd22 = dynamic_cast<DerivedClass *>(pb2); //父类->子类,动态类型转换,安全的。结果是NULL

static_cast:

①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。(int* 转 long* error C2440: “static_cast”: 无法从“int *”转换为“long *”)
④把任何类型的表达式转换成void类型。

reinterpret_cast:

reinterpret_cast<type-id> (expression)
type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)

主要是将原地址的值重新强制定义为新类型。

reinterpret_cast与static_cast的类型转换比较:

#include <stdio.h>using namespace std;class A
{
public:int m_a;
};class B
{
public:int m_b;
};class C:public A,public B
{};int main(int argc, _TCHAR* argv[])
{C* c = new C();c->m_a = 1;c->m_b = 2;A* a1 = static_cast<A*>(c);A* a2 = reinterpret_cast<A*>(c);B* b1 = static_cast<B*>(c);B* b2 = reinterpret_cast<B*>(c);printf("c = %p,a1 = %p,b1 = %p\n",c,a1,b1);printf("c = %p,a2 = %p,b2 = %p\n",c,a2,b2);printf("a1.m_a = %d, b1.m_b = %d\n",a1->m_a,b1->m_b);printf("a2.m_a = %d, b2.m_b = %d\n",a2->m_a,b2->m_b);system("pause");return 0;
}

运行结果:

c = 00392950,a1 = 00392950,b1 = 00392954
c = 00392950,a2 = 00392950,b2 = 00392950
a1.m_a = 1, b1.m_b = 2
a2.m_a = 1, b2.m_b = 1

由运行结果可以很明显地看到,使用reinterpret_cast进行强制转换的时候b2直接是从c的地址开始,将c转换成了b2,而使用static_cast的时候,b1是进行了一个sizeof(A)的一个偏移量的位移,也就是说在多重继承的情况下,将子类的对象指针转换成基类对象指针,使用static_cast才是安全的。reinterpret_cast的目的是将类型重定义,除非你非常明确地希望指向的那一块内存是希望定义到你要转换的目标,否则慎用。

reinterpret_cast的一个使用例子:

#include <stdio.h>using namespace std;typedef void(*FuncPtr)();
typedef int(*FuncPtr2)();void fun1()
{
}int fun2()
{return 10;
}int main(int argc, _TCHAR* argv[])
{FuncPtr fun[10];fun[0] = &fun1;//fun[1] = &fun2; //error C2440: “=”: 无法从“int (__cdecl *)(void)”转换为“FuncPtr”//fun[1] = static_cast<FuncPtr>(&fun2); //error C2440: “static_cast”: 无法从“int (__cdecl *)(int)”转换为“FuncPtr”
fun[1] = reinterpret_cast<FuncPtr>(&fun2); //用强制转换将int fun 转为 void fun 保存起来
FuncPtr2* pfun = reinterpret_cast<FuncPtr2*>(&fun[1]); //在需要使用的时候,再转换回来
printf("run pfun = %d\n",(*pfun)()); //打印得到 "run pfun =10"
system("pause");return 0;
}

转载于:https://www.cnblogs.com/aizquan/p/3937850.html

温故而知新 C++ 类型转换相关推荐

  1. Java 数据类型转换

    学而时习之,温故而知新. 数据类型转换,先放一张图,了解数据类型 简单数据类型之间的转换又可以分为: 1 低级到高级的自动类型转换 2 级到低级的强制类型转换 3 包装类过渡类型转换. (有时候我们有 ...

  2. JavaScript 温故而知新(一)语法

    文章目录 javaScript的组成 在HTML中使用JavaScript JavaScript的注释与分号 JAVAScript的语法 JAVAScript的标识符 JAVAScript的变量 Ja ...

  3. 2021-12-3 温故而知新-JavaScript隐式转换

    背景:因为一个ts的报错让使用了很久的anyscript 有了危机.故好好温习一下之前的基础.温故而知新,就是这个道理.问渠哪得清如许,唯有源头活水来- 一 数学运算符中的类型转换 1. 减.乘.除 ...

  4. java基本类型转换,随记

    java基本类型转换: double double 转 long double random = Math.round(Math.random()*10000); long l = new Doubl ...

  5. Go 知识点(12) — 类型转换以三方库 cast

    类型转换在编程语言中是很常见的操作,在 Go 语言中其类型转换有下面一些注意点. 1. 整数类型之间的转换 对于整数类型转换,原则上目标类型的取值范围要包含被转换值,也就是说要转换类型的值取值范围要小 ...

  6. 数据类型转换pytorch

    du = torch.ones([2,2]) a = np.array([[1,2],[3,4]],dtype=np.float32) b = torch.from_numpy(a)#数据类型是不变的 ...

  7. tf.cast()数据类型转换

    tf.cast()函数的作用是执行 tensorflow 中张量数据类型转换,比如读入的图片如果是int8类型的,一般在要在训练前把图像的数据格式转换为float32. cast定义: cast(x, ...

  8. Java中如何实现Date与String之间的数据类型转换

    String 数据类型转换成 Date String inputDate = "2021-04-11";Date outputDate = null;SimpleDateForma ...

  9. Java基本数据之间的类型转换

    Java 数据类型及类型转换 基本数据类型:共八种: 复合类型:字符串(String),数组(array),类(Class),接口(Interface)等等: 其中个人常用的有:int,boolean ...

最新文章

  1. pytorch实现attention_Longformer: 局部Attention和全局attention的混搭
  2. 区域经济、地理信息、互联网三者交叉之行业背景分析
  3. Matlab:序列分析法MATLAB代码
  4. ATM and Students 双指针,前缀和(1800)
  5. mysql5.6时间问题_mysql5.6版本java插入时间的错误
  6. 异常解析————Parameter metadata not available for the given statement
  7. 看脸 高效学英语 下
  8. web前端学习笔记(二)---Django
  9. shell 字符串
  10. [洛谷P2073] 送花
  11. sql 求相交的行_SQL相交
  12. Hadoop生态基础学习总结
  13. 每天2小时,吃透 985博士总结的这份目标检测、卷积神经网络和OpenCV学习资料笔记(20G高清/PPT/代码)...
  14. python画图入门——for循环及调色盘的应用
  15. 表格的下拉放大 ----------王朋
  16. mac版 IGV(版本2.12.3)安装
  17. Android剥洋葱式解析JSON数据
  18. #R语言# 生成随机数
  19. 主机win7和虚拟机xp之间的文件传输
  20. android测试方法及流程,一种Android通讯终端硬件测试方法、测试工艺以及整机测试流程与流程...

热门文章

  1. The Coding Kata: FizzBuzzWhizz in Modern C++11
  2. zabbix使用Omsa来监控Dell服务器的硬件信息
  3. wpf绑定之格式化日期
  4. 企业级管理软件快速开发平台-完整的权限管理设计
  5. 在上级对自己做绩效评估之前
  6. setState同步异步场景
  7. matlab ann-bp分类器,利用matlab真的BP-ANN分类器设计.doc
  8. linux成为管理员_成为系统管理员需要知道的
  9. 业务模型管理平台 开源_在可靠的开源模型上建立业务
  10. ASP.NET HyperLink控件NavigateUrl中用到DataBinder.Eval时