您好,登錄后才能下訂單哦!
這篇文章主要介紹“C語言中void*的用法”,在日常操作中,相信很多人在C語言中void*的用法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C語言中void*的用法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
void在英文中作為名詞的解釋為"空虛、空間、空隙",而在C語言中,void被翻譯為"無類型",相應的void*為"無類型指針"。
void似乎只有"注釋"和限制程序的作用,當然,這里的"注釋"不是為我們人提供注釋,而是為編譯器提供一種所謂的注釋。
1.對函數返回的限定,這種情況我們比較常見。
2.對函數參數的限定,這種情況也是比較常見的。
當函數不需要返回值值時,必須使用void限定,這就是我們所說的第一種情況。例如:voidfunc(inta,char*b)。
當函數不允許接受參數時,必須使用void限定,這就是我們所說的第二種情況。例如:intfunc(void)。
1.void指針可以指向任意類型的數據,就是說可以用任意類型的指針對void指針對void指針賦值。例如:
int*a;
void*p;
p=a;
如果要將void指針p賦給其他類型的指針,則需要強制類型轉換,就本例而言:a=(int*)p。在內存的分配中我們可以見到void指針使用:內存分配函數malloc函數返回的指針就是void*型,用戶在使用這個指針的時候,要進行強制類型轉換,也就是顯式說明該指針指向的內存中是存放的什么類型的數據(int*)malloc(1024)表示強制規定malloc返回的void*指針指向的內存中存放的是一個個的int型數據。
2.在ANSIC標準中,不允許對void指針進行一些算術運算如p++或p+=1等,因為既然void是無類型,那么每次算術運算我們就不知道該操作幾個字節,例如char型操作sizeof(char)字節,而int則要操作sizeof(int)字節。而在GNU中則允許,因為在默認情況下,GNU認為void*和char*一樣,既然是確定的,當然可以進行一些算術操作,在這里sizeof(*p)==sizeof(char)。
void幾乎只有"注釋"和限制程序的作用,因為從來沒有人會定義一個void變量,讓我們試著來定義:
voida;
這行語句編譯時會出錯,提示"illegaluseoftype'void'"。即使voida的編譯不會出錯,它也沒有任何實際意義。
眾所周知,如果指針p1和p2的類型相同,那么我們可以直接在p1和p2間互相賦值;如果p1和p2指向不同的數據類型,則必須使用強制類型轉換運算符把賦值運算符右邊的指針類型轉換為左邊指針的類型。
float*p1;
int*p2;
p1=p2;
//其中p1=p2語句會編譯出錯,
//提示“'=':cannotconvertfrom'int*'to'float*'”,必須改為:
p1=(float*)p2;
而void*則不同,任何類型的指針都可以直接賦值給它,無需進行強制類型轉換。
void*p1;
int*p2;
p1=p2;
但這并不意味著,void*也可以無需強制類型轉換地賦給其它類型的指針。因為"無類型"可以包容"有類型",而"有類型"則不能包容"無類型"。
按照ANSI(AmericanNationalStandardsInstitute)標準,不能對void指針進行算法操作,即下列操作都是不合法的:
void*pvoid;
pvoid++;//ANSI:錯誤
pvoid+=1;//ANSI:錯誤
//ANSI標準之所以這樣認定,是因為它堅持:進行算法操作的指針必須是確定知道其指向數據類型大小的。
//例如:
int*pint;
pint++;//ANSI:正確pint++的結果是使其增大sizeof(int)。
但是GNU則不這么認定,它指定void*的算法操作與char*一致。因此下列語句在GNU編譯器中皆正確:
pvoid++;//GNU:正確
pvoid+=1;//GNU:正確
pvoid++的執行結果是其增大了1。
在實際的程序設計中,為迎合ANSI標準,并提高程序的可移植性,我們可以這樣編寫實現同樣功能的代碼:
void*pvoid;
((char*)pvoid)++;//ANSI:錯誤;GNU:正確
(char*)pvoid+=1;//ANSI:錯誤;GNU:正確
GNU和ANSI還有一些區別,總體而言,GNU較ANSI更"開放",提供了對更多語法的支持。但是我們在真實設計時,還是應該盡可能地迎合ANSI標準。如果函數的參數可以是任意類型指針,那么應聲明其參數為void*。
注:void指針可以任意類型的數據,可以在程序中給我們帶來一些好處,函數中形為指針類型時,我們可以將其定義為void指針,這樣函數就可以接受任意類型的指針。如:
void*memcpy(void*dest,constvoid*src,size_tlen);
void*memset(void*buffer,intc,size_tnum);
這樣,任何類型的指針都可以傳入memcpy和memset中,這也真實地體現了內存操作函數的意義,因為它操作的對象僅僅是一片內存,而不論這片內存是什么類型(參見C語言實現泛型編程)。如果memcpy和memset的參數類型不是void*,而是char*,那才叫真的奇怪了!這樣的memcpy和memset明顯不是一個"純粹的,脫離低級趣味的"函數!void的出現只是為了一種抽象的需要,如果你正確地理解了面向對象中"抽象基類"的概念,也很容易理解void數據類型。正如不能給抽象基類定義一個實例,我們也不能定義一個void(讓我們類比的稱void為"抽象數據類型")變量。
到此,關于“C語言中void*的用法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。