My professor defined this in the .h file
void list_map(INTLIST* list, void (*f)(void *)); /*Applies a function to each element of the list */
I wrote the function like this:
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)
}
}
}
I call it in main like this:
list_map(aList[i], (void*)list_sort);
In windows environment, no complaints, but I have to run this in a Linux environment. I’m using a makefile to compile all of the code and I get this warning and error:
*c++ -O2 -c main.c
main.c: In function ‘int main(int, char**)’:
main.c:53: warning: deprecated conversion from string constant to ‘char*’
main.c:123: error: invalid conversion from ‘void ()(INTLIST)’ to ‘void ()(void)’
main.c:123: error: initializing argument 2 of ‘void list_map(INTLIST*, void ()(void))’
make: *** [main.o] Error 1*
Can somebody help with the error first and then maybe with the warning?
Edit Portion:
Someone asked for the list_sort function, here it is:
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;
}
}
First: why are you compiling C code as C++?. Please compile it with a C compiler.
The prototype of
list_sort()is:and
list_map()has the prototype:This means that the second argument to
list_map()is a function that takes avoid *argument, and returnsvoid(nothing).Now, the C standard guarantees that a conversion of any object pointer to
void *and back is OK, so given:this is OK:
Note that,
list_sort()could have been declared as:In fact, since your professor is using
void *in some places, he wants to extend your lists to be of a generic type at some point.Anyway, you can pass an
INTLIST *tolist_sort()orlist_sort_generic(), butlist_sort_generic()can be passed any object pointer, whereaslist_sort()can only be passedINTLIST *(or avoid *which was converted from anINTLIST *).Even though
list_sort()can take avoid *, the signature oflist_sort()is not:So, the function types of
list_sort()andlist_sort_generic()are not the same, and cannot be interchanged.list_map()expects a function of the kind thatlist_sort_generic()is, but is getting a function of a different kind.Since you can’t change any prototypes, you need a cast. Now,
void *is a generic type in C, so you would think such a cast would work. But, as I said before, only object pointers can be converted tovoid *and back portably—not function pointer type. So, you need to castlist_sort()to the correct type when callinglist_map().That correct type is
void (*)(void *). This is a function returningvoidand taking avoid *.Hence, the call should be:
But, since the type of
list_sort()and the type expected bylist_map()for its second parameter are not the same, the cast may or may not work. Your professor has given you “not-so-nice” (i.e., wrong) prototypes. Either he should have gone all the way in declaring type-generic functions, or he should have kept everythingINTLIST *. By going half-way, he has introduced a complicated cast that shouldn’t have been there, and may not work. I am sure if you bring this to your professor’s attention, he will admit this oversight.Hope that helped.