2010-01-25 81 views
1

我的教授这样定义在.h文件C编译器抱怨无效(*)

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:warning:从字符串常量到'char *'的过时的转换 main.c:123:错误:从'void()(INTLIST)'无效转换为'void()(空隙)” main.c中:123:错误:初始化的参数2 '空隙list_map(intList中*,空隙()(空隙))' 化妆:*** [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

'list_sort'是什么样的? – ezod 2010-01-25 02:30:32

+0

你可以改变list_sort函数,还是由prof指定的?如果它是固定的,似乎你已经处理了一个强硬的手。 – BobS 2010-01-25 04:19:59

回答

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 *,并且可以移植回—而不是函数指针类型。因此,致电list_map()时,您需要将list_sort()转换为正确的类型。

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

因此,调用应该是:

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

但,既然list_sort()的类型和list_map()其第二个参数期望的类型是不一样的,中投可能会或可能无法正常工作。你的教授给你“不太好”(即,错误)原型。要么他应该一直宣称类型泛型函数,要么他应该保留所有的东西INTLIST *。通过走中途,他引入了一个本不应该在那里的复杂演员,并且可能无法工作。我相信,如果你将这个引入到你的教授的关注中,他会承认这个疏忽。

希望有帮助。

+0

这些是我正在寻找写得很好的细节的东西,我可能不太在乎我希望了解问题的答案,以充分利用和学习语言。 Alok +1加上接受这个彻底的答案。你可以写一本书,我会买它。 – oJM86o 2010-01-25 16:30:49

2

如果你投你的回调到适当的功能类型?

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

“如果你得到的不是鸭子,直到你得到你想要的东西” - 我很抱歉,但这是一个给初学者的不好答案... – LiraNuna 2010-01-25 04:14:56

+1

@LiraNuna:这是一项功课,他不能改变list_map的原型。我怕他的老师想让他揍它,直到它像鸭子一样嘎嘎叫。 – zneak 2010-01-25 04:26:44

+0

这会使警告消失,但是现在当函数在list_map()中调用时,它会调用未定义的行为。 – Christoph 2010-01-25 10:46:47

2

好,

void list_sort(INTLIST* list) 

有错误签名的

void list_map(INTLIST* list, void (*f)(void *)) 
+0

正确的答案。 – 2010-01-25 02:47:05

+0

一直试图跟随这个东西,因为我也在学习C ...但我想我的问题是它看起来像list_map的无效(* f))(void *)是只是一个函数指针?他可以改变void list_sort成为什么? void list_sort(void * list)? – JonH 2010-01-25 02:53:23

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 *)) 

希望这有助于 最好的问候, 汤姆它的工作。

+0

无法更改教授定义的list_map原型,我们不允许更改这些原型。 – oJM86o 2010-01-25 03:01:00

2

list_sort()一个简单的演员阵容足以使警告消失,但它不足以使实际工作:

的C-标准并不能保证一个INTLIST *void *具有兼容表示,即void (INTLIST *)void (void *)是不同的,不兼容的类型。当list_map()调用list_sort()通过你的void (*f)(void *)说法,C99部分6.3.2.3,§8适用:

If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

要使它符合标准,你必须写一个包装功能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); 

命名方案能够实现,是一个严重的跆拳道 - 如果功能不整理清单,称之为list_sort_step()list_select_head()什么的,但请不要list_sort()

+0

list_map是一个映射函数,它只需要一个函数指针指向list_sort(),只要您调用list_map即可排序整个列表,即使list_sort正在逐个执行此元素。我知道这看起来很奇怪,但是教授们是真正无法编码的陌生人。 – oJM86o 2010-01-25 16:25:48

+0

+1也是一个很好的解释。 – oJM86o 2010-01-25 16:32:21