2015-10-15 71 views
3

我有類似的「通用」過程,如qsort,它有一個void指針(指向一個數組),還有一個函數指針參數。這個函數應該適用於任何類型的數組。如何遍歷數組參數作爲void指針

例子:

void do_something(void * array, int count, int size, void (*test)(const void*)){ 
    int i; 
    for(i=0; i<count; i++){ 
     test(array + (index * size)); 
    } 
} 

然而,這給了我下面的警告(GCC test.c的-pedantic-錯誤):

error: pointer of type ‘void *’ used in arithmetic [-Wpedantic] 

而且一些研究,我發現後,這是一個不好的做法,使用這樣的void指針。 (例如Pointer arithmetic for void pointer in C

那麼標準庫如何爲qsort這樣的東西做這種東西?縱觀這段代碼:(http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c),我看到以下內容:

void 
_quicksort (void *const pbase, size_t total_elems, size_t size, 
     __compar_fn_t cmp) 
{ 
    register char *base_ptr = (char *) pbase; 
    .... 
    char *lo = base_ptr; 
    char *hi = &lo[size * (total_elems - 1)]; 
    ... 
} 

難道他們鑄造(字符*),而不管實際類型的?

+1

那麼使用_char_不會比使用_void_ :)更多類型關於char的關節做這項工作(使用_size_步驟移動)。 – hexasoft

回答

3

我問了相似的問題Can I do arithmetic on void * pointers in C?

Void *運算未定義。將1添加到void指針是什麼意思?大多數編譯器(如果他們允許的話)將它視爲sizeof(char)遞增(「下一個字節」),但警告你。

所以,做正確的事情是明確讓它做你想要什麼 - >鑄爲char *和增量是

+0

謝謝。我也很好奇爲什麼要轉換爲字符,並且我在鏈接中找到了答案:「字符類型非常方便,因爲它具有1字節的定義大小。」 – Aaron

1

不完整數據類型void上的指針算術是不合法的,這就是編譯器所抱怨的。

正如你在_quicksort()中看到的那樣,指針是一個常量,所以你不能修改指針指向的地址。 void指針上沒有發生關閉操作。

1

製作的指針空洞只是帶走了指針的「背景」 - 也就是說,系統應該如何看待指針或指針所在的位置。

因此,編譯器不對void指針進行算術運算。爲了做指針運算,編譯器需要知道指針的類型,以便它可以進行正確的轉換(如果指針保存了一個int,它將不會執行32位的相加,或者至少它會讓你知道一些事情已經過去了!)。

由於這個原因,唯一的方法就是將指針指向某個東西,然後去做 - 我不會推薦它,除非您非常清楚指針正在獲取什麼。無效指針是非常黑暗的編程。

+0

但是還有沒有其他的方法來做到這一點,而沒有void指針? – Aaron

+0

@Aaron我相信做事最好的方式是隨時分配類型。這真的取決於你想要達到的目標。 – GrGom

+0

在這種情況下這是不可能的。 – Aaron