在C++中,比较难以理解的就是指针,最常用的也是指针.这篇文章,结合我的所学,所看,来谈谈C++中的指针

指针是什么

指针是一个特殊的变量,指向内存中的一个地址.它具有四个要素:

指针类型:即指针本身所具有的类型.比如:int * p,表示指针的类型是int *

指针所指向的类型:int * p表示指针所指向的类型是int类型

指针的值:指针的值被编译器当作一个地址,而不是一个一般的数值.而指针所指向的内存区就是从指针的值所代表的的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区.比如说一个指针的值是XX,就是说该指针指向了以XX为首地址的一片内存区域.

指针本身所占据的内存区:这个内存区大小,只需要使用sizeof(指针的类型)来测一下就知道了

指针的算术运算

指针可以加上或者减去一个整数.指针的这种运算意义和通常数值的加减运算意义是不一样的,它以单元为单位.来,咱们举个例子:

  1. char a[20];
  2. int *ptr=(int *)a; //强制类型转换
  3. 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

指针表达式

一个表达式的结果如果是一个指针,那么这个表达式就叫指针表达式,比如:

  1. int a;
  2. int *pa;
  3. pa=&a; //这就是一个指针表达式

由于指针表达式的结果是一个指针,所以指针表达式也具有指针具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存

数组和指针的关系

数组的数组名其实可以看作一个指针.

字符串相当于是一个数组,在内存中以数组形式储存,只不过字符串是一个数组常量,内容不可改变,且只能是右值.如果看成指针的话,它既是常量指针,也是指针常量.

  • 假设,我们声明了一个数组TYPE array[n],那么这个数组名称array就有了两重含义:
    • 它代表整个数组,类型是TYPE[n]
    • 它是一个常量指针,该指针类型是TYPE*,该指针指向的类型是TYPE.该指针的值是不能修改的
  • 在不同的表达式中,数组名array可以扮演不同的角色
    • 在表达式sizeof(array)中,数组名array代表数组本身,这时sizeof函数测出的是整个数组的大小
    • 表达式array+n中,array扮演的是指针,所以sizeof(array+n)测出的是指针类型的大小.
  • 指针和结构类型的关系

    可以声明一个指向结构类型对象的指针.

    所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙.但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或者别的什么对齐方式,也就是说需要在相邻两个成员之间加若干个"填充字节".这就导致各个成员之间会有若干个字节的空隙.

    基于此,假设指针*p访问到了结构对象的第一个成员,但是不能保证 *(p+1)就一定能访问到第二个成员.因为成员之间有可能会有若干个填充字节.所以我们要使用指针指向对象时,一般使用ptr->对象名

    指针和函数的关系

    可以把一个指针声明为一个指向函数的指针,可以作为函数的形参,也可以作为实参.

    指针类型转换

    当初始化一个指针或者给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式.

    来举个例子:

    1. float f=12.3;
    2. float *ptr=&f;
    3. int *p;

    这时,如果我们想让指针p指向实数f,应该怎么办呢?p=&f?

    不对.因为指针p的类型是int *,指向的类型是int,而&f的结果是一个指针,它的类型是float *,指向的类型是float.两者类型不一致,直接赋值是肯定行不通的.

    此时,我们就需要用到"强制类型转换":p=(int *)&f;

    1. 总结一下就是:
    2. 如果有一个指针,我们需要把它的类型和所指向的类型改为TYPE *TYPE
    3. 语法格式为:(TYPE *) p;

    关于指针的内容,逃不过这些了.

    愿你有所收获,感谢您的阅读~

    【C++】一篇文章,让你不再害怕指针的更多相关文章

    1. 让你不再害怕指针——C指针详解(经典,非常详细)

      http://blog.csdn.net/soonfly/article/details/51131141 前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理 ...

    2. 一文让你对js的原型与原型链不再害怕、迷惑

      目录 原型与原型链的详细剖析 原型 显式原型prototype 隐式原型__proto__ 显式原型prototype与隐式原型__proto__的关系 原型链(隐式原型链) 探寻原型链的尽头 完整详 ...

    3. 想让安卓app不再卡顿?看这篇文章就够了

      欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由likunhuang发表于云+社区专栏 实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一.Android 由于机型配置和系统的 ...

    4. [转帖]看完这篇文章,我奶奶都懂了https的原理

      看完这篇文章,我奶奶都懂了https的原理 http://www.17coding.info/article/22 非对称算法 以及 CA证书 公钥 核心是 大的质数不一分解 还有 就是 椭圆曲线算法 ...

    5. APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了

      APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了 彻底理解android中的内部存储与外部存储 存储在内部还是外部 所有的Android设备均有两个文件存储区域:"intern ...

    6. 一篇文章,读懂 Netty 的高性能架构之道

      原文 Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机 ...

    7. 【转】APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了

      只要是需要进行联网获取数据的APP,那么不管是版本更新,还是图片缓存,都会在本地产生缓存文件.那么,这些缓存文件到底放在什地方合适呢?系统有没有给我们提供建议的缓存位置呢?不同的缓存位置有什么不同呢? ...

    8. 人脸识别必读的N篇文章

      一,人脸检测/跟踪 人脸检测/跟踪的目的是在图像/视频中找到各个人脸所在的位置和大小:对于跟踪而言,还需要确定帧间不同人脸间的对应关系. 1, Robust Real-time Object Dete ...

    9. final----这篇文章是我收获很大

      final 用于声明属性.方法和类,分别表示属性不可变,方法不可重写,类不可继承. [转]Java final 修饰符知识点总结 final从字面上理解含义为“最后的,最终的”.在Java中也同样表示 ...

    随机推荐

    1. Go-day05

      今日概要: 1. 结构体和方法 2. 接口 一.go中的struct 1. 用来自定义复杂数据结构 2. struct里面可以包含多个字段(属性) 3. struct类型可以定义方法,注意和函数的区分 ...

    2. Maven Tomcat7+ 实现自动化部署

      首先在Tomcat里配置deploy的用户(tomcat根目录/conf/tomcat-users.xml): <role rolename="tomcat"/> &l ...

    3. go context

      Context 使用原则 1.不要把Context放在结构体中,要以参数的方式传递 2.以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位. 3.给一个函数方法传递Co ...

    4. python机器学习-sklearn挖掘乳腺癌细胞(四)

      python机器学习-sklearn挖掘乳腺癌细胞( 博主亲自录制) 网易云观看地址 https://study.163.com/course/introduction.htm?courseId=10 ...

    5. 使用JMeter进行一次简单的带json数据的post请求测试,json可配置参数

      配置: 1.新建一个线程组: 然后设置线程数.运行时间.重复次数. 2.新建Http请求: 设置服务器域名,路径,方法,编码格式,数据内容. 可以在函数助手中,编辑所需要的变量,比如本例中的随机生成电 ...

    6. 【1】【leetcode-79】 单词搜索

      (典型dfs,知道思想写错) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...

    7. HTML第二耍 列表标签

      先复习下上一节 <!doctype html> <html> <head> <meta charset="utf-8"> <t ...

    8. java枚举(enum)

      1. 创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum (抽象类) 类的子类. enum AccountType { SAVING, FIXED, CURRE ...

    9. 【LeetCode】108. Convert Sorted Array to Binary Search Tree

      Problem: Given an array where elements are sorted in ascending order, convert it to a height balance ...

    10. Kali Linux之常见后门工具介绍

      1.Meterpreter 它是Metasploit框架中功能强大的后渗透模块.可以通过Meterpreter的客户端执行攻击脚本,远程调用目标主机上运行的Meterpreter服务端. 命令 作用 ...