欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

C++教程:NULL指針、零指針、野指針-創(chuàng)新互聯(lián)

C++教程:NULL 指針、零指針、野指針

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名與空間、雅安服務(wù)器托管、營(yíng)銷軟件、網(wǎng)站建設(shè)、沁陽(yáng)網(wǎng)站維護(hù)、網(wǎng)站推廣。

1. 空指針、NULL指針、零指針

1.1什么是空指針常量

0、0L、”、3 – 3、0 * 17 (它們都是“integer constant expression”)以及 (void*)0 (我覺得(void*)0應(yīng)該算是一個(gè)空指針吧,更恰當(dāng)一點(diǎn))等都是空指針常量(注意 (char*) 0 不叫空指針常量,只是一個(gè)空指針值)。至于系統(tǒng)選取哪種形式作為空指針常量使用,則是實(shí)現(xiàn)相關(guān)的。一般的 C 系統(tǒng)選擇 (void*)0 或者 0 的居多(也有個(gè)別的選擇 0L);至于 C++ 系統(tǒng),由于存在嚴(yán)格的類型轉(zhuǎn)化的要求,void* 不能象 C 中那樣自由轉(zhuǎn)換為其它指針類型,所以通常選 0 作為空指針常量(C++標(biāo)準(zhǔn)推薦),而不選擇 (void*)0。

1.2 什么是空指針

如果 p 是一個(gè)指針變量,則 p = 0; p = 0L; p = ”; p = 3 – 3; p = 0 * 17; 中的任何一種賦值操作之后(對(duì)于 C 來說還可以是 p = (void*)0;), p 都成為一個(gè)空指針,由系統(tǒng)保證空指針不指向任何實(shí)際的對(duì)象或者函數(shù)。反過來說,任何對(duì)象或者函數(shù)的地址都不可能是空指針。(比如這里的(void*)0就是一個(gè)空指針。把它理解為null pointer還是null pointer constant會(huì)有微秒的不同,當(dāng)然也不是緊要了)。其實(shí)空指針只是一種編程概念,就如一個(gè)容器可能有空和非空兩種基本狀態(tài)。

1.3 NULL 指針

NULL 是一個(gè)標(biāo)準(zhǔn)規(guī)定的宏定義,用來表示空指針常量。因此,除了上面的各種賦值方式之外,還可以用 p = NULL; 來使 p 成為一個(gè)空指針。

(很多系統(tǒng)中的實(shí)現(xiàn):#define NULL (void*)0,與這里的“a null pointer constant”并不是完全一致的)

C++標(biāo)準(zhǔn)庫(kù)定義的NULL指針

// Define NULL pointer value

#ifndef NULL

# ifdef __cplusplus

# define NULL 0

# else

# define NULL ((void *)0)

# endif

#endif // NULL

NULL是一個(gè)宏,在C++里面被直接被定義成了整數(shù)立即數(shù)類型的0,而在沒有__cplusplus定義的前提下,就被定義成一個(gè)值是0的void *類型指針常量。

1.4 零指針

零值指針,是值為0的指針,可以是任何一種指針類型,可以是通用變體類型void*,也可以是char*,int*等等。

在C++里面,任何一個(gè)概念都要以一種語(yǔ)言內(nèi)存公認(rèn)的形式表現(xiàn)出來,例如std::vector會(huì)提供一個(gè)empty()子函數(shù)來返回容器是否為空,然而對(duì)于一個(gè)基本數(shù)值類型(或者說只是一個(gè)類似整數(shù)類型的類型)我們不可能將其抽象成一個(gè)類(當(dāng)然除了auto_ptr等只能指針)來提供其詳細(xì)的狀態(tài)說明,所以我們需要一個(gè)特殊值來做為這種狀態(tài)的表現(xiàn)。

C++標(biāo)準(zhǔn)規(guī)定,當(dāng)一個(gè)指針類型的數(shù)值是0時(shí),認(rèn)為這個(gè)指針是空的。(我們?cè)谄渌臉?biāo)準(zhǔn)下或許可以使用其他的特殊值來定義我們需要的NULL實(shí)現(xiàn),可以是1,可以是2,是隨實(shí)現(xiàn)要求而定的,但是在標(biāo)準(zhǔn)C++下面我們用0來實(shí)現(xiàn)NULL指針)

1.5 空指針向了內(nèi)存的什么地方(空指針的內(nèi)部實(shí)現(xiàn))?

