C語(yǔ)言的空類型指針,空指針,野指針詳解
空類型指針-void*
void是空類型,void*是空類型指針,又叫萬(wàn)能指針,就是該指針能接收任意類型的指針,可以指向任何類型對(duì)象,所以不能對(duì)空類型指針進(jìn)行解引用,必須強(qiáng)制類型轉(zhuǎn)換成相應(yīng)的指針類型,才能進(jìn)行解引用操作。
空指針類型:
- 作為函數(shù)形參類型,可以接收任意類型的指針;
- 作為函數(shù)返回值類型,在函數(shù)外面,將其強(qiáng)制類型轉(zhuǎn)換為相應(yīng)的指針類型
- 可以與另一個(gè)void*類型指針比較大小
注意:空類型指針不能進(jìn)行解引用操作;不能進(jìn)行±整數(shù)運(yùn)算。
空指針-NULL
在C語(yǔ)言中,空指針NULL指的是地址為0的那塊空間
#define NULL((void*)0)
對(duì)于這塊空間是不準(zhǔn)我們進(jìn)行訪問(wèn)的,所以,對(duì)NULL是不能進(jìn)行解引用操作的,所以每次對(duì)指針進(jìn)行解引用操作之前,我們要判斷是否為空指針。
野指針
野指針是指向一個(gè)非法的或已銷毀的內(nèi)存的指針。
對(duì)野指針進(jìn)行解引用操作是非法的。
造成野指針的原因
1.指針未初始化
int main() { char* p; //此時(shí)p是野指針 return 0; }
沒(méi)有對(duì)指針p進(jìn)行初始化,此時(shí)p就是野指針,如果此時(shí)對(duì)p進(jìn)行解引用操作,非法訪問(wèn)內(nèi)存,程序就會(huì)崩潰。
2.指針越界訪問(wèn)
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; }
雖然上面程序正常運(yùn)行,但是其實(shí)越界訪問(wèn)了;只是僅僅訪問(wèn)了非法的內(nèi)存空間,沒(méi)有改變空間的值,程序有可能沒(méi)來(lái)得及報(bào)錯(cuò),但并不代表程序沒(méi)有錯(cuò),但是對(duì)于下面的代碼,程序就會(huì)崩潰:
int main() { int arr[10] = {0}; int i = 0; int* p = arr; for (i = 0; i <= 10; i++) { *p = i; p++; } return 0; }
因?yàn)檫@里非法訪問(wèn)內(nèi)存的同時(shí)試圖改變空間的值,所以程序崩潰。
3.指針指向的空間已經(jīng)釋放
char* fun() { char arr[] = "abc"; return arr; } int main() { char* p = fun(); printf("%s\n",p); return 0; }
執(zhí)行程序,給出如下警告
雖然程序沒(méi)有崩潰,但是這種寫法是非法的,arr是局部變量,函數(shù)調(diào)用結(jié)束,棧幀銷毀,局部變量空間歸還給操作系統(tǒng),我們沒(méi)有使用權(quán)限,此時(shí)p就是野指針,*p屬于非法訪問(wèn)內(nèi)存。
避免野指針
1.指針要進(jìn)行初始化
指針要有初始值,初始化為NULL,或者有具體的指向。
既然NULL也不能進(jìn)行解引用操作,那么為什么可以將指針初始化為NULL?這里初始化為NULL,只是為了給指針一個(gè)指向,但是實(shí)際使用時(shí),我們并不能對(duì)NULL進(jìn)行解引用操作,所以使用指針之前才要有效性判斷。
2.使用指針之前要進(jìn)行有效性判斷
使用指針之前,要判斷是否為NULL,如果為NULL,那么是不能進(jìn)行解引用操作的
3.避免越界訪問(wèn)
不要進(jìn)行越界訪問(wèn)操作,即使還是訪問(wèn)不改變值也是非法的
4.不要返回局部變量的地址
局部變量空間在函數(shù)到調(diào)用結(jié)束,就歸還給操作系統(tǒng),如果返回局部變量的地址,函數(shù)外面接收該返回值的指針就變成了野指針
5.當(dāng)指針指向的空間釋放后,要將該指針置為NULL
這樣避免對(duì)野指針解引用操作,同時(shí)避免二次釋放動(dòng)態(tài)開辟的內(nèi)存空間
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; }
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++利用PCL點(diǎn)云庫(kù)操作txt文件詳解
這篇文章主要為大家詳細(xì)介紹了C++如何利用PCL點(diǎn)云庫(kù)操作txt文件,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2024-01-01Matlab實(shí)現(xiàn)鼠標(biāo)光標(biāo)變成愛(ài)心和瞄準(zhǔn)鏡形狀
這篇文章主要為大家詳細(xì)介紹了如何利用Matlab實(shí)現(xiàn)將鼠標(biāo)光標(biāo)變成愛(ài)心和瞄準(zhǔn)鏡等形狀,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-08-08C語(yǔ)言中求余弦值的相關(guān)函數(shù)總結(jié)
這篇文章主要介紹了C語(yǔ)言中求余弦值的相關(guān)函數(shù)總結(jié),包括求余弦和雙曲線余弦以及反余弦的求值,需要的朋友可以參考下2015-08-08解析C++中的虛擬函數(shù)及其靜態(tài)類型和動(dòng)態(tài)類型
虛擬函數(shù)(Visual Function)亦常被成為虛函數(shù),是C++中的一個(gè)重要特性,本文我們就來(lái)解析C++中的虛擬函數(shù)及其靜態(tài)類型和動(dòng)態(tài)類型2016-06-06linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼
下面小編就為大家?guī)?lái)一篇linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12