我可以将结构传递给一个带有void*的函数吗?

Lea*_*g C 6 c structure void-pointers data-structures

因为这是一个空*我应该能够传递任何类型的指针吗?为什么编译器会给我错误?

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;
  }
}
Run Code Online (Sandbox Code Playgroud)


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_ *)'
Run Code Online (Sandbox Code Playgroud)

Chr*_*ice 6

关键是让你的比较函数也采用void指针:

int comp_function(void *a, void *b){
  struct word *word1 = a;
  struct word *word2 = b;
  // Use word1 and word2 as before.
}
Run Code Online (Sandbox Code Playgroud)

附录,关于为什么编译器给你的警告:

引用我在这里找到的c99标准

指向void的指针可以转换为指向任何不完整或对象类型的指针.指向任何不完整或对象类型的指针可能会转换为指向void的指针并再次返回; 结果应该等于原始指针.

这意味着您可以拥有如下代码,编译器不会发出您所看到的警告:

void *a = NULL;
int (*f)(int a, char *b) = NULL;
a = f;
f = a;
Run Code Online (Sandbox Code Playgroud)

推测这意味着下面的内容也会起作用(毕竟,我们只是用"struct foo*"代替"void*",对吗?)

int (*f1)(void*, void*);
int (*f2)(struct foo*, struct foo*);
f1 = f2;
Run Code Online (Sandbox Code Playgroud)

但是,这会生成警告,因为它不会尝试将指针类型分配给指向void的指针(反之亦然),这是标准允许的.相反,它试图将类型的值赋给类型int (*)(struct foo*, struct foo*)的变量int (*)(void*, void*).

当然,您可以尝试使编译器对显式转换感到满意,这会使编译器相信您必须知道您正在做什么.但是这样做即使在调用"iffy"行为时也会失去获得这些警告的特权和安全性.