標(biāo)準(zhǔn)并沒有對(duì)空指針指向內(nèi)存中的什么地方這一個(gè)問題作出規(guī)定,也就是說用哪個(gè)具體的地址值(0x0 地址還是某一特定地址)表示空指針取決于系統(tǒng)的實(shí)現(xiàn)。我們常見的空指針一般指向 0 地址,即空指針的內(nèi)部用全 0 來表示(zero null pointer,零空指針);也有一些系統(tǒng)用一些特殊的地址值或者特殊的方式表示空指針(nonzero null pointer,非零空指針),具體請(qǐng)參見C FAQ。

在實(shí)際編程中不需要了解在我們的系統(tǒng)上空指針到底是一個(gè) zero null pointer 還是 nonzero null pointer,我們只需要了解一個(gè)指針是否是空指針就可以了——編譯器會(huì)自動(dòng)實(shí)現(xiàn)其中的轉(zhuǎn)換,為我們屏蔽其中的實(shí)現(xiàn)細(xì)節(jié)。注意:不要把空指針的內(nèi)部表示等同于整數(shù) 0 的對(duì)象表示——如上所述,有時(shí)它們是不同的。

1.6 對(duì)空指針實(shí)現(xiàn)的保護(hù)政策

既然我們選擇了0作為空的概念,在非法訪問空的時(shí)候我們需要保護(hù)以及報(bào)錯(cuò)。因此,編譯器和系統(tǒng)提供了很好的政策。

我們程序中的指針其實(shí)是WINDOWS內(nèi)存段偏移后的地址,而不是實(shí)際的物理地址,所以不同的程序中的零值指針指向的同一個(gè)0地址,其實(shí)在內(nèi)存中都不是物理內(nèi)存的開端的0,而是分段的內(nèi)存的開端,這里我們需要簡(jiǎn)單介紹一下WINDOWS下的內(nèi)存分配和管理制度:

WINDOWS下,執(zhí)行文件(PE文件)在被調(diào)用后,系統(tǒng)會(huì)分配給它一個(gè)額定大小的內(nèi)存段用于映射這個(gè)程序的所有內(nèi)容(就是磁盤上的內(nèi)容)并且為這個(gè)段進(jìn)行新的偏移計(jì)算,也就是說我們的程序中訪問的所有NEAR指針都是在我們“自家”的段里面的,當(dāng)我們要訪問FAR指針的時(shí)候,我們其實(shí)是跳出了“自家的院子”到了他人的地方,我們需要一個(gè)段偏移地址來完成新的偏移(人家家里的偏移)所以我們的指針可能是OE02:0045就是告訴系統(tǒng)我們要訪問0E02個(gè)內(nèi)存段的0045好偏移,然后WINDOWS會(huì)自動(dòng)給我們找到0E02段的開始偏移,然后為我們計(jì)算真實(shí)的物理地址。

所以程序A中的零值指針和程序B中的零值指針指向的地方可能是完全不同的。

保護(hù)政策:

我們的程序在使用的是系統(tǒng)給定的一個(gè)段,程序中的零值指針指向這個(gè)段的開端,為了保證NULL概念,系統(tǒng)為我們這個(gè)段的開頭64K內(nèi)存做了苛刻的規(guī)定,根據(jù)虛擬內(nèi)存訪問權(quán)限控制,我們程序中(低訪問權(quán)限)訪問要求高訪問權(quán)限的這64K內(nèi)存被視作是不容許的,所以會(huì)必然引發(fā)Access Volitation 錯(cuò)誤,而這高權(quán)限的64K內(nèi)存是一塊保留內(nèi)存(即不能被程序動(dòng)態(tài)內(nèi)存分配器分配,不能被訪問,也不能被使用),就是簡(jiǎn)單的保留,不作任何使用。

我們?cè)谥苯佣x一個(gè)指針后并不知道這個(gè)指針指向何處(而不是有些程序員認(rèn)為的如同JAVA等語(yǔ)言會(huì)自動(dòng)零值初始化),所以我們一旦非法地直接訪問這些未知地內(nèi)容時(shí),極其有可能會(huì)觸碰到程序所不能觸碰地內(nèi)存(這時(shí)類似64K限制地保護(hù)政策又會(huì)起效,就如同你不僅隨意闖入了陌生人的家(野指針),而且拿著刀子要問他要錢(訪問),警察(WINDOWS內(nèi)存訪問保護(hù)政策)當(dāng)然請(qǐng)你去警察局(報(bào)錯(cuò))談?wù)?,所以養(yǎng)成良好的指針初始化(賦值為NULL)以及使用FREE(或者時(shí)DELETE)之后立即再初始化為空是十分必要的!

1.7 為什么通過空指針讀寫的時(shí)候就會(huì)出現(xiàn)異常?

