空类型指针、空指针、野指针
空类型指针、空指针、野指针
<[id_1833518234]>[id_[id_16[id_939466532]5116553]773146785[id_995624270]id_595955898]void代表一种无类型,而void*则是一种无类型指针,也被称为通用指针。这种指针能够容纳任何类型的指针,指向任何对象类型。因此,我们不能对无类型指针进行解引用操作,必须将其强制转换为特定类型的指针,才能执行解引用。
空类型指针:
[id_1864108888]
空指针-NULL
在C语言中,空指针NULL指的是地址为0的那块空间
#define NULL((void*)0)
这块区域是禁止我们进入的,因此,对NULL对象不能执行解引用c语言空怎么表示,故此,在每次尝试对指针进行解引用之前,我们必须确认它是否为空指针。
野指针
野指针是指向一个非法的或已销毁的内存的指针。
对野指针进行解引用操作是非法的。
百度百科指出,在C/C++这类编程语言里,所谓的悬空指针,是指当指针原本指向的对象被删除后,该指针便失去了指向的有效目标,从而成为悬空指针。而野指针,则是指那些尚未进行初始化的指针。
在这里,我们把悬空指针归为野指针。
造成野指针的原因 1.指针未初始化
int main()
{
char* p;
//此时p是野指针
return 0;
}
由于指针p未经过初始化,它便成为了一个未定义的指针,若在此之后尝试对p进行解引用,将会导致对内存的非法访问c语言空怎么表示,进而引发程序崩溃。
2.指针越界访问
int main()
{
int arr[] = {1,2,3,4,5};
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ",p[i]);
}
return 0;
}
尽管程序目前运行良好,但事实上已经越界访问了数据;尽管仅是访问了那些不合法的内存区域,且并未对这些区域的值进行修改,可能是因为程序尚未捕捉到这一错误,但这并不意味着程序完全无误(编译器也是由人编写的,同样可能含有bug,编译器未能及时报错空类型指针、空指针、野指针,并不意味着我们的代码没有问题!),然而,针对接下来的代码,程序将会直接崩溃。
int main()
{
int arr[10] = {0};
int i = 0;
int* p = arr;
for (i = 0; i <= 10; i++)
{
*p = i;
p++;
}
return 0;
}
因为这里非法访问内存的同时试图改变空间的值,所以程序崩溃。
3.指针指向的空间已经释放
char* fun()
{
char arr[] = "abc";
return arr;
}
int main()
{
char* p = fun();
printf("%s\n",p);
return 0;
}
执行程序,给出如下警告
尽管程序并未发生崩溃,然而此处的编程方式是不合规的;arr作为局部变量,一旦函数调用结束,其栈帧就会被销毁,并且回收至操作系统,我们便失去了对这一局部变量空间的访问权限;在此情况下,p便成为了悬垂指针,对*p的访问则构成了对非法内存的访问。
避免野指针
1.指针要进行初始化
指针要有初始值,初始化为NULL,或者有具体的指向。
既然NULL无法执行解引用动作c语言空怎么表示,那么为何指针可以被设定为NULL值?将指针初始化为NULL,其目的仅是赋予它一个指向,然而在实际应用中空类型指针、空指针、野指针,我们无法对NULL进行解引用,因此在使用指针前必须进行有效性检验。
2.使用指针之前要进行有效性判断
在运用指针前,务必确认其是否为空指针,若是空指针,则不得执行解引用动作。
3.避免越界访问
不要进行越界访问操作,即使还是访问不改变值也是非法的
4.不要返回局部变量的地址
当函数执行完毕后,其局部变量空间会被操作系统收回,若此时函数返回了局部变量的地址,那么在函数外部接收该返回值的指针就会变成无效指针。
5.当指针指向的空间释放后,要将该指针置为NULL
通过这种方式,我们能够防止对野指针进行解引用,并且还能有效防止对已动态分配的内存空间进行重复释放。
int main()
{
int* p = (int*)malloc(10*sizeof(int));
//1.判断有效性
if (p == NULL)
{
return -1;
}
//2.使用指针
int i = 0;
for (i = 0; i < 10; i++)
{
p[i] = i;
}
//3.释放指针指向的空间
free(p);
//free(p);//非法操作
//4.指针置为NULL
p = NULL;
free(p);//释放空指针什么都不做
return 0;
}