2010-11-09 63 views
1

我有以下代碼:警告關於C函數指針

#include <stdlib.h> 
#include <stdio.h> 

typedef void (*func_t)(void * data); 

void func2(int * arg, func_t free_func) { 
     free_func(arg); 
} 

void func(int * a) { 
     printf("%d\n", *a); 
} 

int main(int argc, char ** argv) { 
     int a = 4; 
     func2(&a, func); 
     return 0; 
} 

編譯這給了我 警告:傳遞`FUNC2' 的ARG 2從兼容的指針類型

這是爲什麼? int指針不應該與void指針兼容嗎?

回答

1

你也可以這樣做:

free_func((int *)arg); 

不過,請注意轉換一個void *至T *(在這種情況下int *) 是不安全由於使用T *的副作用,實際上並不指向T

例如

char i = 0; 
char j = 0;  
char* p = &i; 
void* q = p; 
int* pp = q; /* unsafe, legal C, not C++ */ 
printf("%d %d\n",i,j); 
*pp = -1; /* overwrite memory starting at &i */ 
printf("%d %d\n",i,j); 
3

你可以將類型轉換並不意味着編譯器會很樂意爲你做。

在這種情況下,函數指針定義不匹配。 C不會假定聲明爲int*的函數會很高興,而不是void*,儘管這兩種類型之間的轉換是隱含的。 C是如何處理函數指針的,這是一個微妙的問題。

如果你想這沒有警告的工作,你將不得不投,像這樣:

func2(%a, (func_t)func); 
+0

好的,所以類型之間的轉換是隱含的,但涉及這些類型的函數簽名之間不是隱含的?反直覺。 – 2010-11-09 20:52:10

+0

這就是它的要義。是的,我從來沒有說C很直觀。 ;) – cdhowie 2010-11-09 20:53:07

+0

我也不明白爲什麼我以前從來沒有遇到過......可能與VC++沒有抱怨它有關。 – 2010-11-09 20:54:39

1

指針類型只有當它們的基本類型兼容兼容,intvoid不兼容。

此外,int和void指針可能具有不同的大小和表示形式。

0

如果更改FUNC的聲明/定義

void func(void * a) { 
     printf("%d\n", *(int*)a); 
} 

一切都按你所期望的。

+0

隊長明顯? – 2010-11-09 22:55:17