因为这是一个空*我应该能够传递任何类型的指针吗?为什么编译器会给我错误?
int cmp_func(void *, void *));
typedef struct word_{
char key[WORD_SIZE];
int *frequency;
} word;
Phash_table new_hash(int size, int (*hash_func)(char *), int (*cmp_func)(void *\
, void *));
int comp_function(struct word_ *word1,struct word_ *word2){
if( word1->frequency < word2->frequency){
return -1;
}
if(word1->frequency < word2->frequency){
return 1;
}
if(word1->frequency == word2->frequency){
return 0;
}
}
project4_functions.c:47:3: warning: passing argument 3 of 'new_hash' from incompatible pointer type [enabled by default]
hash.h:38:13: note: expected 'int (*)(void *, void *)' but argument is of type 'int (*)(struct word_ *, struct word_ *)'
答案 0 :(得分:6)
关键是让你的比较函数也采用无效指针:
int comp_function(void *a, void *b){
struct word *word1 = a;
struct word *word2 = b;
// Use word1 and word2 as before.
}
附录,关于为什么编译器会给你警告:
引用我发现的here
的c99标准指向void的指针可以转换为指向任何不完整或对象的指针 类型。指向任何不完整或对象类型的指针可以转换为指向void的指针 又回来了;结果应该等于原始指针。
这意味着你可以拥有如下代码,编译器不会发出你所看到的警告:
void *a = NULL;
int (*f)(int a, char *b) = NULL;
a = f;
f = a;
很有可能推断出这意味着以下内容也会起作用(毕竟,我们只是用“struct foo *”代替“void *”,对吗?)
int (*f1)(void*, void*);
int (*f2)(struct foo*, struct foo*);
f1 = f2;
然而,这会产生警告,因为不尝试将指针类型指定给指向void的指针(反之亦然),这是标准所允许的。相反,它尝试将类型int (*)(struct foo*, struct foo*)
的值分配给int (*)(void*, void*)
类型的变量。
当然,可以尝试使编译器对显式转换感到满意,这使编译器相信您必须知道自己在做什么。但是这样做即使在调用“iffy”行为时也会失去获得这些警告的特权和安全性。
答案 1 :(得分:3)
您的问题与您的代码不符。您的代码不会将结构指针作为void指针传递。它将一个函数指针作为另一个传递。函数指针不兼容,因此错误。
传递结构指针是合法的,因为结构指针可以隐式地转换到void指针。它不需要在表示上与void指针相同。 (例如,有些机器的结构指针与void指针的大小不同。)
通过类比考虑在期望long时传递int的情况。这是合法的,因为存在隐式转换,但这并不意味着接受int的函数可以与接受long的函数互换。
答案 2 :(得分:0)
您需要转换函数指针,因为函数原型与函数期望的函数原型不匹配:
typedef int (cmp_f)(void *, void *));
new_hash(..., ..., (cmp_f*)cmp_func_p);
当然,typedef不是必需的,但是它使你的代码比没有你的代码更具可读性(你通常只在不允许为此目的使用typedef的考试中没有那个typedef的情况下执行;)