<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 深入理解void類(lèi)型

深入理解void類(lèi)型

作者: 時(shí)間:2016-11-27 來(lái)源:網(wǎng)絡(luò ) 收藏
1.空指針

一般來(lái)說(shuō),程序的起始地址是從“代碼區”的0地址開(kāi)始存放的(注:如果插入一個(gè)內存分布圖,則更能說(shuō)明問(wèn)題,此處省略),但實(shí)際上現代操作系統并非如此,卻保留了從0開(kāi)始的一塊內存。至于這塊內存到底有有多大,與具體的操作系統有關(guān)。如果程序試圖訪(fǎng)問(wèn)這塊內存,則系統提示異常。

本文引用地址:http://dyxdggzs.com/article/201611/322491.htm

為什么操作系統不是保留一個(gè)字節呢?由于內存管理是按頁(yè)來(lái)進(jìn)行的,因此無(wú)法做到單獨保留一個(gè)字節。盡管如此,但還是有極少數系統設定RAM區從0地址開(kāi)始,但指向有效變量的指針不會(huì )指向0地址。即使“代碼區”從0地址開(kāi)始,但在任何情況下,0地址都不是C語(yǔ)言中任何函數的起始地址,因此指向有效函數地址的指針也不會(huì )指向0地址。

?課外知識延伸

雖然80C51微控制器XDATA區(外部RAM)是從0地址開(kāi)始的,但只要對保存在0地址中的變量不進(jìn)行取地址操作(&操作),即可有效地保證指針不會(huì )指向0地址。

與此同時(shí),雖然32位ARM7微控制器也是從0地址開(kāi)始的,但這塊內存僅用于存放中斷向量代碼,而不是程序中的有效變量地址,因此即便用空指針來(lái)判斷指針的有效性,其仍然是可行的。

基于此,于是將空指針定義為指向0地址的指針。毫無(wú)疑問(wèn),任何一種指針類(lèi)型都有一個(gè)特殊的指針值,即空指針。它既不會(huì )指向任何對象或函數,也不是任何對象或函數的地址。而未初始化的指針,則完全可能指向任何地方。

由此可見(jiàn),空指針與未初始化的指針是完全不同的兩個(gè)概念。那么,將如何在程序中獲得一個(gè)空指針呢?

2.空指針常量與NULL

標準C規定,在初始化、賦值或比較時(shí),如果一邊是變量或指針類(lèi)型的表達式,則編譯器可以確定另一邊的常數0為空指針,并生成正確的空指針值。即在指針上下文中“值為0的整型常量表達式”在編譯時(shí)轉換為空指針。

為了讓程序中的空指針使用更加明確,標準C專(zhuān)門(mén)定義了一個(gè)標準預處理宏NULL,其值為“空指針常量”,通常為0或(void *)0,即在指針上下文中NULL與0是等價(jià)的,而未加修飾的0也是完全可以接受的。由于void *指針的特殊賦值屬性,比如:

#define NULL ((void *)0)

當NULL定義為((void *)0)時(shí),即NULL是可以賦值給任何類(lèi)型指針的值,它的類(lèi)型為void*,而不是整數0,因此初始化“FILE *fp = NULL;”是完全合法的。

而為了區分整數0和空指針0,當需要其它類(lèi)型的0的時(shí)候,即使可能工作,但也不能使用NULL,如果這樣處理其格式是錯誤的,這在非指針上下文中是不能工作的。特別地,不能在需要ASCII空字符(NUL)的地方使用NULL。如果確實(shí)需要,則可以自定義為:

#define NUL

由此可見(jiàn),常數0是一個(gè)空指針常量,而NULL僅僅是它的一個(gè)別名。

3.空指針的用途

一般來(lái)說(shuō),未初始化是不能使用的非法指針,因為它完全有可能指向任何地方,從而導致程序無(wú)法判斷它為非法指針。因此,不管指針變量是全局的還是局部的、靜態(tài)的還是非靜態(tài)的,都應該在聲明它的同時(shí)進(jìn)行初始化,要么賦予一個(gè)有效的地址,要么賦予NULL。

