c语言--空指针和野指针

本文详细介绍了C语言中指针的概念,包括不同类型指针的声明,野指针的形成原因(未初始化、越界访问和空间释放),以及如何通过初始化、检查边界和置NULL来规避野指针。还强调了空指针(NULL)的区别和正确使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、指针简介

指针很灵活,它可以指向任意类型的数据。指针的类型说明了它所指向地址空间的内存,以下是有效的指针声明:

int    *p;    /* 一个整型的指针 */
double *p;    /* 一个 double 型的指针 */
float  *p;    /* 一个浮点型的指针 */
char   *p;    /* 一个字符型的指针 */

二、野指针

概念

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

成因

1.指针未初始化

#include<stdio.h>
int main()
{
	int* p;//局部变量指针未初始化,默认为随机值
	*p = 20;
	return 0;
}

2.指针越界访问

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = &arr[0];//p此时不是野指针
	int i = 0;
	for (i = 0; i <= 11; i++)
	{
		        //当指针指向的范围超出数组arr的范围时,p就是野指针
		*(p++) = i;
	}
	return 0;
}

在这里插入图片描述

运行结果:
在这里插入图片描述
这就是指针越界访问了后的结果。

3.指针指向的空间释放

#include<stdio.h>
int* test()
{
	int a = 0;
	return &a;
}
int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

在这里插入图片描述
这就是非法访问了。

如何规避野指针

1.指针初始化

1.如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给初始化一个明确的地址。2.如果现在还不知道应该指向哪里,就初始化为NULL。
例如:

#include<stdio.h>
int main()
{
	int a = 10;
	int* p = &a;//1.明确知道指针指向哪里
	int* p2 = NULL;//不明确指针指向哪里
	return 0;
}

2. 小心指针越界

一个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是
越界访问。如上面那个代码的解释。

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = &arr[0];//p此时不是野指针
	int i = 0;
	for (i = 0; i <= 11; i++)
	{
		        //当指针指向的范围超出数组arr的范围时,p就是野指针
		*(p++) = i;
	}
	return 0;

3.指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性免返回局部变量的地址

当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的时候,我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问,同时使⽤指针之前可以判断指针是否为NULL。我们可以把野指针想象成野狗,野狗放任不管是⾮常危险的,所以我们可以找⼀棵树把野狗拴起来,就相对安全了,给指针变量及时赋值为NULL,其实就类似把野狗栓前来,就是把野指针暂时管理起来。不过野狗即使拴起来我们也要绕着⾛,不能去挑逗野狗,有点危险;对于指针也是,在使⽤之前,我们也要判断是否为NULL,看看是不是被拴起来起来的野狗,如果是不能直接使⽤,如果不是我们再去使⽤。

4.避免返回局部变量的地址

不要返回局部变量的地址(解释如上图)

#include<stdio.h>
int* test()
{
	int a = 0;
	return &a;
}
int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

三、空指针(NULL)

在 C 语言中,如果一个指针不指向任何数据,我们就称之为 空指针 ,用 NULL 表示。例如:

int *p = NULL;

注意区分大小写,null 没有任何特殊含义,只是一个普通的标识符。NULL 是一个宏定义,在 stdio.h 被定义为:

#define NULL ((void *)0)

我们知道,变量一旦定义就要分配内存,指针变量也是如此。例如:

int *p;  //它不是空指针,这个是为初始化

它的值是随机的,是垃圾值,如果不小心使用了它,运行时一般会引起段错误,导致程序退出,甚至会不知不觉地修改数据。p 经过定义,就一定在内存中分配了 4 个字节的空间,只是它的值是随机的,不像 int 会被初始化为 0,但是它确实指向了一段正常使用的内存。使用 p 时,操作的就是这段内存的数据,幸运的话能够正常运行,不过大部分情况下这段内存是无权操作。

NULL 和 0

不要把 NULL 和 0 等同起来,下面的写法也是不对的:

int *p = 0;

正确的书写:

int *p = NULL;

在这里插入图片描述
欧耶!!!!!!!我学会啦!!!!!!!

好的,在 C 语言中,“空指针指针”是非常重要的两个概念,它们都涉及到内存管理的问题。 ### 空指针 (Null Pointer) **空指针**是指指向地址值为 `NULL` 的指针变量。它表示该指针当前未指向任何有效的内存位置。 在程序运行时,如果尝试访问或解引用一个空指针,则会触发未定义行为(通常导致程序崩溃)。因此,使用空指针前需要先检查是否为空。 #### 示例: ```c int *p = NULL; // 定义了一个空指针 p if (p == NULL) { printf("Pointer is null.\n"); } ``` --- ### 指针 (Wild Pointer) **指针**是一个指向未知或无效内存区域的指针,其内容未经初始化或者已经释放了所指向的内存空间。由于这种状态的存在,当对指针进行操作时可能会破坏其他数据甚至造成系统不稳定。 常见的形成原因包括: 1. 指针声明之后没有显式地赋初值; 2. 动态分配的空间被 free() 后仍继续使用原指针; 3. 函数返回局部自动变量地址等错误做法; #### 示例: ```c int* p; // 此处 p 未被初始化,成为指针 void func(int **pptr){ int x=5; *pptr=&x; /* 将函数内局部变量取址给外部传入的二级指针 */ } /* 当退出func后,x的生命期结束,再次通过pptr间接访问就会出错 */ int main(){ int y,*q=NULL; func(&q); /* q 变成了指向已销毁堆栈上对象的一个指针*/ if(q != NULL){ cout << "Value:"<< (*q)<<endl ; // 这里存在潜在危险,因为*q不再有效 } } ``` 为了防止这些问题的发生,应该尽量避免上述情况,并养成良好的编码习惯比如及时将不用的动态存储区置零(`free(ptr),ptr=null`) 或者初始化所有的新创建指针等等措施都可以有效地降低产生指针的概率。 --- ### 总结对比: | 特性 | 空指针 | 指针 | |---------------|----------------------------------|-----------------------------| | 是否明确 | 明确无误 | 地址不确定 | | 使用风险 | 如果直接解引会导致异常终止 | 高度不可预测的风险 | 希望这个解释能够帮到您!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

权^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值