NULL指針分配的分區(qū):其范圍是從 0x00000000到0x0000FFFF。這段空間是空閑的,對(duì)于空閑的空間而言,沒有相應(yīng)的物理存儲(chǔ)器與之相對(duì)應(yīng),所以對(duì)這段空間來說,任何讀寫操作都是會(huì)引起異常的??罩羔樖浅绦驘o(wú)論在何時(shí)都沒有物理存儲(chǔ)器與之對(duì)應(yīng)的地址。為了保障“無(wú)論何時(shí)”這個(gè)條件,需要人為劃分一個(gè)空指針的區(qū)域,固有上面NULL指針分區(qū)。

1.8 是否可以定義自己的 NULL 的實(shí)現(xiàn)?

NULL 是標(biāo)準(zhǔn)庫(kù)中的一個(gè)reserved identifier (保留標(biāo)識(shí)符)。所以,如果包含了相應(yīng)的標(biāo)準(zhǔn)頭文件而引入了 NULL 的話,則再在程序中重新定義 NULL 為不同的內(nèi)容是非法的,其行為是未定義的。也就是說,如果是符合標(biāo)準(zhǔn)的程序,其 NULL 的值只能是 0,不可能是除 0 之外的其它值,比如 1、2、3 等。

1.9 malloc 函數(shù)在分配內(nèi)存失敗時(shí)返回 0 還是 NULL?

malloc 函數(shù)是標(biāo)準(zhǔn) C 規(guī)定的庫(kù)函數(shù)。在標(biāo)準(zhǔn)中明確規(guī)定了在其內(nèi)存分配失敗時(shí)返回的是一個(gè) “null pointer”(空指針)。對(duì)于空指針值,一般的文檔(比如 man)中傾向于用 NULL 表示,而沒有直接說成 0。但是我們應(yīng)該清楚:對(duì)于指針類型來說,返回 NULL 和 返回 0 是完全等價(jià)的,因?yàn)?NULL 和 0 都表示 “null pointer”(空指針)。(一般系統(tǒng)中手冊(cè)中都返回NULL)

C++里面的NEW再內(nèi)存失敗是會(huì)拋出一個(gè)BAD_ALLOC異常。

2. 野指針

“野指針”不是NULL指針,是指向“垃圾”內(nèi)存的指針。

2.1 “野指針”的成因主要有兩種

1)指針變量沒有被初始化。任何指針變量剛被創(chuàng)建時(shí)不會(huì)自動(dòng)成為NULL指針,它的缺省值是隨機(jī)的,它會(huì)亂指一氣。所以,指針變量在創(chuàng)建的同時(shí)應(yīng)當(dāng)被初始化,要么將指針設(shè)置為NULL,要么讓它指向合法的內(nèi)存。例如:

char *p = NULL;

char *str = (char *) malloc(100);

2)指針p被free或者delete之后,沒有置為NULL,讓人誤以為p是個(gè)合法的指針。

free和delete只是把指針?biāo)傅膬?nèi)存給釋放掉,但并沒有把指針本身干掉。free以后其地址仍然不變(非NULL),只是該地址對(duì)應(yīng)的內(nèi)存是垃圾,p成了“野指針”。如果此時(shí)不把p設(shè)置為NULL,會(huì)讓人誤以為p是個(gè)合法的指針。如果程序比較長(zhǎng),我們有時(shí)記不住p所指的內(nèi)存是否已經(jīng)被釋放,在繼續(xù)使用p之前,通常會(huì)用語(yǔ)句if (p != NULL)進(jìn)行防錯(cuò)處理。很遺憾,此時(shí)if語(yǔ)句起不到防錯(cuò)作用,因?yàn)榧幢鉷不是NULL指針,它也不指向合法的內(nèi)存塊。

char *p = (char *) malloc(100);

strcpy(p, “hello”);

free(p); // p 所指的內(nèi)存被釋放,但是p所指的地址仍然不變

if(p != NULL) // 沒有起到防錯(cuò)作用

{

strcpy(p, “world”); // 出錯(cuò)

}

3)指針操作超越了變量的作用范圍。這種情況讓人防不勝防,示例程序如下:

class A

{

public:

void Func(void){ cout << “Func of class A” << endl; }

};

void Test(void)

{

A *p;

{

A a;

p = &a; // 注意 a 的生命期 ,只在這個(gè)程序塊中(花括號(hào)里面的兩行),而不是整個(gè)test函數(shù)

}

p->Func(); // p是“野指針”

}

函數(shù)Test在執(zhí)行語(yǔ)句p->Func()時(shí),對(duì)象a已經(jīng)消失,而p是指向a的,所以p就成了“野指針”。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

分享標(biāo)題:C++教程:NULL指針、零指針、野指針-創(chuàng)新互聯(lián)
本文路徑:http://chinadenli.net/article46/ddeheg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、手機(jī)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司、微信公眾號(hào)建站公司、網(wǎng)站維護(hù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司