【c】c语言-有关指针知识点-梳理(个人理解)

1——内存和地址
在讲内存和地址之前,我们想有个⽣活中的 案例
假设有⼀栋宿舍楼,把你放在楼⾥,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩,
如果想找到你,就得挨个房⼦去找,这样效率很低,但是我们如果根据楼层和楼层的房间的情况,给
每个房间编上号,如:
⼀楼: 101 102 103. ..
⼆楼: 201 202 203. ...
...
有了房间号,如果你的朋友得到房间号,就可以快速的找房间,找到你。
如果把上⾯的例⼦对照到计算中,⼜是怎么样呢?
我们知道计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数
据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何⾼
效的管理呢?
其实也是把内存划分为⼀个个的内存单元,每个内存单元的⼤⼩取1个字节。
计算机中常⻅的单位(补充)
⼀个⽐特位可以存储⼀个2进制的位1或者0
1.bit - ⽐特位                      比特和字节之间进率是8,一字节等于八个比特位
2.byte - 字节                        其他单位之间进率是1024,
3.KB                        
4.MB
5.GB
6.TB                        
7.PB   
                             
其中,每个内存单元,相当于⼀个学⽣宿舍,⼀
个⼈字节空间⾥⾯能放8个⽐特位,就好⽐同学们
住的⼋⼈间,每个⼈是⼀个⽐特位。
每个内存单元也都有⼀个编号(这个编号就相当
于宿舍房间的⻔牌号),有了这个内存单元的编
号,CPU就可以快速找到⼀个内存空间。
⽣活中我们把⻔牌号也叫地址,在计算机中我们
把内存单元的编号也称为地址。C语⾔中给地址起
了新的名字叫:指针。
内存单元的编号 == 地址 == 指针
2——地址是如何编写的
我们知道cpu通过地址访问内存中的内容拿到cpu中进行解析运算,但是这个地址是如何产生的呢?其实
计算机中的编址,并不是把每个字节的地址记录
下来,⽽是通过硬件设计完成的。
⾸先,必须理解,计算机内是有很
多的硬件单
元,⽽硬件单元是要互相协同⼯作的。所谓的协
同,⾄少相互之间要能够进⾏数据传递。
但是硬件与硬件之间是互相独⽴的,那么如何通
信呢?答案很简单,⽤"线"连起来。
⽽CPU和内存之间也是有⼤量的数据交互的,所
以,两者必须也⽤线连起来。
不过,我们今天关⼼⼀组线,叫做地址总线。
我们可以简单理解,32位机器有32根地址总线,
每根线只有两态,表⽰0,1【电脉冲有⽆】,那么
⼀根线,就能表⽰2种含义,2根线就能表⽰4种含
义,依次类推。32根地址线,就能表⽰2^32种含
义,每⼀种含义都代表⼀个地址。
地址信息被下达给内存,在内存上,就可以找到
该地址对应的数据,将数据在通过数据总线传⼊
CPU内寄存器。
3——&
&叫做取地址操作符 、顾名思义它可以取出变量的地址
打印出来的结果就为a的地址
4——*
*也是一个操作符,叫做解引用操作符,用处是通过地址访问在地址处的变量
*pa就等价与a,
5——拆解指针
a为整型变量,pa为指针变量,*pa为指针,int *为pa的类型
注:通常口头上说的指针为指针变量,我们所说的指针指向哪里,就是指针变量中地址所指的变量
6——指针变量大小怎末看
指针变量类型大小取决于电脑硬件,32位机器中大小为四个字节,64位机器中大小为八个字节,
字节大大小和机器的地址总线有关,32位机器地址总线为32条,32条地址总线是32个比特位就是四个字节
7——指针变量类型的意义
指针变量类型决定指针变量加减运算跳过几个字节
8——void*类型指针
void*类型可以接收任意类型的地址,通常应用于函数传参接受地址,例:void Test(void *pa)
但是这种类型不可以进行解引用,通常在不知道实参类型时,传参使用void*
9——const修饰指针
const修饰方式有三种
一种:const int *pa,int const *pa,他表示不可以对pa进行解引用,但是变量pa可以改变
二种:int * const pa 表示可以对pa进行解引用,但是pa值不可以改变
三种:const int * const pa 表示既不可以解引用也不可以改变pa值
10——指针运算
指针的基本运算有三种,分别是:
指针+- 整数        还是指针
指针-指针        为地址之间的元素个数
指针的关系运算        大小比较(指针变量也是数)
11——如何规避野指针
1>一句话 一定要初始化
如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给指针赋值NULL.
NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址会报错。
2>使用完的指针及时初始NULL,使用时检查指针是否有效
3>小心指针越界
⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是
越界访问。
12—— assert断⾔
assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报
错终⽌运⾏。这个宏常常被称为“断⾔”。
13——数组名的理解
一维数组 char arr[10]={1,2,3};
我们知道 arr[1]=2,实际上arr[1]可以写成1[arr],*(arr+1)的形式
14——⼀维数组传参的本质
本质是传的数组首元素地址,所以不可以在函数内部用sizeof计算数组长度;
15——二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪⾥?
二级指针也是指针,只不过指向一级指针,规则和一级指针一样
16——指针数组
就是存放指针的数组,表示为,int * arr[10];
17——指针数组模拟⼆维数组
就是将多个一维数组放到一个指针数组中,通过调用指针数组调用一维数组进而在调用一维数组的内容,如下图:
18——常量字符串
像上面这两种定义就叫常量字符串,首先有一个const使指针无法解引用,使字符串无法更改
C/C++会把常量字符串存储到单独的⼀个内存区域,
当⼏个指针指向同⼀个字符串的时候,他们实际会指向同⼀块内存。
注:此时str3或dtr4中储存的是字符串中h的地址
19——数组指针
数组指针字面意思是一种指针,指向数组,其实就是如此,可以这样定义int (*pa)[10],意思是*pa指向有十个元素的数组,所有元素为int类型,用整个数组的地址初始化:int (*pa)[10]=&arr
那它有什莫用呢,和二维数组传参有关
20——二维数组传参本质
⾸先我们再次理解⼀下⼆维数组,⼆维数组起始可以看做是每个元素是⼀维数组的数组,也就是⼆维
数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏,是个⼀维数组。
所以,根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第⼀⾏的地址,是
维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是 int [5] ,所以第⼀⾏的地址的类
型就是数组指针类型 int(*)[5] 。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀
⾏这个⼀维数组的地址
总结 :⼆维数组传参,形参的部分可以写成数组,也可以写成指针形式
21——函数指针变量
前面说数组指针变量是存放数组地址的,那这里函数指针变量就是存放函数地址的,函数的名字就是函数地址或者对函数名&也是函数地址,结构:int (*pa)(int,int),类似这样就为函数指针,所以函数指针变量可以间接调用函数
1>signal是一个函数调用
2>signal的参数是一个int类型和一个函数指针类型,该类型的返回值为void参数为一个int类型
3>signal的返回值是一个函数指针类型,该类型返回值为void参数为一个int类型
22——typedef关键字
三种重命名方式
23——函数指针数组
存放函数地址的数组,可以通过调用数组内不同元素来调用函数,可以通过使用函数指针数组对多种类型返回值类型相同的函数进行调用,可以方便高效实现不同功能函数调用
24——回调函数
就是通过函数指针调用函数,可以将类型相同但功能不同的函数进行统一调用,就是间接调用函数指针,再将你想调用的函数传给指针
  • 42
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值