深入理解指针类型间的转换

C++中指针的强制转换

强制类型转换(int)、(int&)和(int*)的区别

内存中的地址

  地址的本质就是一串0和1的机器代码,内存中的地址没有明确数据类型,但地址值有类型,以32位编译器为例,内存中的地址是一个32位的整数。无论什么类型的指针变量,在内存中本质上都是一样的,都是一个整数值的地址值,该地址值可以转换为其他类型,比如float或char,但一般不要强转,此时已不再是合法地址而是一个单纯的数据值,除了没有意义外,还会出现数据读取错误(后面会解释)。

int a;

 当我们用a时,由于前面把a定义为int型,则编译器知道从a的地址开始向后取4个字节再把它解释成int型。

指针变量及不同指针类型的含义

(1)指针变量

int *a;

  指针变量,本质上是一个变量,只是它是存放地址的变量,指针的类型代表的是它所指向的变量的类型。因此就有了指向整型、字符型、浮点型等其它类型的指针,但实际上所有类型的指针变量存放的都是int型。

  上述代码表示指向整型的指针变量a,其中a表示一个地址值,上面曾提到地址没有明确的数据类型,因为地址可以为指向整型的指针,可以为指向浮点型的指针。指针类型为整型,表示当我们对该地址进行访问(解引用)时,编译器会将它解释为整型。

  注意:指针地址只指向数据存储的内存的位置,具体变量的类型由编译器告知。

(2)不同类型的指针

  声明不同类型的指针变量既是规定了该变量结合指针运算符时读取内存中的字节数,同样规定了在指针移动和指针的运算时(加、减)在内存中移动的最小字节数。

强制转换的原理

(1)普通变量强转

  (float)a,就是先按照int类型取出该数值,再将该数值按照int to float的规则转换成float型,如果反过来,则会发生数据截断。

(2)指针变量强转

  旧指针 to 新指针的强制类型转换是指将指针所指的内容的类型由原先的类型转换为后面的类型:即进行变量解释的时候,解释的类型变化。

  如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*和TYPE,那么语法格式是:(TYPE*)p;这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,(也就是说,新指针指向的数据将会用TYPE类型进行解释,如果之前是浮点型数据-3.75,先将其转换为二进制代码,然后转化为TYPE类型存储),它指向的地址就是原指针指向的地址。

  注意:(int &)y,告诉编译器将y当做int看待

void test02(){2 3     //-----------------------------4     //float指针相关的强制转换5     //不同类型的指针变量,在内存中本质上都是一样的,都是一个整数值的地址值,一般表现为8位十六进制数6     //不同的类型表示地址指向值的解释类型,及该变量在内存中占据字节的数目7     //地址值可以强转为其他类型,但将地址指向值解释为其他类型容易出错,如float解释为int8     //常量直接赋值给指针是不可以的,必须强转为合法地址,另外由于内存地址是整型值,因此浮点型数据不能成为合法地址9     //-----------------------------
10     float a = 10.1;
11     float *p_ = &a;
12
13     cout << typeid(p_).name() << endl; //float*
14     cout << p_ << endl; //地址,8位十六进制数字(32位二进制数字)
15     cout << *p_ << endl; //地址指向的数据,同样为32位二进制数字,按照float进行解释,得到10.1
16
17     //cout << (float)p_ << endl; //不允许将地址直接转化为浮点型,但可以间接修改
18     cout << (char)p_ << endl; //直接将地址转化为字符型
19     cout << (int)p_ << endl; //直接将地址转化为十进制整型
20
21     cout << (int*)p_ << endl; //将地址float *类型转换为int*,后面的解释会发生变化,但地址的十六进制数字不会发生变化
22     cout << *(int*)p_ << endl; //地址指向的数据,会按照int型进行解释,得到1092721050
23     cout << (int&)(*p_) << endl; //同样的将数据解释为int型,得到1092721050, 则是告诉编译器将数据看成int对待
24
25     cout << *(int*)&p_ << endl; //将地址(8位十六进制数字)转换为十进制,先取p_的地址,然后按照int进行解释
26     cout << *(float*)&p_ << endl; //将地址(8位十六进制数字)转换为float,先取p_的地址,然后按照float进行解释
27     cout << *(float*)p_ << endl; //输出10.1
28
29     cout << (char*)p_ << endl; //将地址float*类型转换为char*类型,其实地址的十六进制数字不会发生变化,但<<会直接输出指向的字符串
30     cout << static_cast<const void *>(p_) << endl; //可以这样输出转换为char*后的地址
31     cout << *(char*)&p_ << endl; //将地址(8位十六进制数字)转换为char,先取p_的地址,然后按照char进行解释
32     cout << *(char*)p_ << endl; //将数值型数据按照字符类型,这里无法将float解释为char型,但是int型默认可以转换为ASCII码,解释为char型
33 }

(3)为什么内存中的地址值不能直接转换为float?

  当地址值转换为float时,编译器会有两种转换方式:(1)将整型地址值转换为浮点型;(2)将地址指向的值转换为浮点型,但不知道采用哪一种,需要我们显式地进行转换。

(4)地址值强转后访问的数据错误

  前面提到可以将地址值转为float或char,此时地址值变成了数据(有可能无法解释为char数据),而非合法地址。在对该地址进行访问时,需要将该地址值重新变为合法地址,通过(int*)强转,但浮点型数据不允许作为地址值。

(5)字符强转为合法地址

