【C++】一篇文章,让你不再害怕指针
在C++中,比较难以理解的就是指针,最常用的也是指针.这篇文章,结合我的所学,所看,来谈谈C++中的指针
| 指针是什么 |
指针是一个特殊的变量,指向内存中的一个地址.它具有四个要素:
指针类型:即指针本身所具有的类型.比如:int * p,表示指针的类型是int *
指针所指向的类型:int * p表示指针所指向的类型是int类型
指针的值:指针的值被编译器当作一个地址,而不是一个一般的数值.而指针所指向的内存区就是从指针的值所代表的的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区.比如说一个指针的值是XX,就是说该指针指向了以XX为首地址的一片内存区域.
指针本身所占据的内存区:这个内存区大小,只需要使用sizeof(指针的类型)来测一下就知道了
| 指针的算术运算 |
指针可以加上或者减去一个整数.指针的这种运算意义和通常数值的加减运算意义是不一样的,它以单元为单位.来,咱们举个例子:
char a[20];
int *ptr=(int *)a; //强制类型转换
ptr++;
咱们来看看在上面的程序中,它是如何进行加减的.
首先定义了数组a的类型为char类型,大小为20.
然后定义了指针ptr,类型为int *,它指向的类型是int,被初始化为指向整型变量a.
最后,ptr++表示指针ptr被加了1,但是对于编译器来说,它是把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4,因为在32位程序中,int占4个字节.由于地址是用字节做单位的,所以ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节.由于char类型的长度是一个字节,所以原来ptr是指向数组a的第0号单元开始的4个字节,此时指向了数组a中从第4号单元开始的4个字节.
指针加减乘除一个整数时,都是如此,都是以单元为单位来进行的.
但是指针不能加指针,这是非法操作,因为进行加法之后,得到的结果是一个不知所向的地方,而且毫无意义.指针可以减指针,但类型必须相同,一般用在数组操作方面.
| 运算符&和* |
在指针运算符中,最常见的就是&和*这两个了.
&是取地址符,是间接运算符
&a的运算结果是一个指针,指针的类型就是a的类型加一个,指针所指向的类型是a的类型,指针所指向的地址就是a的地址
*p的运算结果就是看p所指向的内容.比如 * p=12, * p的类型是int,所占用的地址就是p所指向的地址,即12
| 指针表达式 |
一个表达式的结果如果是一个指针,那么这个表达式就叫指针表达式,比如:
int a;
int *pa;
pa=&a; //这就是一个指针表达式
由于指针表达式的结果是一个指针,所以指针表达式也具有指针具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存
| 数组和指针的关系 |
数组的数组名其实可以看作一个指针.
字符串相当于是一个数组,在内存中以数组形式储存,只不过字符串是一个数组常量,内容不可改变,且只能是右值.如果看成指针的话,它既是常量指针,也是指针常量.
- 它代表整个数组,类型是TYPE[n]
- 它是一个常量指针,该指针类型是TYPE*,该指针指向的类型是TYPE.该指针的值是不能修改的
- 在表达式sizeof(array)中,数组名array代表数组本身,这时sizeof函数测出的是整个数组的大小
- 表达式array+n中,array扮演的是指针,所以sizeof(array+n)测出的是指针类型的大小.
| 指针和结构类型的关系 |
可以声明一个指向结构类型对象的指针.
所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙.但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或者别的什么对齐方式,也就是说需要在相邻两个成员之间加若干个"填充字节".这就导致各个成员之间会有若干个字节的空隙.
基于此,假设指针*p访问到了结构对象的第一个成员,但是不能保证 *(p+1)就一定能访问到第二个成员.因为成员之间有可能会有若干个填充字节.所以我们要使用指针指向对象时,一般使用ptr->对象名
| 指针和函数的关系 |
可以把一个指针声明为一个指向函数的指针,可以作为函数的形参,也可以作为实参.
| 指针类型转换 |
当初始化一个指针或者给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式.
来举个例子:
float f=12.3;
float *ptr=&f;
int *p;
这时,如果我们想让指针p指向实数f,应该怎么办呢?p=&f?
不对.因为指针p的类型是int *,指向的类型是int,而&f的结果是一个指针,它的类型是float *,指向的类型是float.两者类型不一致,直接赋值是肯定行不通的.
此时,我们就需要用到"强制类型转换":p=(int *)&f;
总结一下就是:
如果有一个指针,我们需要把它的类型和所指向的类型改为TYPE *TYPE
语法格式为:(TYPE *) p;
关于指针的内容,逃不过这些了.
愿你有所收获,感谢您的阅读~
【C++】一篇文章,让你不再害怕指针的更多相关文章
- 让你不再害怕指针——C指针详解(经典,非常详细)
http://blog.csdn.net/soonfly/article/details/51131141 前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理 ...
- 一文让你对js的原型与原型链不再害怕、迷惑
目录 原型与原型链的详细剖析 原型 显式原型prototype 隐式原型__proto__ 显式原型prototype与隐式原型__proto__的关系 原型链(隐式原型链) 探寻原型链的尽头 完整详 ...
- 想让安卓app不再卡顿?看这篇文章就够了
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由likunhuang发表于云+社区专栏 实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一.Android 由于机型配置和系统的 ...
- [转帖]看完这篇文章,我奶奶都懂了https的原理
看完这篇文章,我奶奶都懂了https的原理 http://www.17coding.info/article/22 非对称算法 以及 CA证书 公钥 核心是 大的质数不一分解 还有 就是 椭圆曲线算法 ...
- APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了
APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了 彻底理解android中的内部存储与外部存储 存储在内部还是外部 所有的Android设备均有两个文件存储区域:"intern ...
- 一篇文章,读懂 Netty 的高性能架构之道
原文 Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机 ...
- 【转】APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了
只要是需要进行联网获取数据的APP,那么不管是版本更新,还是图片缓存,都会在本地产生缓存文件.那么,这些缓存文件到底放在什地方合适呢?系统有没有给我们提供建议的缓存位置呢?不同的缓存位置有什么不同呢? ...
- 人脸识别必读的N篇文章
一,人脸检测/跟踪 人脸检测/跟踪的目的是在图像/视频中找到各个人脸所在的位置和大小:对于跟踪而言,还需要确定帧间不同人脸间的对应关系. 1, Robust Real-time Object Dete ...
- final----这篇文章是我收获很大
final 用于声明属性.方法和类,分别表示属性不可变,方法不可重写,类不可继承. [转]Java final 修饰符知识点总结 final从字面上理解含义为“最后的,最终的”.在Java中也同样表示 ...
随机推荐
- PHP中的表单传值
前言:试想一下如果PHP没有了表单传值,那么就相当于一个没有表达能力的人,因此表单传值在php中是相当重要的,但是不难,接下来我们一起来探讨一下吧------> (一)什么是表单传值 概念:表 ...
- Maven 本地仓库,远程仓库,中央仓库,Nexus私服,镜像 详解
一. 本地仓库 本地仓库是远程仓库的一个缓冲和子集,当你构建Maven项目的时候,首先会从本地仓库查找资源,如果没有,那么Maven会从远程仓库下载到你本地仓库.这样在你下次使用的时候就不需要从远程下 ...
- 使用eclipse粗略统计代码代数【原】
- 前台ajax传参数,后台spring mvc用对象接受
第二种方法:利用spring mvc的机制,调用对象的get方法,要求对象的属性名和传的参数名字一致(有兴趣的同学看 springmvc源码) 1.将参数名直接写成对象的属性名 $.ajax({ ur ...
- Nginx 学习笔记(六)引入线程池 性能提升9倍
原文地址:https://www.cnblogs.com/shitoufengkuang/p/4910333.html 一.前言 1.Nignx版本:1.7.11 以上 2.NGINX采用了异步.事件 ...
- Hadoop 博文整理
参考文章##搭建 使用yum安装CDH Hadoop集群 http://blog.javachen.com/2013/04/06/install-cloudera-cdh-by-yum/ Ha ...
- Socket编程 (一)
<<Linux 网络编程>>摘要 注意: 其中的大部分成员是网络字节序(大端字节序); 编程: 服务器先要做的事情: socket() 初始化Socket bind() 绑定本 ...
- 钉钉C# 使用数据接口要注意的问题
1.钉钉的数据json全部使用的首字母小写的驼峰写法,如果首字母大写,将读取接口失败. 2.钉钉的文档同一个接口可能有simple和非simple两种写法,如果发现数据不全,可以把simple去掉试试 ...
- HTTP访问控制(CORS)
当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域 HTTP 请求. 比如,站点 http://domain-a.com 的某 HTML 页面通过 <img ...
- 【bzoj 1901】Zju2112 Dynamic Rankings
Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是 ...