深入理解指针1

目录

如对您有帮助,还望三连支持,谢谢!!!

1.内存和地址

计算机中常⻅的单位(补充):

如何理解编址

2.指针变量和地址

2.1取地址操作符(&)

2.2指针变量和解引用操作符(*)

2.2-1指针变量

2.2-2如何理解指针变量

2.2-3解引用操作符

2.3指针变量的大小

3.指针变量类型的意义

3.1指针的解引用:

3.2指针+-整数:

4.const修饰指针

4.1const指针变量:

4.2const修饰指针变量:

5.指针运算

5.1指针+-整数

5.2指针-指针

5.3指针关系运算

6.野指针

指针未初始化:

指针越界访问:

指针指向已经释放了的空间:


如对您有帮助,还望三连支持,谢谢!!!

前言:指针通常被认为是c语言中比较难的知识,今天我们就来用大致5篇文章来带领大家深入理解指针,使读者对指针有更加深刻的认识。

1.内存和地址

在讲解指针之前,我们要先了解一下内存和地址,由于指针知识相对有点小抽象,所以我们尽量以举例子的形式给大家讲解,就比如我们生活中的例子:

我们上大学时为了管理学生,把学生分配到了一个个的宿舍房间中,每个房间都有固定的人数:比如6人寝,4人寝。

我们姑且认为是八人寝(有点夸张了哈哈):

一个寝室由八个人组成,而这个寝室就相当于一个内存单元;寝室里面的每个学生就相当于组成内存单元的一个比特位。

计算机内存就是由一个个内存单元(寝室)组成的,单位为字节。

了解了这个后,我么再来想一个问题:如果我要找二楼一个特定的房间,怎么找?

为了更好的管理寝室,每个寝室都有一个寝室号,也就是门牌号:

就如上图所示,有了门牌号,就能更加方便的找到我们想要的寝室了。

而门牌号就相当于地址,有了地址(门牌号),就能更快的找到特定的寝室(内存单元)。

通过这个例子,我们就对内存单元和地址的关系有了一个初步的了解。

放在计算机中来说:

我们知道计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数
据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何⾼效的管理呢?

其实也是把内存划分为⼀个个的内存单元,每个内存单元的⼤⼩取1个字节。

计算机中常⻅的单位(补充):


在生活中我们把门牌号叫做地址,在计算机中我们把内存单元的编号也成为地址,c语言给地址起了一个新的名字:指针

所以我们可以理解为:
内存单元的编号==地址==指针

如何理解编址

有读者会问,为什么地址是0XFFFFFFFF这个长度呢?长度不能是别的数了吗?这就涉及到计算机组成原理的知识了:

CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,⽽因为内存中字很多,所以需要给内存进⾏编址(就如同宿舍很多,需要给宿舍编号⼀样)。

计算机中的编址,并是把每个字节的地址记录下来,⽽是通过硬件设计完成的。

地址总线32位环境下有32根,所以地址长度为32,表示成16进制,所以才会是8个数字表示一个地址。

这里了解一下即可。

2.指针变量和地址

2.1取地址操作符(&)

理解了内存和地址的关系,我们再回到C语⾔,在C语⾔中创建变量其实就是向内存申请空间,⽐如:

⽐如,上述的代码就是创建了整型变量a,内存中申请4个字节,⽤于存放整数10,其中每个字节都有地址,我们通过调试可得到:

如上图所示,我们通过调试获取了整型变量a的地址,那么我们想要得到a的地址,又该怎么做呢?这时候就得用&操作符,代码如下:

如上图所示,我们就成功的取出了a的地址并将结果打印了出来,假设我们的打印结果006FFD70,则a在内存中的储存大致如下图所示:

我们取出了a的4个字节中最小的地址。虽然整型变量占⽤4个字节,我们只要知道了第⼀个字节地址,顺藤摸⽠访问到4个字节的数据也是可⾏的。

2.2指针变量和解引用操作符(*)

2.2-1指针变量

