第九讲:指针(1)

1.内存和地址

1.1内存

我们在买电脑时,有着8GB、16GB、32GB等不同内存大小的电脑,而这些内存会被分成一个个小的内存单元,每个内存单元的大小是1bit,也就是一个字节,一个比特位可以存储一个1/0,所以说每一个字节都有它对应的地址。在c语言中,我们给地址取了一个新的名字:指针。也就是说:指针就是地址,地址就是指针,就是他们在内存单元中的编号
在这里插入图片描述

1.2如何理解编址

计算机的编址,并不是把每个字节的地址记下来,而是通过硬件设计来完成的,也就是说一开始的地址的确定的。那如何将这么多的硬件连接起来呢?答案是:用线
在这里插入图片描述
地址信息被下达给内存,在内存上就能找到这个地址所记录的数据,将这些数据通过数据总线传递给CPU内寄存器。
可以简单理解为:32位机器上有着32根地址线,每一个地址线只能有两种状态:0/1,而32根地址线能够表示出2^32种不同的状态,每一种状态都表示一个地址

2.指针变量跟地址

2.1取地址操作符&

C语言中创建变量其实就是向内存中申请空间,那么怎样才能知道他们的地址呢?答案是:取地址操作符&
而取地址操作符取出的是最低位的字节的地址

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

2.2.1指针变量

我们可以将地址存储在指针变量中
在这里插入图片描述
指针变量就是用来存放地址的,存放在指针变量中的值都会被理解成指针
在这里插入图片描述

2.2.2解引用操作符*

在这里插入图片描述
解引用操作符就是通过pa中存放的地址,找到其指向的空间,其实也就是a变量,所以*pa = 20就给a改变成20了

2.3指针变量的大小

1.在32位平台下地址是32个bit位,指针变量大小是4个字节
2.在64位平台下地址是64个bit位,指针变量大小是8个字节
3.指针变量的大小与指针类型无关,只要是指针类型的变量,在相同的平台下,大小是相同的

3.指针变量类型的意义

3.1解引用操作

在这里插入图片描述
对比以上两个代码,我们可以发现,int的指针在改变时将a的4个字节的数全部改成了0,而char的指针在改变时只改变了n的一个字节,所以说:指针的类型决定了指针在解引用时能够访问的多大权限

3.2指针±整数

其实就是+1*(sizeof(指针类型))
指针的类型决定了指针向前或向后走的距离有多大

3.3void*类型指针(泛型指针)

如果我们将int类型变量的地址赋给char*,会报警告:
在这里插入图片描述
但当我们用void*来接受时,就不会报警告:
在这里插入图片描述
但是void类型的指针无法进行指针运算:
在这里插入图片描述

4.const修饰指针

在这里插入图片描述

2.1const放在指针前

在这里插入图片描述

2.2const放在指针后

在这里插入图片描述

2.3const放在指针前后

在这里插入图片描述

5.指针的基本运算

5.1指针±整数

5.2指针±指针

注意:
只有相同类型的指针才能够相减,而只有在同数组中的指针相减才有意义

两个指针相减的结果是一个整数,表示两个指针之间的元素个数

5.3指针的关系运算

1.==:判断两个指针是否指向同一处地址
2。>、<、<=、>=:判断两个指针指向的内存地址的大小,通常用于数组:

int arr[] = {1, 2, 3, 4, 5};
int *p1 = arr;
int *p2 = arr+1;

if(p1 < p2)
	//会执行,因为p1指向数组第一个元素,p2指向数组第二个元素
}

6.野指针

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

6.1野指针成因

6.1.1指针未初始化

在这里插入图片描述

6.1.2指针越界访问

在这里插入图片描述

6.1.3指针指向的空间释放

在这里插入图片描述
因为n是局部变量,离开test函数之后会被销毁,所以返回值不知道

6.2如何规避野指针

6.2.1指针初始化

如果知道指针指向哪里就给指针赋值,如果不知道指向哪里就赋给NULL:在这里插入图片描述

6.2.2小心指针越界

6.2.3指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性

在这里插入图片描述

6.2.4避免返回局部变量的地址

6.3assert断言

我们可以使用assert函数来判断指针是否位空指针

7.指针的传值调用和传址调用

7.1strlen函数的模拟实现

在这里插入图片描述chuan

7.2传值调用和传址调用

在这里插入图片描述
传入了值,但是无法将a和b进行交换
在这里插入图片描述
传入的是地址,实现了a和b的交换

7.3总结

传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改主调函数中的变量的值,就需要传址调⽤。

  • 33
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值