• 【C/C++】类型转换



    在这里插入图片描述

    1.C语言中的类型转换

    在C语言中,如果赋值运算符左右两侧类型不同,或者形参和实参类型不匹配,或者返回值类型和接收返回值类型不一致,就会发生类型转换。

    C语言中的类型转换分为两种:隐式类型转换和强制类型转换

    1.1隐士类型转换【相近类型,意义相近】
    void test()
    {
        int i=1;
        double d=i;
        printf("%f,%f",d,i);
    }
    输出:
        1.00000  0.00000
    解释:
        i按照%f的方式输出时,发生了整形提升。
        浮点数在内存的存储规则为:
        	(-1)^S*M*2^E
        S:一个比特位,表示数的正负
        M:23个比特位,有效数字,科学计数法表示
        E:8个比特位,表示指数位
    

    在这里插入图片描述

    需要注意的是:E在存储到内存的时候,需要加上一个中间数127

    1.2.强制类型转换

    强制类型转换针对的是意义相差很远的类型,比如int类型和指针类型

    void test()
    {
        int i=0;
        int* p=&i;
        int address(int)p;
        printf("%p,%d\n",p,address);
    }
    输出:
        0133FA4C,20183628
    

    2.C++的类型转换

    2.1相近类型转换–static_cast

    static_cast用于相近类型,意义相似的类型。static_cast用于非多态类型的转换(静态转换)。

    void test()
    {
        double d=11.11;
        int a=static_cast<int>(d);
        cout<<a<<endl;
    }
    输出:11
    
    2.2强制类型转换—reinterpret_cast
    void test()
    {
        double d=12.34;
        int a=static_cast<int>(d);
        cout<<a<<endl;
        int*p=reinterpret_cast<int*>(a);
        cout<<p<<endl;
    }
    输出:
        12
    	0000000C
    
    2.3去掉对象const属性—const_cast

    const_cast最常用的用途就是删除变量的const属性,方便赋值

    const int ca=2;
    int*pi=const_cast<int*>(&ca);
    *pi=3;
    cout<<ca<<endl;
    cout<<*pi<<endl;
    输出:
        2 3
    为什么ca输出的是2?
        对于ca,编译器做出了优化,考虑到const类型被修改的可能性很小,所以编译器将ca存放在寄存器中。
      
        
    如果修改为
    volatile const int ca=2;
    int*pi=const_cast<int*>(&ca);
    *pi=3;
    cout<<ca<<endl;
    cout<<*pi<<endl;
    输出:
        3 3
     volatile表示强制从内存中取出变量值
    
    2.4dynamic_cast

    dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

    • 向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)【多态和切片原理
    • 向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)

    注意:

    1. dynamic_cast只能用于父类含有虚函数的类

    2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

    dynamic_cast底层实现使用了虚表的结构

    class A
    {
    public:
    	void f()
    	{}
    };
    class B :public A
    {
    	void f()
    	{}
    };
    void test(A* pa)
    {
    	B* ptr1 = static_cast<B*>(pa);
    	B* ptr2 = dynamic_cast<B*>(pa);
    }
    int main()
    {
    	A a;
    	B b;
    	test(&a);
    	test(&b);
    	return 0;
    }
    

    在这里插入图片描述

    class A
    {
    public:
    	virtual void f()
    	{}
    };
    class B :public A
    {
    	void f()
    	{}
    };
    void test(A* pa)
    {
    	B* ptr1 = static_cast<B*>(pa);
    	B* ptr2 = dynamic_cast<B*>(pa);
    }
    int main()
    {
    	A a;
    	B b;
    	test(&a);
    	test(&b);
    	return 0;
    }
    
  • 相关阅读:
    可升级合约的原理-DelegateCall
    实现动态表单的一种思路
    Redis缓存穿透,背八股文 居然没用!!!
    2023年B题人工智能对大学生学习影响的评价
    Linux安装
    给定一个数组arr,长度为N且每个值都是正数,代表N个人的体重。再给定一个正数 limit,代表一艘船的载重。
    ES6基础
    Windows10实用的12个快捷组合键
    【HarmonyOS】低代码平台组件拖拽使用技巧之页签容器
    map的详细用法
  • 原文地址:https://blog.csdn.net/qq_53893431/article/details/127104542