網絡消費網 >  5G > > 正文
        深入理解void類型
        時間:2021-12-04 10:22:04
        1.空指針

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

        本文引用地址:http://www.eepw.com.cn/article/201611/322491.htm

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

        ?課外知識延伸

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

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

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

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

        2.空指針常量與NULL

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

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

        #define NULL ((void *)0)

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

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

        #define NUL

        由此可見,常數0是一個空指針常量,而NULL僅僅是它的一個別名。

        3.空指針的用途

        一般來說,未初始化是不能使用的非法指針,因為它完全有可能指向任何地方,從而導致程序無法判斷它為非法指針。因此,不管指針變量是全局的還是局部的、靜態的還是非靜態的,都應該在聲明它的同時進行初始化,要么賦予一個有效的地址,要么賦予NULL。

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

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

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

        if(pucBuf==0){

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

        }

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

        unsignned char*pcData = NULL;//定義pcData為unsigned char類型指針

        void*pvData;//定義pvData為void類型指針

        pvData = pcData;//無需進行強制類型轉換

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

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

        void a;//非法聲明

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

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

        4. 用無類型指針作為函數參數

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

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

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

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

        通用swap排序函數的參考代碼見程序清單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}

        關鍵詞: 深入理解void類

        版權聲明:
            凡注明來網絡消費網的作品,版權均屬網絡消費網所有,未經授權不得轉載、摘編或利用其它方式使用上述作品。已經本網授權使用作品的,應在授權范圍內使用,并注明"來源:網絡消費網"。違反上述聲明者,本網將追究其相關法律責任。
            除來源署名為網絡消費網稿件外,其他所轉載內容之原創性、真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考并自行核實。
        熱文

        網站首頁 |網站簡介 | 關于我們 | 廣告業務 | 投稿信箱
         

        Copyright © 2000-2020 www.fnsyft.com All Rights Reserved.
         

        中國網絡消費網 版權所有 未經書面授權 不得復制或建立鏡像
         

        聯系郵箱:920 891 263@qq.com

        備案號:京ICP備2022016840號-15

        營業執照公示信息

        亚洲乱亚洲乱妇无码麻豆| 国产精品亚洲午夜一区二区三区| 亚洲美女色在线欧洲美女| 亚洲精品国产福利一二区| 亚洲爆乳精品无码一区二区| 久久久久亚洲国产| 亚洲日日做天天做日日谢| 精品亚洲AV无码一区二区| 亚洲国产成人精品无码区在线网站| 亚洲黄色在线观看网站| 亚洲精品自拍视频| 亚洲国产精品成人精品小说| 亚洲第一二三四区| 亚洲乱码中文论理电影| 67194在线午夜亚洲| 亚洲高清视频在线| 亚洲精华国产精华精华液| 亚洲JLZZJLZZ少妇| www亚洲精品少妇裸乳一区二区| 理论亚洲区美一区二区三区| 高清在线亚洲精品国产二区| 亚洲国产高清在线一区二区三区| 亚洲色偷拍区另类无码专区| 中文字幕亚洲不卡在线亚瑟| 亚洲综合国产一区二区三区| 亚洲成色WWW久久网站| 久久精品国产精品亚洲色婷婷| 亚洲日本中文字幕| 亚洲国产精品综合久久2007| 亚洲人成77777在线播放网站不卡 亚洲人成77777在线观看网 | 亚洲婷婷天堂在线综合| 33333在线亚洲| 亚洲av无一区二区三区| 亚洲高清无码专区视频| 亚洲小说区图片区另类春色| 亚洲Av熟妇高潮30p| 亚洲国产午夜电影在线入口| 亚洲日韩av无码中文| avtt亚洲天堂| 亚洲精品国产成人片| 久久久久亚洲AV无码专区首JN|