首頁  >  文章  >  php教程  >  深入理解void以及void指針的含義

深入理解void以及void指針的含義

高洛峰
高洛峰原創
2016-12-13 13:15:531458瀏覽

void的意義
void即“無型別”,void *則為“無型別指標”,可指向任何資料型別。

void指標使用規範
①void指標可以指向任意類型的數據,亦即可以任意資料型別的指標為void指標賦值。例如:
int *pint;
void *pvoid;
pvoid = pint; /* 不過不能pint = pvoid; */
如果要將pvoid賦給其他型別指針,則需要強制型別轉換如:pint = (int * )pvoid;


②在ANSI C標準中,不允許對void指標進行算術運算如pvoid++或pvoid+=1等,而在GNU中則允許,因為在缺省情況下,GNU認為void *與char *一樣。 sizeof( *pvoid )== sizeof( char ).

void的作用
①對函數傳回的限定。
②對函數參數的限定。
當函數不需要傳回值時,必須使用void限定。例如: void func(int, int);
當函數不允許接受參數時,必須使用void限定。例如: int func(void)。


由於void指標可以指向任意類型的數據,亦即可用任意資料型別的指標針對void指標賦值,因此也可以用void指標來當作函數形參,這樣函數就可以接受任意資料型別的指標作為參數。例如:
void * memcpy( void *dest, const void *src, size_t len );
void * memset( void * buffer, int c, size_t num );

許多初學者對C/C++語言中的void及void指標類型不甚理解,因此在使用上出現了一些錯誤。本文將對void關鍵字的深刻意義進行解說,以下詳述void及void指標類型的使用方法與技巧。

1.規則小心使用void指標型別
  依照ANSI(AmericanNationalStandardsInstitute)標準,不能對void指標進行演算法操作,即下列操作都是不合法的:
void*pvoid;
pvoid++//ANSI:錯誤+ =1;//ANSI:錯誤
//ANSI標準之所以這樣認定,是因為它堅持:進行演算法操作的指標必須是確定知道其指向資料類型大小的。
//例如:
int*pint;
pint++;//ANSI:正確
  pint++的結果是使其增大sizeof(int)。
  但是大名鼎鼎的GNU(GNU'sNotUnix的縮寫)則不這麼認定,它指定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標準。

2.規則二如果函數的參數可以是任意類型指針,那麼應聲明其參數為void*

  典型的如內存操作函數memcpy和memset的函數原型分別為:
void*memcpy(void*dest,constvoid *src,size_tlen);   
void*memset(void*buffer,intc,size_tnum);
  這樣,任何類型的指標都可以傳入memcpy和memset中,這也真實地體現了記憶體運算元的意義,因為它可以傳入memcpy和memset中,這也真實地體現了記憶體運算元的意義,因為它操作的物件僅僅是一片內存,而不論這片內存是什麼類型。如果 memcpy和memset的參數類型不是void*,而是char*,那才叫真的奇怪了!這樣的memcpy和memset明顯不是一個「純粹的,脫離低級趣味的」函數!
下面的程式碼執行正確:
//範例:memset接受任意型別指標
int  intarray[100]; 
memset(intarray,0,100*sizeof(int));//將intarray任意型別指標
int  intarray1[100],  intarray2[100];
memcpy(intarray1,intarray2,100*sizeof(int));//將intarray2拷貝給intarray1
 *型,標準函式庫函數的編寫者是多麼地富有學問啊!

3.規則三void不能代表一個真實的變數

  下面程式碼都企圖讓void代表一個真實的變數,因此都是錯誤的程式碼:

voida;//錯誤
function(voida);//錯誤
    體現了一種抽象,這個世界上的變數都是「有類型」的,譬如一個人不是男人就是女人(還有人妖?)。
  void的出現只是為了一種抽象的需要,如果你正確地理解了物件導向中「抽象基底類別」的概念,也很容易理解void資料類型。正如不能為抽象基底類別定義一個實例,我們也不能定義一個void(讓我們類比的稱void為「抽象資料類型」)變數。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:void與void*詳解下一篇:void與void*詳解