今天當我讀別人的代碼時,我看到類似void *func(void* i);
的東西,這個void*
分別代表函數名和變量類型是什麼意思?void *意味着什麼以及如何使用它?
另外,我們什麼時候需要使用這種指針以及如何使用它?
今天當我讀別人的代碼時,我看到類似void *func(void* i);
的東西,這個void*
分別代表函數名和變量類型是什麼意思?void *意味着什麼以及如何使用它?
另外,我們什麼時候需要使用這種指針以及如何使用它?
一個指向void
是一個 「通用」 指針類型。 A void *
可以轉換爲任何其他指針類型而無需顯式強制轉換。你不能取消引用void *
或做指針運算;您必須首先將其轉換爲指向完整數據類型的指針。
它用於需要能夠在同一代碼中使用不同指針類型的地方。一種常用列舉的例子是庫函數qsort
:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base
是一個數組的地址,nmemb
是陣列中元件的數量,size
是各元件的尺寸,並且compar
是一個指向函數來比較數組中的兩個元素。它被稱爲像這樣:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
陣列表達式iArr
,dArr
,並lArr
被隱式地從數組類型轉換爲指針類型的函數調用,並且每個被隱式地從「指針轉換爲int
/double
/long
「到」指向void
的指針「。
比較功能將類似於:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
通過接受void *
,qsort
可以與任何類型的數組。
使用void *
的缺點是您將類型安全性置於窗外並轉向迎面而來的交通。沒有什麼來保護你使用了錯誤的比較例程是:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt
期待它的參數是指向int
S,但實際上是與double
s工作。編譯時無法解決這個問題;你只會結束一個錯誤排序的數組。
實際上不能保證'void *'可以被轉換爲函數指針。但對於數據指針而言,你所說的是成立的。 – Vatine 2016-07-12 10:52:40
void*
是'指向內存的指針,沒有假設存儲了哪種類型'。 可以使用,例如,如果你想傳遞一個參數來運作,這種說法有幾種類型和功能,您將處理每種類型。
之前函數名的空白意味着它不返回任何東西。只是做一些東西。另一方面VOID作爲參數使它成爲通用函數,可以接受任何類型的參數。但是你必須提供這個參數的大小。
'void'和'void *'之間有區別。查看其他答案 – Aftnix 2012-07-24 08:24:05
該函數接受一個指向任意類型的指針並返回一個。
你可以看看這篇關於指針http://www.cplusplus.com/doc/tutorial/pointers/的文章,並閱讀章節:void pointers。
這也適用於C語言。
void類型的指針是一種特殊類型的指針。在C++中,void 表示缺少類型,所以void指針指向的是 指向沒有類型(因此也有未確定的長度和未確定的取消引用屬性)的值。
這允許void指針指向任何數據類型,從整數 值或float到字符串。但作爲交換,他們有一個很大的限制:它們指向的數據不能直接取消引用(這是合乎邏輯的,因爲我們沒有類型來取消引用 ),因此我們將始終必須在 空隙指針指向一個具體 數據類型解引用它之前的一些其他指針類型。
使用void *表示該函數可以接受一個不需要是特定類型的指針。 例如,在插座的功能,你必須
send(void * pData, int nLength)
這意味着你可以把它在很多方面,例如
char * data = "blah";
send(data, strlen(data));
POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));
這與其他語言的泛型非常相似,但沒有類型檢查,對吧? – 2016-08-25 14:05:06
我想它會是相似的,但是因爲沒有類型檢查,犯錯可能會導致非常奇怪的結果或導致程序徹底崩潰。 – TheSteve 2016-08-28 23:58:37
一個void*
是一個指針,但它指向的類型是未指定的。當你將一個void指針傳遞給一個函數時,你需要知道它的類型是什麼,才能在函數中稍後將它轉換回正確的類型來使用它。您將在pthreads
中看到示例,該示例使用的函數與您的示例中用作線程函數的原型完全相同。然後,您可以使用void*
參數作爲指針到您選擇的一個通用的數據類型,然後將它轉換回該類型的線程函數中使用。在使用void指針時需要小心,因爲除非你回到它的真正類型的指針,否則你可能會遇到各種各樣的問題。
C11標準(n1570)§6.2.2.3AL1 P55表示:
一個指向
void
可轉化爲或者從一個指針到任何對象 類型。指向任何對象類型的指針都可以被轉換爲指向void的指針並返回;結果應與原始指針 相等。
你可以使用這個通用指針來存儲指向任何對象類型的指針,但是你不能對它使用通常的算術運算,而且你不能遵守它。
這意味着指針你可以使用這個鏈接來獲取有關指針更多信息 http://www.cprogramming.com/tutorial/c/lesson6.html
C是在這方面顯着。可以說 虛空就是虛無 void *就是一切(可以是everyhing)
它只是這個微小的*而已。
雷內指出了。 void *是指向某個位置的指針。什麼是如何「解釋」是留給用戶的。
這是在C中使用不透明類型的唯一方法。非常突出的例子可以在例如glib或通用數據結構庫中找到。在「C接口和實現」中對它進行了非常詳細的處理。
我建議你閱讀完整章節,並嘗試理解指向「獲取它」的概念。
void指針被稱爲泛型指針。我想用一個示例pthread場景來解釋。
線程函數將有原型
void *(*start_routine)(void*)
的並行線程API設計者考慮的參數和返回線程函數的值。如果這些東西是通用的,我們可以在作爲參數發送時將類型轉換爲void *。同樣的返回值可以從void *中檢索(但是我從來沒有使用線程函數的返回值)。
void *PrintHello(void *threadid)
{
long tid;
// ***Arg sent in main is retrieved ***
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
//*** t will be type cast to void* and send as argument.
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
你在用什麼C書?你在要求整個章節的更好的部分。 – cnicutar 2012-07-24 08:16:03
看看http://stackoverflow.com/questions/692564/concept-of-void-pointer-in-c-programming – WDan 2012-07-24 08:21:00
它的回答之前:http://stackoverflow.com/questions/1043034/what-does -void-mean-in-cc-and-c and here: http://stackoverflow.com/questions/7324860/using-void-in-c – d33pika 2012-07-24 08:21:17