过关斩将,擒“指针”(上)(1)

简介: 过关斩将,擒“指针”(上)

1.指针是什么 ?

指针是什么?


我们知道计算机内存中的基本存储单位是字节,计算机对每个字节都会进行编号,我们把对字节的编号称为地址,那么这个地址也就称为指针


地址:地址是唯一标识一块内存空间的,我们可以通过地址找到对应的内存空间


注:我们通常所说的指针是指的指针变量 ,是用来存放地址的变量。


指针:地址

指针变量:存放地址的变量

内存编号图:



q1.png

我们如何将变量的地址放入到一个指针变量中?


我们通常用 & (取地址符),将一个变量的地址放入到指针变量中


int a = 0;
  int* p = &a;

注:a 是 int 类型,所以它占4个字节,将 4个字节中的的第 1 个字节地址放入指针 p 中。指针 p 的类型是int*,但并不代表指针 p 也占4个字节,而是代表着 p 找到了变量 a 的第一个字节的地址后,应该访问多少个字节。


我们现在知道了计算机会对内存中的每一个存储单元(字节)进行编址,那我们现在思考一下计算机是如何对进行编址的?


对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0), 那么32根地址线产生的地址就会是: 就会产生2的32次方个地址,每个地址由32位二进制进行编码


q2.png


同样的方法对64位的机器,就会产生 2 的 64 次方个地址,每个地址由64位二进制进行编码


32位的机器:一个地址由32位二进制组成,8个二进制等于一个字节,那么32位的机器产生的地址也就是4个字节

64位的机器:一个地址由64位二进制组成,8个二进制等于一个字节,那么64位的机器产生的地址也就是8个字节

2.指针变量和指针变量类型

我们知道变量有不同的类型,那么指针变量有没有类型呢?


准确来说:指针变量是有类型的,但它跟变量的类型却有所不同。变量的类型一般大多数是用来开辟多大的空间的,而指针变量的类型并不是用来开辟空间的,而是表示它能访问多大空间


接下来我们一起来看看指针变量类型的作用吧!


2.1指针变量+-整数

q1.png


变量 a 是一个int类型的,打印 &a 打印的是变量 a 起始位置字节空间的地址,pi 和 pc 里面存放的都是 a 起始位置的地址 ,所以它们打印的也是 a 起始位置的地址。但是 pi 是 int* 类型的所以它可以访问 4 个字节 ,所以pi + 1跳过了四个字节的地址。pc 是char* 类型的所以它可以访问 1 个字节,所以pc + 1跳过了 1 个字节的地址


指针类型决定了指针向前或向后走一步有多大距离

2.2指针变量的解引用

w2.png


将n的地址强制类型转换为 char* 赋值给 char* pc 字符指针变量。因为每个变量的地址都是起始位置的地址,那么 pc 中也就存放了 n 变量的起始位置的地址,然后给 pc解引用 找到 pc 指向的地址对应的空间,因为 pc 是 char* 类型的它只能访问一个字节的空间大小,所以它只改变了起始位置空间里面的内容。



w1.png

n 是一个整型变量,将 n 的地址赋值给 int* pi 整型指针变量。因为每个变量的地址都是起始位置的地址,那么 pi 中也就存放了 n 变量的起始位置的地址,然后给 pi解引用 找到 pi 指向的地址对应的空间,因为 pi 是 int* 类型的它可以访问四个字节的空间大小,变量n是整型占四个字节空间大小,所以它改变了n所有的空间里面的内容


指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)

比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节


3.野指针

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


3.1野指针的成因

① 指针未初始化



q1.png

局部变量指针未初始化,默认为随机值 。如果不知道给指针初始化为什么,建议初始化为NULL。


② 指针越界访问



w3.png

数组下标是从 0 开始的,arr 数组中有 10 个元素,所以下标到 9 就结束了。但它依然可以访问改变下标为 10 的空间里面的内容,这就是越界访问,当程序运行时程序会直接崩溃并提示崩溃原因。当指针指向的范围超出数组 arr 的范围时,p 就是野指针


③ 指针指向的空间释放  



w2.png

用 malloc 开辟一块 int 类型大小的空间,让指针变量 p 指向这块空间。当释放了这块空间时应该让 p 指向 NULL ,要是 p 没有指向 NULL, p 依旧记得这块空间地址。但是这块空间已经释放了也就等于还给了操作系统,那就很可能被其他分配的动态内存所占用。但是 p 还是指向了这块空间,当使用者忘记了前面已经释放这块空间时,就很有可能误改变了已经属于其他空间的值。所以当指针指向一块动态内存开辟的空间时,当这块动态内存被释放,指针应该置为 NULL。


3.2如何避免野指针

指针初始化

小心指针越界

指针指向空间释放即使置NULL

避免返回局部变量的地址

指针使用之前检查有效性  


相关文章
|
存储 C++
过关斩将,擒“指针”(下)(1)
过关斩将,擒“指针”(下)
111 0
过关斩将,擒“指针”(下)(1)
|
编译器
过关斩将,擒“指针”(上)(2)
过关斩将,擒“指针”(上)
110 0
过关斩将,擒“指针”(上)(2)
|
6月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
2月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
28 0
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
4月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
4月前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
4月前
|
存储 编译器 C语言
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
|
5月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下