第14章:指针

编程入门 行业动态 更新时间:2024-10-11 19:14:53

第14章:<a href=https://www.elefans.com/category/jswz/34/1768268.html style=指针"/>

第14章:指针

      指针是 C 语言里边非常重头戏的一块,也是相对来说比较难的一块,但是,听我讲,讲完之后你会觉得:哎呀,指针也就那么回事,很多同学都和我说,听了你的指针之后发现,终于明白了指针是什么东西,要谈指针,就必须要会讲明白内存!

内存是电脑上特别重要的存储器,计算机中所有程序的运行都是在内存中进行的!

所有为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节

为了能够有效的访问内存的每个单元,就给内存单元进行了编号,这些编号被成为该内存单元的地址

14.1 如何正确使用内存

      重点一:为了有效的使用内存,我们该如何去管理内存呢?我们买回来的计算机有4个 G 内存或者8个 G 内存,这么大的内存空间,我们该如何去使用它呢?

      我们都知道,内存属于空间,其实内存的使用和我们现实生活中对于空间的使用是有非常相似的地方!比如在我们现实生活中,我们国土面积960万平方公里,但是真正去访问这些空间的时候,我们会发现:我们给每一个空间都编了有效的地址。比,我们想找到一个地方:重庆市潼南区古溪镇狮桥村狮桥村委员会,北京市海淀区西北旺镇屯佃村鑫鑫超市,河北省保定市蠡县鲍墟乡东五夫村东五夫委员会等等,因为当我们描述这样的地址的时候,就可以精确的找到一个房间,就能够找到这个房间里边相关的事物,就找到了我们现实生活中的一个空间,而我们现实生活中是怎么找到这块空间的?是通过地址。而地址,又跟我们一个一个的房间是关联的,我们给每一个房间都编了号,如601,602,603,604等等,然后通过地址就可以找到房间

      其实对于内存也是一样的,内存是一块大的空间,这块内存我该如何去使用呢?我们把内存划分成了这样一个一个的有效的格子,当我把内存划分成这样一个一个小的格子的时候,这个时候其实跟生活中是一样的,我们给每个这样的格子再编个号,比如最上面开头是0,然后依次是12等等,给每一个这样的格子都编上一个小的号,这个时候跟我们现实生活中是一样的,我们现实生活中,给每个房间都编了个号;而我们内存里边,也要划分成这样一个一个的小的格子,给每个格子都编个号,这就是内存的管理方式,它是借鉴我们生活中实际的一些情况,然后来进行内存空间的管理 ,如图所示:

然而,这个地方就又分成了2个问题:

14.2:内存是怎么编号的(重点)

      其实,我们在讨论计算机的时候,我们的机器是32位机器(或者是64位机器),那这个32/64位是什么意思呢?32位机器是有32根地址线,而地址线是物理的线,物理的线可以通电,通电的时候它的正电就是1,同理,负电就是0,而如果32根地址线上如果真的全部通上电,那有的电是正的,有的电是负的,正负电之分,就产生1/0这样的信号。所以我们把电信号转化成数字信号,这个时候就变成了0/1组成的二进制序列,对于我们的32位机器有32根地址线,那这个线上产生的二进制序列的弱信号它的可能性就是32个全0,然后一直涨,二进制序列如果涨1的话,最后会变成32个全1,也就是说,它的可能性就是32个全0到32个全1,如图所示:

      由于一个串是32个位,那我们就可以把这样的二进制序列就可以作为一个内存编号,所以总共产生了2的32次方个二进制序列,这些序列都可以作为内存的编号,当这个二进制序列成为一个内存的编号的时候,我们就把这个编号称为这个内存单元的地址

总结一句核心:内存是怎么编号的呢?是因为我们有地址线,地址线通电产生的电信号,电信号转化成数字信号,对应的二进制序列就是地址,编号就被称为地址

