各位小伙伴们好久不见 (●'◡'●)
文章还存在很多不足,请各位大佬,于晏,彦祖,亦菲们多多提供建议。小罗一定会提供更好的文章
在讲内存和地址之前,我想先举一个生活案例:
当你处在一栋没有标明房间号码的公寓楼前 ,假设让你去找房间1003,你会找的到吗?我想是很困难的,所以我们需要房间号码牌。拥有了号码牌,你可以简单随意的就可以找到目标房间。这样也可以极大的提高我们的效率,在计算机中也存在类似的想法。
1.内存和地址
补充一下课外知识:
内存(Memory)是计算机的重要部件,也称内存储器和主存储器,它用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行,内存性能的强弱影响计算机整体发挥的水平。只要计算机开始运行,操作系统就会把需要运算的数据从内存调到CPU中进行运算,当运算完成,CPU将结果传送出来。
内存的运行决定计算机整体运行快慢。
我们平常使用的程序,如:Windows操作系统、打字软件、游戏软件等。一般安装在硬盘等外存上,但仅此是不能使用其功能,必须把它们调入内存中运行,才能真正使用其功能。
我们平时输入一段文字或玩一个游戏,其实是在内存中进行。好比在一个书房,存放书籍的书架和书柜相当于电脑的外存,我们工作的办公桌相当于内存。
通常,我们把要永久保存、大量数据存储在外存上,把一些临时或少量的数据和程序放在内存上。当然,内存的好坏会直接影响电脑的运行速度。
内存是暂时存储程序以及数据的地方。当我们使用WPS处理文稿时,当你在键盘上敲入字符时,它被存入内存中。当你选择存盘时,内存中的数据才会被存入硬(磁)盘。
如果把上面的例子对照到计算机中,会是怎么样呢?
我们知道计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数 据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何高效的管理呢? 其实也是把内存划分为⼀个个的内存单元,每个内存单元的大小取1个字节。 计算机中常见的单位(补充): ⼀个比特位( bit )可以存储⼀个2进制的位1或者01 Byte = 8 bit1 KB = 1024 Byte1 MB = 1024 KB1 GB = 1024 MB1 TB = 1024 GB
ps: 是不是有点吃惊,1 MB 竟然不是 1000 KB,不用担心小伙伴们,我当时也是很天真的认为如此。但现在大家有印象就好,也可以拿这个简单的冷知识去 ”坑一坑“ 好朋友。(●'◡'●)
内存单元的编号其实就是地址。
其中每个内存单元可以存放八个bit,就好比在学校的寝室里,寝室有寝室号(地址),一个寝室(内存单元)可以住8个人(bit)。
这样计算机可以通过地址可以快速找到数据的位置(内存空间)。
而在C语言中 地址又被称为指针。
2. 指针变量和地址
2.1 取地址操作符(&)
比如,上述的代码就是创建了整型变量a,内存中 申请4个字节,⽤于存放整数10,其中每个字节都 有地址,上图中4个字节的地址分别是: 0x000000DB822FFA340x000000DB822FFA35
0x000000DB822FFA36
0x000000DB822FFA37 既然我们能从vs中看到地址 那我们如何才能得到a的地址呢? 这时就需要⼀个操作符(&)-取地址操作符
#include <stdio.h>int main(){int a = 10;int* p = &a;// 此步骤表明将a的地址取出 放入变量p中//详细解读// 指针变量p 的类型是 (int*) // 而(int) 表明变量指向的对象是int类型 (*)表明p 是指针变量//&是取地址操作符 p 是指针变量 指针变量p中存储的是变量a的地址//无论你赋什么值 给指针变量 它都会当作地址处理printf("%p\n", p);//编号 == 指针 == 地址}
虽然&a得到的是a的第一个地址,但a是int类型占四个字节,所有我们可以顺着思路往下推,就能得到a的所有字节的地址。
2.2 指针变量和解引用操作符(*)
#include <stdio.h>int main(){int a = 10;int* p = &a;//那么存储现在知道怎么做了,那要使用的话怎么办呢?*p;// (*)解引用操作符 作用:通过找p中储存的地址, 从而找到原地址(a)对应的值*p = 0; // 这里就是p通过(*) 解引用找到地址, 并且修改a内容 变为0// ps: 不知有没有小伙伴想到 // (&) 可以取地址 (*) 可以解地址 ,那有没有可能他们两个放在一起时就可以互相抵消呢?// 答案是可以的 以此处为例: *p 实际上就是 *&a 那么结果就是a 所对应的值 //而 众多的指针类型 你或许会认为他们所占的空间不太相同 但实际上他们所占字节是完全相同的//原因就与地址线的数量有关//在32位环境下 指针变量大小所占字节都是 4个字节//在64位环境下 指针变量大小所占字节都是 8个字节(下图会简单解释原因) //指针变量大小 于它类型无关//指针类型决定了指针进行解引用操作符的时候访问几个字节,也就是决定了指针有多大权限!return 0;}
我们可以简单理解,32位机器有32根地址总线, 每根线只有两态,表示0,1【电脉冲有无】,那么 ⼀根线,就能表⽰2种含义,2根线就能表示4种含 义,依次类推。32根地址线,就能表示2^32种含 义,每⼀种含义都代表⼀个地址。那么32位地址线 就对应32个bit位 , 32bit = 4Byte。这就是为什么在32位环境下,指针变量类型的大小都是4个字节。 3. 指针变量类型的意义 3.1 指针的解应用 和 指针+-整数 int a = 0;int* pa = &a;char* pc = &a;printf("pa=%p\n", pa);printf("pa+1=%p\n ", pa + 1);printf("pc=%p\n", pc);printf("pc+1=%p\n", pc + 1);//指针类型决定了指针 +1 , -1 向后走几个字节// int* +1 ---> 向后走4个字节// char* +1 ---> 向后走1个字节//结论:指针的类型决定了指针向前或者向后走⼀步有多大(距离)
指针类型的作用在解应用的时候,就体现出来了,char*类型解引用时只能访问一个字节,而int*类型解引用可以访问4个字节。
3.2 void*指针
在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为无具体类型的指针(或者叫泛型指 针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进行指针的+-整数和解引用的运算。
4. const修饰指针
学习之前我们先简单来看一下const的意思,这样能更好的帮助我们去理解const在c语言中的作用
4.1 const修饰变量
4.2 const修饰指针变量
情况1 const 在 * 右边
情况2 const 在 * 左边
情况3 * 两边都有const 这表明 所有都不可以被修改
到此我的c语言指针科普,先告一段落,欲知后事如何,且听下回分解。
再次感谢小伙伴们的 点赞,支持和评论。
文章还有众多不足,请大家多多指正。
在下一定当全力以赴。