標準C規定,全局指針變量的默認值為NULL,而對于局部指針變量則必須明確地指定其初值。因此,void通常用于指針變量的初始化,用來(lái)判斷一個(gè)指針的有效性。比如:

unsigned char *pucBuf=(void *)0;//定義pucBuf為unsigned char類(lèi)型指針并初始化為空指針

如果后續的代碼忘記初始化指針而直接使用的話(huà),則可能造成程序失敗。雖然空指針也是非法指針,但可以通過(guò)程序判斷并告訴程序員代碼可能有問(wèn)題。也就是說(shuō),如果一開(kāi)始就將指針初始化為空指針,則可避免程序異常。比如:

if(pucBuf==0){

return error;//如果pucBuf為空指針,則返回參數錯誤

}

由于void類(lèi)型指針的不確定性,因此它可以指向任意類(lèi)型的數據,那么只要在使用時(shí)做一個(gè)簡(jiǎn)單的強制類(lèi)型轉換就可以了。比如:

unsignned char*pcData = NULL;//定義pcData為unsigned char類(lèi)型指針

void*pvData;//定義pvData為void類(lèi)型指針

pvData = pcData;//無(wú)需進(jìn)行強制類(lèi)型轉換

pcData = (unsigned char*) pvData;//將pvData強制轉換為unsigned char類(lèi)型指針

顯然不存在void類(lèi)型的對象,也就是說(shuō),當對象為空類(lèi)型時(shí),其大小為0字節;當對象未確定類(lèi)型時(shí),那么它的大小也是未確定的,因此不能聲明void類(lèi)型變量。比如:

void a;//非法聲明

既然上述聲明是非法的,那么,也就不能將sizeof運算符用于void類(lèi)型。也就意味著(zhù),編譯器不知道所指對象的大小,由于指針的算術(shù)運算總是基于所指對象的大小的,因此不允許對void指針進(jìn)行算術(shù)運算。

總之,在指針聲明中,void *表示通用指針的類(lèi)型。如果void作為函數的返回類(lèi)型,則表示不返回任何值。如果void位于參數列表中,則表示沒(méi)有參數。

4. 用無(wú)類(lèi)型指針作為函數參數

由于C語(yǔ)言中最小長(cháng)度的變量為char類(lèi)型(包括unsigned char、signed char等),其sizeof(char)的結果為1,而其它任何變量的長(cháng)度都是它的整數倍。比如,如果使用SDCC51編譯器,其sizeof(int)為2。因為通用swap函數函數不知道需要交換的變量的類(lèi)型,所以需要一個(gè)參數給出相應的指示。由于C語(yǔ)言的變量類(lèi)型多種多樣,因此不可能為每一種變量類(lèi)型編號,而且swap并不關(guān)心變量的真正類(lèi)型,所以可以用變量的長(cháng)度代替變量類(lèi)型。通用swap函數的原型為:

void swap(void *pvData1, void *pvData2, int iDataSize)

將a,b兩個(gè)變量(變量類(lèi)型必須一樣)的值交換的代碼如下:

swap(&a, &b, sizeof(a));

通用swap排序函數的參考代碼見(jiàn)程序清單1.1。

程序清單1.1通用swap排序函數

1void swap (void *pvData1, void *pvData2, int iDataSize)

2{

3unsigned char *pcData1 = NULL;

4unsigned char *pcData2 = NULL;

5unsigned charucTmp1;

6

7pcData1 = (unsigned char *)pvData1;

8pcData2 = (unsigned char *)pvData2;

9

10do {

11ucTmp1 = *pcData1;

12*pcData1= *pcData2;

13*pcData2= ucTmp1;

14pcData1++;

15pcData2++;

16} while (--iDataSize > 0);

17}



關(guān)鍵詞: 深入理解void類(lèi)

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>