14.3:一个这样的内存单元是多大空间(重点)

      我们已经知道了,我们总共有2的32次方这样的地址,那一个内存单元给多大空间呢?我们看一下:

      据我们所知,计算机里边最小单位是比特位,再往上是 byte,再往上是 kb,再往上是 MB,再往上是 GB,再往上是 TB,再往上是 PB,然后呢,以此类推,我们可以算一下,2的32次方这么多个地址,每一个地址对应一个内存单元,我们可以管理2的32次方个内存单元,那1个内存单元是多大呢?当我们知道一个内存单元多大,我们就能够知道总共能管理多大内存了。

      我们假设一个 bit 给一个编号,一个内存单元就是一个 bit,那我们就能管理2的32次方个 bit 的空间,2的32次方个 bit 的空间有多大呢?我们来看一下:

      可见最终我们只能管理0.5GB 这么大的空间,那我们管理的空间也太少了吧,太小了。实际上,在早期32位机器的时候,那个时候2个 G 的内存都已经很常见了,所以一个比特位是一个内存单元的时候不合适,管理的空间太小了

      还有其他的理由:如果一个 bit 给一个地址,C 语言最小单位是 char 类型,char 类型1个 char 是一个 byte,也就是8个 bit,一个 bit 给一个地址的话,char 就得8个地址,感觉有点太浪费了,感觉太浪费了!!管理的力度太细了,就比如:我给你寄个快递,寄到重庆城市科技学院主教105教室的第5个平米上,密度管理的太细,所以管理 bit 也太细了,我们最小单位都是 char,一个 char 给8个 bit,8个 bit给8个地址太浪费,没必要这么细

      所以再往下的话,不是一个 bit 的话给什么呢?再往下就是 byte,一个内存单元一个字节怎么样呢?这个其实是比较合适的,因为一个 char 是一个字节,一个字节给个地址,所以一个 char 给个地址就很合适;所以,最终经过平衡之后,一个内存单元最终取的是1个byte,一个 byte 为一个内存单元,然后分配地址;也就是说,一个字节给一个编号

     

