【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中也同样表示 ...
随机推荐
- Linux系统诊断必备技能之一:lsof 用法详解!
lsof(list open files)是一个查看当前系统文件的工具.在linux环境下,任何事物都以文件的形式存在,用户通过文件不仅可以访问常规数据,还可以访问网络连接和硬件:如传输控制协议 (T ...
- Ajax和Json的介绍(一)
Ajax简介: 优点: 1.Ajax是一种网页开发技术,异步JavaScript和XML;(这样叫的原因是是因为ajax传递数据是用json格式的,而json和xml又类似,都是以键值对,josn是& ...
- 剑指Offer_编程题_9
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. class Solution { public: int jumpFloorI ...
- 使用Nexus配置Maven私有仓库
使用Nexus配置Maven私有仓库 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装配置Nexus 1>.下载nexus 下载地址:https://www.sonat ...
- Python的基础详情
Python的基础信息 Python是一种动态解释性高级语言 Python即可面向对象,也可以面向过程 解释行语言 无需编译 程序以'行'为单位进行执行 执行速度慢 开发效率快 可跨平台 编译型语言 ...
- vue this.$router.push和this.$route.path的区别
this.$router 实际上就是全局路由对象任何页面都可以调用 push(), go()等方法: this.$route 表示当前正在用于跳转的路由器对象,可以调用其name.path.quer ...
- ruby新建web项目步骤,使用mysql数据库
1.创建一个项目 指定数据库 rails new demo02 -d mysql 2.修改 config/database.yml 修改数据库密码 default: &default adap ...
- js中html拼接
https://i.cnblogs.com/EditPosts.aspx?postid=10620765&update=1
- 项目thymeleaf
官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#link-urls 定义和引用片段 在我们的模板中,我们经常需 ...
- 学院派福利——C#+SQL Server图书管理系统
这是sql server的第七.八次上机内容,抽了几天时间给做了 在原有的booksDB库中加了一个Admin表:UserName:root,PassWord:123456. 环境:Visual St ...