指针中关于“指针被错误使用场景”的系统总结:

C语言提供了指针,给予了C/C++用户在写程序时访问计算机时最大权力,这是相比其他的Java,Python主流编程语言它最大的优势所在。让它在嵌入式开发,操作系统领域有着广大的应用市场。但是权力也不能滥用,如果你错误地去使用指针,会有很严重地后果。

那对于初学者而言,有那些使用指针时的常见错误呢。我想不外乎于两种:

  1. 对空指针的非法访问;
  2. 对野指针的非法访问;

我们现在来一一了解一下,具体是怎么一回事。

一、对空指针的非法访问:

空指针?好吧,空指针其实就是我们C语言里面经常用到的NULL,它实际上是一个宏。如果把它定义展开应该是下面这样的:

#define NULL ((void *)0)

你会发现实际上NULL就是对数字0做一个强制类型转换操作,将其转换为void*指针。实际上就是取出地址编号为0的地址给到了我们的NULL。

ANSIC(C语言标准)规定说数字0作为地址时,普通的用户程序是没有资格进行访问的。那如果你不小心访问了NULL指针,对它进行解引用操作,那程序会崩溃的!

那怎么规避这里的问题呢,其实这种问题的规避比较简单,也很容易被发现。我们比较推介的是:当一个指针在使用之前需检查该指针的有效性——检查这个指针是否是空指针NULL,如果不是NULL指针,我们再对它进行访问。

二、对野指针的非法访问:

野指针就是指向位置不可知的一个指针,虽然这个指针里面也保存着一个地址编号,但是这个地址编号不属于我们的用户,用户没有权限去访问这个地址编号里面的内容。

而且一般来说这种对野指针的非法访问,其普遍性更高。为什么呢?首先从形式上来说野指针是不唯一的,任何一个指针在你对它进行初始化之前那都是野指针。虽然有一些野指针有一些特别的标识,就是规律性的地址编号,比如0xcccccccc,0xbcbcbcbc……

其二,即便说你有写代码的良好习惯,你每定义一个指针,都对它进行了合适的初始化,那也很难避免野指针,因为野指针的产生可不止这一个途径。

(I)常见的导致野指针的操作:

那在哪些情况下,我们可能会产生野指针呢?那这里就给大家总结了以下一些可能非法访问野指针的操作:

操作一:指针未初始化,就直接拿来用:

如图,下面这种代码就是常见的未初始化指针,就直接使用该指针的例子:

int *p;
*p = 10;

这里定义了一个指针p,但是没有任何对指针进行初始化的操作,就直接进行解引用并赋值为10,这样的写法是错误的。

正确的做法,是先要对指针变量进行初始化。常见的对指针变量进行初始化的方法有:

  • 把一个实际变量的地址作为初始值赋值给指针变量之后,再使用指针变量
  • 将某个函数的返回值作为初始值赋值给指针变量,这个函数的返回值是其对应的指针类型,亦或是void*类型。典型的例子就是指针通过malloc函数(C语言里面用来申请内存空间的一个库函数)拿到内存中一部分空间,并对这一部分空间进行管理。
  • 某些库函数或用户自定义函数,拿指针变量的地址做参数,并通过这种方式对该指针变量进行初始化。即通过某些具有初始化指针变量的函数对指针变量进行初始化。

通过上面这一些方法初始化指针变量之后,你就可以放心大胆地使用它了。

操作二:数组的越界访问:

C语言创建变量的本质就是在向内存申请空间,如果你定义了一个数组,那么你将拥有了一段连续的内存空间的使用权。

但是这段连续的空间是有限的。你只能在数组合法的范围内访问它,超出这段合法范围的空间就是野指针,使用权限是不属于你的,即下面这种写法也是常见的野指针的非法访问:

int arr[10] = { 0 };
arr[10] = 10;

数组长度是10,最大的有效检索下标是9,你访问的下标为10这里的空间其实并不属于你,这种就是野指针的非法访问。

操作三:指针指向的空间被释放了:

最后就是指针指向的空间被释放了,常见一个场景就是你在一个函数A内部返回一个局部变量的地址,并且在另一个函数B里面调用了函数A,并且使用了它返回过来的地址。那就是非常典型的访问空间被释放的指针的地址,这是一个野指针,你去访问那就会出现问题了!

举例说明,如图下面这种写法是不能得到其所期望的结果的:

#include<stdio.h>

int* test()
{
	int a = 10;
	printf("%p\n", &a);
	return &a;
}

int main()
{
	int* p = test();
	printf("%p %d\n", p, *p);
	printf("%p %d\n", p, *p); 
	printf("%p %d\n", p, *p);
	return 0;
}

运行结果:

第一次使用这块地址,你会发现可以打印出预期的10,但是多运行几次呢,显然野指针就无法经受考验了。

那C语言里面有没有办法拿到一个函数里面局部变量的地址,并且在其他地方去正常使用这个地址,实际上也不是没有办法,如果你对C语言的动态内存管理有点了解的话这也是可以做到的。但不是我们现在探讨的重点所在。

这些都是我们在使用指针时会导致野指针的不当操作。但是你说只有这些吗?实际上这只是一些常见的导致野指针的不当操作,学习和工作中可能难免会有更加复杂的场景。所以这更多需要我们大家多练习,多积累实践经验,多总结才能有效规避野指针的产生。即熟能生巧。

三、正确使用指针的良好习惯:

虽然说,熟能生巧,但是首先第一步也是最重要的一步,就要要建立起良好的编程习惯。博主在下面给大家系统总结出下面一些日常用C语言的良好习惯,做到这些能有效减少野指针的产生,希望能够帮助到你:

  • 定义出指针的同时就对指针进行初始化,如果你目前还不确定应该初始化什么值,为了安全,请把这个指针赋值为NULL;
  • 请小心数组的的越界;
  • 指针指向的空间被释放以后(用户可以通过free函数释放一个指针指向的空间,具体详情请关注C语言的动态内存管理的内容),应当及时置空;
  • C语言的函数应当避免返回局部变量的地址;
  • 最后也是之前提到过的,指针使用之前检查指针的有效性,指针不为NULL,我们才使用它。

那么今天的总结到这里就结束了,关于指针学习方面的博客我们就要告一段落了,但是指针在我们后面的学习当中扮演着不可或缺的角色,尤其是在C语言的动态内存管理和数据结构方面,所以以后见到它的机会和复习这块知识的机会还是挺多的😁!

那么,下期再见喽!🙂🙂🙂

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值