void test04(){2     char m = 'b';3     char *n = "b";4     //cout << typeid('b').name() << endl;5     float *p0;6     int *p1;7     float *p2;8     float *p3;9     p0 = (float*)(&m);
10     p1 = (int*)(m); //会先转换为m变量的ASCII值,98
11     p2 = (float*)(98);
12     p3 = (float*)(n);
13     //cout << &(int(m)) << endl;
14     cout << static_cast<const void *>(&m) << endl;
15     cout << p0 << endl;
16     cout << p1 << endl;
17     //cout << *p1 << endl;//相当于将98强转为合法地址,但并没有对该地址进行初始化,因此直接输出会显示访问冲突
18     cout << p2 << endl;
19     cout << p3 << endl;
20 }

  特别注意:char*类型不能直接由cout输出对应地址,cout会直接输出指向的字符串,可以用static_cast<const void *>(&m)来进行地址输出。

C++指针类型间强制转换相关推荐

  1. C++指针类型与强制转换

    C++ 指针类型 指针,用来描述内存地址,并通过提供指针操作来实现与内存相关的程序功能. 指针是一个特殊数据类型,也可以理解为混合数据类型.指针具有数据类型信息及数据在内存空间的地址. C++指针的类 ...

  2. Mat与IplImage*类型间的转换

    在Opencv2.X以上的处理中,大部分处理都是以Mat为主,而对于习惯了1.X的我来说,有时候会带来不便,希望能采用1.X的形式来处理. 经过试验,介绍两种简单的Mat与IplImage*类型间的转 ...

  3. Matlab中mat2gray函数的原理和使用及图像类和类型间的转换

    mat2gray 函数mat2gray可以把任意任意类型图像矩阵转换为取值范围为[0,1]的归一化double类数组. 调用格式 B = mat2gray(A) 将图像矩阵A归一化为图像矩阵B,A的值 ...

  4. 学习笔记 | c++中四种类型cast(强制)转换

    c++中四种cast转换 C++四种强制转换方式,应用场景,细节 1.const_cast 用于将const变量转为非const. 用来修饰类型的const或volatile属性.除了去掉const或 ...

  5. C#类型的强制转换及隐式转换

    1.类型间的强制转换和隐式转换: 2.checked的使用初试: 3.C#要求把类型强制转换的定义放在源类(或结构)或者目标类(或结构)的内部,它的副作用是不能定义两个类之间的类型强制转换,除非至少可 ...

  6. Java----char类型、强制转换

    1.char的大小 一个字符 = 两个字节 1 char = 2 byte = 16 bit 2.char的强制转换 public class HelloWord {public static voi ...

  7. linux 第1个参数时在不兼容的指针类型间转换,警告:从不兼容的指针类型传递参数[默认启用]...

    我一直在寻找其他线程与某些有关的,但不知何故,我只是不明白- 我想对我已经评估的一组值做一些FFT,并写这个程序来首先读取值并将它们保存到大小为n的数组. int main () { // some ...

  8. java如何强制转换_如何实现JAVA类型的强制转换

    object对象转换为String的一些总结 ----------------------------------------------------------------------------- ...

  9. ASP.NET下QueryString不同字符编码间强制转换的解决方案

    正常的情况下,现在asp.net的网站很多都直接使用UTF8来进行页面编码的,这与Javascript.缺省网站的编码是相同的,但是也有相当一部分采用GB2312.      对于GB2312的网站如 ...

最新文章

  1. css中绝对定位中的left和top属性
  2. MCU小tips(提高效率)
  3. 电脑硬件知识学习_编程入门书籍:大学学习计算机基础必读 5 本经典入门书籍,收藏...
  4. 从事java编程技能要求_5道Java视频课程,提高您的编程技能
  5. 使用MVC连接数据库及MVC应用的一般命名
  6. 计算机语言php自学,php自学需要多久?
  7. 一种结合颜色特征和区域生长的疾病斑图像分割方法(复杂环境下分割效果好)
  8. 海鲜之战:上半场活鲜炒作已曲终,下半场冷冻海鲜厚积薄发?
  9. 同步计数器 CountDownLatch
  10. Discuz!X/数据库操作方法
  11. Luogu1894[USACO4.2] 完美的牛栏The Perfect Stall
  12. 网络编程+Socket+UDP+TCP+三次握手四次挥手
  13. Gartner首发中国数据库市场指南,巨杉数据库代表数据库领域厂商入选
  14. 微服务架构设计模式 pdf_分享一份美团T9大牛总结的神仙微服务架构设计模式PDF...
  15. 树莓派GPIO引脚介绍
  16. 双活数据中心构建方法及实现技术
  17. 5款值得推荐的工具和软件,让你的工作效率翻倍
  18. 魔方机器人大赛——视觉算法
  19. 国外类似VC的emule下载网站网址大全
  20. Matlab R2017b 绘制散点图

热门文章

  1. 【自制插件】将MMD4Mecanim转换的MMD模型导入maya
  2. manjaro安装相关
  3. 知道你们为什么抢不到红米吗?来看看这个
  4. 软件开发非著名高手修炼法:ET-TCARBSSW
  5. java毕业设计项目介绍 基于SSM+Vue数字化家谱网站管理系统
  6. c++ boost库学习-01-lexical_cast
  7. 幼儿园游戏与设计课程标准
  8. 【火眼金睛】用PWC光流法来训练Deepfakes换脸检测模型
  9. VS Code配置C和Python调试环境,以及我自己的配置备份和参考
  10. 基于Laravel在线题库管理系统 魔众题库系统