在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 array[n],那么这个数组名称array就有了两重含义:
    • 它代表整个数组,类型是TYPE[n]
    • 它是一个常量指针,该指针类型是TYPE*,该指针指向的类型是TYPE.该指针的值是不能修改的
  • 在不同的表达式中,数组名array可以扮演不同的角色
    • 在表达式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++】一篇文章,让你不再害怕指针的更多相关文章

    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. Vue.js 循环语句

      循环使用 v-for 指令. v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名. v-for 指令: v-for 可以 ...

    2. django_admin用法

      Django内置的admin Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.con ...

    3. rancher使用fluentd-pilot收集日志分享

      fluentd-pilot简介 fluentd-pilot是阿里开源的docker日志收集工具,Github项目地址:https://github.com/AliyunContainerService ...

    4. npm 更新版本

      需要升级npm版本大于某个版本.百度搜索如何更新npm至最新版本.90%的解决方案是让我们再用npm全局安装一遍npm,就可以更新至最新版本了.即: npm install -g npm 但是,我尝试 ...

    5. Linux记录-配置sudoers无密登录和环境变量

      su root vim /etc/sudoers.d/sfapp sfapp ALL=(ALL) ALLsfapp ALL=(ALL) NOPASSWD: ALL Defaults !env_rese ...

    6. 搭建vscode+vue环境

      转自:https://blog.csdn.net/mao834099514/article/details/79138484 一.安装vue.js 1.简介 Vue.js(读音 /vjuː/, 类似于 ...

    7. jquery load 陷阱【原】

      基础写法 function load(targetId,templateName) { $("#"+targetId).load(contextPath+templateName) ...

    8. Shell编程(六)awk工具

      1. {print} coins.txt gold USA American Eagle gold Austria Franz Josef Korona silver USA ingot gold S ...

    9. 改变this指向的三种方法

      call.apply.bind三者为改变this指向的方法. 共同点:第一个参数都为改变this的指针.若第一参数为null/undefined,this默认指向window call(无数个参数) ...

    10. SDL 库 无法解析的外部符号 __imp__fprintf

      VS2015 在链接器->命令行 里加入legacy_stdio_definitions.lib 另外一个常见错误关于stderr的用 extern "C" { FILE _ ...