記憶體與指標

void 指標

/ void: voyd /

大多數指標帶著型別——int *、char *、double *——說明它們指向什麼。有時你想要一個能持有「任何東西位址」的指標,而不必承諾那是哪一種東西。void 指標,寫成 void *,正是如此:一個通用、無型別的指標,一個沒有附帶被指型別的位址。

void * 可以被指派任何物件的位址,任何物件指標也可以指派回它,在 C 裡都不需要轉型——這就是它之所以是語言中「這裡有一塊記憶體」的通用貨幣(而不說裡面住著什麼)的原因。malloc() 回傳 void * 正是因為它不知道、也不在乎你要存什麼;你把它指派給一個具型別的指標,它就轉換過去。但無型別是有代價的:你不能解參考 void *(沒有東西告訴它要讀幾個位元組),也不能對它做指標算術(沒有元素大小可供縮放)。要使用那份資料,你必須先把它轉成一個具體的指標型別,這會把兩種能力都還給你。

void 指標是 C 寫出「適用於任何型別」程式碼的方式:通用容器、攜帶使用者提供之上下文的回呼,以及像 qsort() 與 memcpy() 這種搬移或比較原始位元組的函式。誠實的提醒是:它丟掉了型別檢查——一旦位址變成 void *,編譯器就無法再告訴你「你把它轉回了錯的型別」,所以一次粗心的轉換可能毫無警告地把位元組重新詮釋成錯誤種類的物件。void * 是刻意設計、強大的「逃離型別系統」之路;把它當成要省著用、且要小心轉回的東西。

void *raw = malloc(sizeof(int)); int *n = raw; *n = 42; ——malloc 交回一個 void *,你把它轉成 int *,之後才能解參考。當它還是 void * 時,你不能做 *raw 或 raw + 1。

void * 可持有任何位址,但必須轉成具型別的指標才能使用。

void * 意指「指向某個未指定之物的指標」,這不同於空指標(「指向無物的指標」)。經由 void * 轉換會悄悄丟棄型別檢查,所以一次錯誤的轉換會把同樣的位元組重新詮釋成錯誤型別卻毫無警告——這是微妙臭蟲的真實來源。

又稱
generic pointeruntyped pointer通用指標