上面讲了如何取出a的地址,但是我们取出a的地址,要把他存放起来,以便以后使用,这时我们应该把它存放在哪里呢?

答案:指针变量

指针变量也是一个变量,用来存放地址,存在指针变量中的值会被认为是地址。

2.2-2如何理解指针变量

如上图,int*pa=&a,其中*说明pa是一个指针变量,int说明pa指向的是int类型的对象

那如果char b='w',这时候又该用什么类型的指针来接受呢?

char*pb=&b;

用char类型的指针接收char类型的数据地址。

2.2-3解引用操作符

们将地址保存起来,未来是要使⽤的,那怎么使⽤呢?
在现实⽣活中,我们使⽤地址要找到⼀个房间,在房间⾥可以拿去或者存放物品。
C语⾔中其实也是⼀样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)

指向的对象,这⾥必须学习⼀个操作符叫解引⽤操作符(*)。

    上面的代码我们创建了一个整形a和一个int类型的指针pa指向a,

然后我们通过解引用操作符(*)找到a并将a的值修改为了1。

有同学肯定在想,这⾥如果⽬的就是把a改成0的话,写成 a = 0; 不就完了,为啥⾮要使⽤指针呢?
其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径,写代码就会更加灵活,后期慢慢就能理解了。 

2.3指针变量的大小

我们上面讲了指针变量存放的是地址,所以指针变量的大小取决于地址的大小。

而在X64环境中,有64根地址线,所以地址大小为8个字节。

在X86环境中,有32根地址线,所以地址大小为4个字节。

3.指针变量类型的意义

既然我们上面讲了不管什么类型的指针变量,大小都为4/8个字节,那么不同类型的指针变量又有什么意义呢?

3.1指针的解引用:

通过调试我们可以看到,代码一对pi解引用会把n的四个字节全部修改为0;

而代码二对pc解引用只会把n的第一个字节修改为0

由此我们可以得出以下结论:

指针的类型决定了:对指针解引用时有多大的访问权限(一次能访问操作几个字节)

比如:char*的指针解引用能访问一个字节,int*解引用能访问4个字节。

3.2指针+-整数:

代码运行结果如下:

我们通过上面的代码发现:pc指针加1跳过了一个字节(地址加了一),而pi指针加一跳过了四个字节(地址加了4)。这就是不同类型指针所带来的变化。

结论:指针的类型决定了指针向前或者向后走一步的距离有多大

4.const修饰指针

4.1const指针变量:

变量是可以被修改的,可以直接修改,也可以通过指针的方式修改,那么如果我们想要一个变量加上一些限制,使其不能被修改,该怎么做呢?这时就要用到const

那么,此时问题来了,被const修饰的变量的值一定能被修改吗?

答案:可以。

我们虽然不能直接修改,但是我们可以通过指针来访问改变量,从而修改该变量的值。

4.2const修饰指针变量:

这段代码,我们运行可以初步看出:const在*左边,影响的是指针指向的内容,是指针指向的内容不能被修改;const在*右边,影响的是指针本身,指针本身的值不能被修改。

结论:const修饰指针变量的时候
• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本⾝的内容可变。
• const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指
向的内容,可以通过指针改变。

5.指针运算

指针运算大致可分为以下三种:

5.1指针+-整数

我们都知道数组在内存中是连续存放的,所以我们可以通过指针顺藤摸瓜打印出数组内容:

5.2指针-指针

strlen的模拟实现,这种方式就是指针减去指针,我们以前再讲字符串函数的时候讲过,不再赘述。

5.3指针关系运算

arr+sz指针跳过了整个数组,指向紧挨数组后面的地址;p初始时是数组首元素的地址,通过比较这两个指针,打印出来了数组的内容。

6.野指针

概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

指针未初始化:

指针越界访问:

指针指向已经释放了的空间:

所以我们在写代码时,要尽量的避开野指针。

避开野指针,我们就要养成良好的代码风格:指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性;避免返回局部变量的地址等等

至此,我们已经初步认识了解了指针。下篇文章我们将更深层次的讲解指针的知识。

  • 57
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值