14.4 如何创建指针变量(重点)

      如果能够听懂以上这些东西是非常重要的,这些基础的铺垫,我们才能知道内存单元是有地址的,那我们是不是就可以拿出内存单元的地址呢?拿出内存单元的编号呢?这个时候才有了地址的概念,才有了指针的概念,话不多说,直接上代码((int a = 10的代码):

      还是定义一个局部变量 int a = 10,10要存起来得有空间吧,所以 a 在内存中要分配空间,既然分配空间,分配多大空间呢?分配空间是4个 byte,那问题来了:a 分配的4个字节是哪4个字节?假设1个内存单元是一个字节,这就是为 a 分配的一块空间,这4个字节,每个字节都有自己的编号,我想拿出 a 的的地址,且当我们一个变量所占空间是4个字节的时候,&a 拿到的是这4个字节的第一个字节的地址(也就是首地址),只要我拿到这份连续空间的起始位置的地址,后面的照样能够找到,不会说&a 把4个地址都拿常量,只会拿出它的第一个字节的地址,虽然它每个字节都分配了地址,但是&a 只会拿出它第一个字节的地址,从前往后第一个字节的地址,如图所示:(0055FC2C)

      我们确实能够拿到,a 占了4个字节的地址,拿到的时候是4个自己的起始地址,但是这个&a 拿出来之后它也是个值,虽然是个地址,是个编号,但它也是个值,这个值要存起来,我们得需要一块空间,我们的这块空间假设名字叫 pa,pa 是用来存放地址的,所以在 C 语言中 pa 叫指针变量

      学到这里还是没明白,不要紧,在解释一下:我们 a 的地址拿出来之后是个值,只要存起来就得放到变量里边去,所以放到 pa 里边去,所以这个时候的 pa 就叫指针变量,那问题来了,我们创建个整型变量,可以写 int a,是创建个整型的类型 a,也就是整型类型的变量 a。那 pa 呢?pa 也得有自己的类型,pa 是个指针类型,它的类型怎么写呢?叫 int* pa,这是它的一个写法。如图所示:

      对于这个 int * 是怎么理解的呢?一颗星,说明 pa 是指针变量,而前面的 int,说明 pa 指向的对象是 int 类型的。pa 现在指向的是 a,a 的类型是 int,所以 *pa,这就是指针变量的一种定义方式

总结:指针变量是用来存放地址的,存放谁呢?存放别人的地址。指针类型怎么定义呢?一颗星说明 pa 是指针,前面的 int 说明 pa 指向的是 a 这样的整型变量

由此,我们能不能举一反三呢?比如 char ch = 'w',然后取&ch,这个时候我们要放到一个变量里边去,写个 pc,pc 的类型该怎么写?答案是:char* pc = &ch,如图所示:

为什么呢?因为这颗星是给 pc 的,说明 pc 是指针,而前面的 char 说明了 pc 指向那个变量的类型是 char 类型

指针变量可以存放自身地址吗?

说明放是可以放进去的,但是类型有所差异,如图所示:

      当我们能够拿到 a 的地址的时候,难道仅仅是为了拿到 a 的地址吗?举一个例子:&a 拿出 a 的地址,存到 pa 里边去,pa 的类型叫 int*,难道这个 pa 里边存 a 的地址仅仅是为了存起来吗?不是,我们有朝一日可能想通过 pa 里边存的值找到 a,pa 里边存了 a 的地址,肯定是通过这个地址最后想找到 a,比如说:我给你发信息,同学你把你的地址给我吧,我把你的地址抄到我的笔记本上记下来了,难道我就是为了抄到笔记本上吗?不是,我可能是有一天我需要通过这个地址找到你,我给你寄个快递,或者说我直接通过这个地址找到你的学校,跟你聊聊天。所以 pa 里边存的地址未来是有用的,想通过这里边存的地址找到 a,所以怎么找呢?pa 前面加一颗星,这个时候改成20,因为 pa 里边存的是 a 的地址,所以 *pa 就是通过 pa 里边的地址找到 a,这颗星叫解引用操作符。*pa 就是通过 pa 的里边的地址找到 a,所以 *pa = 20就把 a 改掉了,a 就变成20了,因此,我们改 a 可以不通过 a 改变,只要 a 的地址交给 pa,pa 解引用就可以找到 a,这是一种间接的改变(借助于 pa 去改变 a),这里边就讲了另外一个操作符叫*,这个*叫解引用操作符,也是单目操作符,如图所示:

      再来一个例子,当我们写个 int num = 10的时候,其实相当于我们在内存里边开辟了4个 byte,这里边存了一个10,这个 num 占4个 byte,每个 byte 都有地址:44、45、46、47。当我们取出 num 地址的时候,其实取出来的是4个 byte 里边第一个 byte 的地址,即取出的是44(较小的地址),44要存到 p 里边去,p 是个指针变量,有一块空间,我们把44存到这个空间里边去,这个时候 p 就相当于指向了 num。再讲一遍!!!相当于 p 里边存的地址指向了 num,所以当 *p 的时候,其实找到的就是 num,可以改成20,如图所示:


补充:

1.  指针变量是用来干什么的?是用来存放地址的;存放谁的地址呢?存放别人的地址。

2. 值是用来干什么的?第一:存,第二:当我们有一天的时候可能通过*pa 来找到它所指向的对象

3. 当我们取出变量的地址的时候,可以取出来,但是要存起来,我们得有个变量,这个变量就被称为指针变量

4. & 和 * 都是单目操作符

5. %p 是专门用来打印地址

6. 指针就是地址(pa 叫指针变量,它里边存的是地址,所以我们使用 pa 这个指针变量的时候,就是使用它里边的地址)

14.5:指针变量的大小

我们已经知道了:指针是有类型的,类型有各种各样的,所以我们算指针变量大小的时候,算它的类型也一样,

更多推荐

第14章:指针

本文发布于:2024-03-23 02:12:06,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1739229.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指针

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!