我的教授在.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;
}
}
答案 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 *))
希望这有帮助, 最好的祝福, 汤姆。