6

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

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_ *)'
4

3 回答 3

6

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

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

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

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

指向 void 的指针可以转换为指向任何不完整或对象类型的指针或从指针转换。指向任何不完整或对象类型的指针可以转换为指向 void 的指针并再次返回;结果应与原始指针比较。

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

void *a = NULL;
int (*f)(int a, char *b) = NULL;
a = f;
f = a;

很容易推断这意味着以下内容也将起作用(毕竟,我们只是将“void*”替换为“struct foo*”,对吧?)

int (*f1)(void*, void*);
int (*f2)(struct foo*, struct foo*);
f1 = f2;

但是,这会产生您的警告,因为它没有像标准允许的那样尝试将指针类型分配给指向 void 的指针(反之亦然)。相反,它试图将 type 的值分配给 typeint (*)(struct foo*, struct foo*)的变量int (*)(void*, void*)

当然,您可以尝试使编译器对显式强制转换感到满意,这使编译器相信您必须知道自己在做什么。但是这样做,即使调用“不确定”行为,您也会失去获得这些警告的特权和安全性。

于 2012-05-06T19:31:27.813 回答
3

您的问题与您的代码不符。您的代码不会将结构指针作为 void 指针传递。它将一个函数指针作为另一个函数指针传递。函数指针不兼容,因此出现错误。

在需要 void 指针的地方传递结构指针是合法的,因为结构指针可以隐式转换为 void 指针。它不需要在表示上与 void 指针相同。(例如,有些机器的结构指针与 void 指针的大小不同。)

以此类推,考虑在预期为 long 时传递 int 的情况。这是合法的,因为存在隐式转换,但这并不意味着接受 int 的函数可以与接受 long 的函数互换。

于 2012-05-06T19:37:06.093 回答
0

您需要转换函数指针,因为您的函数原型与函数期望的不匹配:

typedef int (cmp_f)(void *, void *));
new_hash(..., ..., (cmp_f*)cmp_func_p);

当然 typedef 不是必需的,但它使你的代码比没有更可读(你通常只在不允许使用 typedef 的考试中不使用 typedef ;))

于 2012-05-06T19:30:22.187 回答