C编译器抱怨void(*)

时间:2010-01-25 02:25:03

标签: c

我的教授在.h文件中定义了这个

void list_map(INTLIST* list, void (*f)(void *)); /*Applies a function to each element of the list */

我写了这样的函数:

 void list_map(INTLIST* list, void (*f)(void *))
  {
   INTLIST* pTemp=NULL;

   if (list == NULL)
    {
      //list is empty
    }
   else
      {
       for(pTemp=list; pTemp->next!=NULL; pTemp=pTemp->next)
          {
             f(pTemp); //f is a function pointer we call list map from main like list_map(lst, list_sort)
          }    
      }
  }

我这样称呼它是主要的:

  list_map(aList[i], (void*)list_sort);

在Windows环境中,没有任何抱怨,但我必须在Linux环境中运行它。我正在使用makefile编译所有代码,我收到此警告和错误:

* c ++ -O2 -c main.c main.c:在函数'int main(int,char **)'中: main.c:53:警告:不推荐将字符串常量转换为'char *' main.c:123:错误:从'void()(INTLIST )'到'void()(void )'无效转换 main.c:123:错误:初始化'void list_map的参数2(INTLIST *,void()(void ))' make:*** [main.o]错误1 *

有人可以先帮助解决错误,然后再发出警告吗?

编辑部分:

有人要求list_sort函数,这里是:

 void list_sort(INTLIST* list)
 {
  INTLIST* pTemp=NULL;
  INTLIST* pTemp2=NULL;

  pTemp=list;          //temp pointers to compare node values
  pTemp2=list;

  if (pTemp->next !=NULL)     //move to second node
   {
      pTemp2=pTemp2->next;
   }

  while(pTemp2 != NULL)
   {   
       //we implement a selection sort 
       //check if incoming node->datum with each node in the list
       //swap values if <
      if (pTemp2->datum < pTemp->datum)
         {
         //swap the values
         int temp = pTemp->datum;
         pTemp->datum = pTemp2->datum;
         pTemp2->datum = temp;
         }
         //advance the pointer
      pTemp2=pTemp2->next;
   }
 }

5 个答案:

答案 0 :(得分:2)

如果你将回调转换为正确的函数类型?

list_map(aList[i], (void (*)(void*))list_sort);

答案 1 :(得分:2)

好吧,

void list_sort(INTLIST* list)

有错误的签名作为

的第二个参数传递
void list_map(INTLIST* list, void (*f)(void *))

答案 2 :(得分:2)

list_sort()的简单演员足以让警告消失,但这还不足以让它真正起作用:

C标准不保证INTLIST *void *具有兼容的表示形式,即void (INTLIST *)void (void *)是不同的,不兼容的类型。当list_map()通过list_sort()参数调用void (*f)(void *)时,C99第6.3.2.3节,§8适用:

  

如果使用转换的指针进行调用   类型不是的函数   与指向类型兼容,   行为未定义。

要使其符合标准,您必须为list_sort()编写包装函数:

void list_sort_wrapper(void *list)
{
    list_sort(list);
}

并将其用作通话的参数:

list_map(aList[i], list_sort_wrapper);

此外,如果正确实现list_sort()(未检查算法),它已经遍历列表,即为每个节点调用它根本没有任何意义。

修改

好的,list_sort()实际上并没有对整个列表进行排序 - 可以通过

来实现
list_map(list, list_sort_wrapper);

命名方案是严重的WTF - 如果函数没有对列表进行排序,请将其称为list_sort_step()list_select_head()或其他内容,但请不要list_sort()

答案 3 :(得分:1)

首先:为什么要将C代码编译为C ++?。请用C编译器编译它。

list_sort()的原型是:

void list_sort(INTLIST* list);

list_map()有原型:

void list_map(INTLIST* list, void (*f)(void *));

这意味着list_map()的第二个参数是一个带有void *参数的函数,并返回void(无)。

现在,C标准保证将任何对象指针转换为void *并返回正常,因此给出:

INTLIST *l;
/* make l point to a valid INTLIST */
void *pl = l;

这没关系:

list_sort(pl);

请注意,list_sort()可能已声明为:

void list_sort_generic(void *l);

事实上,由于您的教授在某些地方使用void *,他希望在某些时候将您的列表扩展为通用类型。

无论如何,您可以将INTLIST *传递给list_sort()list_sort_generic(),但list_sort_generic()可以传递任何对象指针,而list_sort()只能传递INTLIST *(或从void *转换而来的INTLIST *

即使list_sort()可以使用void *list_sort()的签名也不是:

void list_sort(void *l);

因此,list_sort()list_sort_generic()的函数类型不相同,并且不能互换。 list_map()期望list_sort_generic()的函数类型,但是它具有不同类型的函数。

由于您无法更改任何原型,因此需要进行强制转换。现在,void *是C中的泛型类型,所以你会认为这样的演员会起作用。但是,正如我之前所说,只有对象指针可以转换为void *并且可以转换为portable-not函数指针类型。因此,您需要在调用list_sort()时将list_map()强制转换为正确的类型。

正确的类型是void (*)(void *)。这是一个返回void并取void *

的函数

因此,呼叫应该是:

list_map(aList[i], (void (*)(void *))list_sort);

但是,由于list_sort()的类型和list_map()期望的第二个参数的类型不相同,因此强制转换可能有效,也可能无效。你的教授已经给你“不那么好”(即错误的)原型。要么他应该在声明类型泛型函数时一直走,要么他应该保留所有INTLIST *。通过中途,他引入了一个不应该存在的复杂演员,并且可能无法奏效。我相信如果你把它带到教授的注意力,他会承认这种疏忽。

希望有所帮助。

答案 4 :(得分:0)

在您的函数list_sort中,参数为INTLIST *list

list_map(aList[i], (void*)list_sort);

通过查看标题,函数原型是一个函数指针,其参数类型为void *

void list_map(INTLIST* list, void (*f)(void *))
                                      ^^^^^^^^

函数指针*f必须匹配签名,因此冲突和编译器生成的警告。由于*f指向list_sort,因此方法签名不匹配。

如果你的函数原型改为

,它会工作
void list_map(INTLIST* list, void (*f)(INTLIST *))

希望这有帮助, 最好的祝福, 汤姆。