Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Passing function pointer as argument to a function???

Reply
Thread Tools

Passing function pointer as argument to a function???

 
 
Charles Sullivan
Guest
Posts: n/a
 
      09-19-2005
The library function 'qsort' is declared thus:
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));

If in my code I write:
int cmp_fcn(...);
int (*fcmp)() = &cmp_fcn;
qsort(..., fcmp);

then everything works. But if instead I code qsort as:

qsort(..., &cmp_fcn);

the compiler complains about incompatible pointer type.

Can someone help me understand exactly what I'm passing to
the qsort function in the "bad" code other than the pointer
to a function and/or how this differs from the "good" code?

How could the qsort statement be written directly without
the use of an intermediary like 'fcmp' ?

Thanks for your help.

Regards,
Charles Sullivan







 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      09-19-2005


Charles Sullivan wrote On 09/19/05 11:05,:
> The library function 'qsort' is declared thus:
> void qsort(void *base, size_t nmemb, size_t size,
> int(*compar)(const void *, const void *));
>
> If in my code I write:
> int cmp_fcn(...);
> int (*fcmp)() = &cmp_fcn;


FYI: The `&' is harmless but unnecessary, both here
and below.

> qsort(..., fcmp);
>
> then everything works. But if instead I code qsort as:
>
> qsort(..., &cmp_fcn);
>
> the compiler complains about incompatible pointer type.
>
> Can someone help me understand exactly what I'm passing to
> the qsort function in the "bad" code other than the pointer
> to a function and/or how this differs from the "good" code?


Well, let's see: The compiler says that cmp_fcn() is
of the wrong type. Might this mean that there's something
wrong with cmp_fcn()? It seems a possibility, doesn't it?
However, this is all just speculation on my part, since you
haven't (hint, hint) shown what cmp_fcn() looks like ...

> How could the qsort statement be written directly without
> the use of an intermediary like 'fcmp' ?


By writing a cmp_fcn() that matches what qsort()
requires.

--


 
Reply With Quote
 
 
 
 
Kenneth Brody
Guest
Posts: n/a
 
      09-19-2005
Charles Sullivan wrote:
>
> The library function 'qsort' is declared thus:
> void qsort(void *base, size_t nmemb, size_t size,
> int(*compar)(const void *, const void *));
>
> If in my code I write:
> int cmp_fcn(...);
> int (*fcmp)() = &cmp_fcn;
> qsort(..., fcmp);
>
> then everything works. But if instead I code qsort as:
>
> qsort(..., &cmp_fcn);
>
> the compiler complains about incompatible pointer type.


qsort is expecting a pointer to a function which returns an int and
gets passed two const void * parameters. However, you are passing
it a pointer to a function which returns int and gets passed a
variable number of unknown parameters.

> Can someone help me understand exactly what I'm passing to
> the qsort function in the "bad" code other than the pointer
> to a function and/or how this differs from the "good" code?


When using the intermediate fcmp variable, you are passing it
a function which returns int, and whose parameters are left
unprototyped.

> How could the qsort statement be written directly without
> the use of an intermediary like 'fcmp' ?


If cmp_fcn() does, in fact, take two const void * parameters, then
say so by changing:

int cmp_fcn(...);
to
int cmp_fcn(const void *,const void *);

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <private.php?do=newpm&u=>

 
Reply With Quote
 
Martin Ambuhl
Guest
Posts: n/a
 
      09-19-2005
Charles Sullivan wrote:
> The library function 'qsort' is declared thus:
> void qsort(void *base, size_t nmemb, size_t size,
> int(*compar)(const void *, const void *));
>
> If in my code I write:
> int cmp_fcn(...);
> int (*fcmp)() = &cmp_fcn;
> qsort(..., fcmp);
>
> then everything works. But if instead I code qsort as:
>
> qsort(..., &cmp_fcn);
>
> the compiler complains about incompatible pointer type.
>
> Can someone help me understand exactly what I'm passing to
> the qsort function in the "bad" code other than the pointer
> to a function and/or how this differs from the "good" code?
>
> How could the qsort statement be written directly without
> the use of an intermediary like 'fcmp' ?


Exactly as you use fcmp. To clarify:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

#define ASIZE 10

int cmp_fcn(const void *e1, const void *e2);

int main(void)
{
double asrc[ASIZE], awrk[ASIZE];
int (*fcmp) () = cmp_fcn;
size_t i;
srand(time(0));
printf(" example using cmp_fcn as argument\n");
for (i = 0; i < ASIZE; i++)
asrc[i] = rand() / (1. + RAND_MAX);
memcpy(awrk, asrc, sizeof asrc);
qsort(awrk, ASIZE, sizeof *awrk, cmp_fcn);
for (i = 0; i < ASIZE; i++)
printf("%lu: %f %f\n", (unsigned long) i, asrc[i], awrk[i]);
printf("\n");

printf(" example using fcmp as argument\n");
for (i = 0; i < ASIZE; i++)
asrc[i] = rand() / (1. + RAND_MAX);
memcpy(awrk, asrc, sizeof asrc);
qsort(awrk, ASIZE, sizeof *awrk, fcmp);
for (i = 0; i < ASIZE; i++)
printf("%lu: %f %f\n", (unsigned long) i, asrc[i], awrk[i]);
return 0;
}


int cmp_fcn(const void *e1, const void *e2)
{
const double *p1 = e1, *p2 = e2;
return (*p1 > *p2) ? 1 : (*p1 < *p2) ? -1 : 0;
}

example using cmp_fcn as argument
0: 0.563498 0.111813
1: 0.195851 0.195851
2: 0.111813 0.254336
3: 0.294201 0.294201
4: 0.318893 0.318893
5: 0.586812 0.511567
6: 0.724280 0.563498
7: 0.925669 0.586812
8: 0.511567 0.724280
9: 0.254336 0.925669

example using fcmp as argument
0: 0.887919 0.053615
1: 0.053615 0.134536
2: 0.471209 0.211441
3: 0.457827 0.240006
4: 0.640444 0.457827
5: 0.211441 0.471209
6: 0.240006 0.511690
7: 0.511690 0.640444
8: 0.699548 0.699548
9: 0.134536 0.887919
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-19-2005
Kenneth Brody <> writes:
> Charles Sullivan wrote:
>>
>> The library function 'qsort' is declared thus:
>> void qsort(void *base, size_t nmemb, size_t size,
>> int(*compar)(const void *, const void *));
>>
>> If in my code I write:
>> int cmp_fcn(...);
>> int (*fcmp)() = &cmp_fcn;
>> qsort(..., fcmp);
>>
>> then everything works. But if instead I code qsort as:
>>
>> qsort(..., &cmp_fcn);
>>
>> the compiler complains about incompatible pointer type.

>
> qsort is expecting a pointer to a function which returns an int and
> gets passed two const void * parameters. However, you are passing
> it a pointer to a function which returns int and gets passed a
> variable number of unknown parameters.


No, he's not. A function that takes a variable number of arguments
must have at least one named argument before the "...". Note also his
use of "..." in the call to qsort. The ellipsis isn't being used as C
syntax; it's just an ellipsis.

He's just not showing us exactly what he's doing -- which means we
can't guess what the problem is.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Emmanuel Delahaye
Guest
Posts: n/a
 
      09-19-2005
Charles Sullivan wrote on 19/09/05 :
> The library function 'qsort' is declared thus:
> void qsort(void *base, size_t nmemb, size_t size,
> int(*compar)(const void *, const void *));
>
> If in my code I write:
> int cmp_fcn(...);
> int (*fcmp)() = &cmp_fcn;


You don't need the &.

> qsort(..., fcmp);
>
> then everything works. But if instead I code qsort as:
>
> qsort(..., &cmp_fcn);


You don't need the &.

qsort(..., cmp_fcn);

> the compiler complains about incompatible pointer type.


How exactly is cmp_fcn() prototyped ?

> Can someone help me understand exactly what I'm passing to
> the qsort function in the "bad" code other than the pointer
> to a function and/or how this differs from the "good" code?


The compare function must exactly have this prototype :

int compare_function (void const *, void const *);

> How could the qsort statement be written directly without
> the use of an intermediary like 'fcmp' ?


Using the correct prototype for the compare function. We all do that
every day... (well, sort of)

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"


 
Reply With Quote
 
Charles Sullivan
Guest
Posts: n/a
 
      09-19-2005
On Mon, 19 Sep 2005 20:12:17 +0000, Keith Thompson wrote:

> Kenneth Brody <> writes:
>> Charles Sullivan wrote:
>>>
>>> The library function 'qsort' is declared thus:
>>> void qsort(void *base, size_t nmemb, size_t size,
>>> int(*compar)(const void *, const void *));
>>>
>>> If in my code I write:
>>> int cmp_fcn(...);
>>> int (*fcmp)() = &cmp_fcn;
>>> qsort(..., fcmp);
>>>
>>> then everything works. But if instead I code qsort as:
>>>
>>> qsort(..., &cmp_fcn);
>>>
>>> the compiler complains about incompatible pointer type.

>>
>> qsort is expecting a pointer to a function which returns an int and
>> gets passed two const void * parameters. However, you are passing
>> it a pointer to a function which returns int and gets passed a
>> variable number of unknown parameters.

>
> No, he's not. A function that takes a variable number of arguments
> must have at least one named argument before the "...". Note also his
> use of "..." in the call to qsort. The ellipsis isn't being used as C
> syntax; it's just an ellipsis.
>
> He's just not showing us exactly what he's doing -- which means we
> can't guess what the problem is.


Mea culpa. I had forgotten about the C syntax and used "..." to
represent stuff I _thought_ irrelevant to the question.

Here's an example which illustrates the way I've been using
qsort:
-------------------------------------
#include <stdio.h>
#include <stdlib.h>

int val[] = { 3, 2, 1, 4, 5 };

int cmp_fcn ( int *one, int *two )
{
return (*one < *two) ? -1 :
(*one > *two) ? 1 : 0;
}

int main ( void )
{
int (*fcmp)() = &cmp_fcn;
qsort((void *)val, 5, sizeof(int), fcmp);
printf("%d %d %d %d %d\n",
val[0], val[1], val[2], val[3], val[4]);
return 0;
}
-----------------------------------

Regards,
Charles Sullivan



 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      09-20-2005
On Mon, 19 Sep 2005 23:36:43 GMT, Charles Sullivan
<> wrote:

>On Mon, 19 Sep 2005 20:12:17 +0000, Keith Thompson wrote:
>
>> Kenneth Brody <> writes:
>>> Charles Sullivan wrote:
>>>>
>>>> The library function 'qsort' is declared thus:
>>>> void qsort(void *base, size_t nmemb, size_t size,
>>>> int(*compar)(const void *, const void *));
>>>>
>>>> If in my code I write:
>>>> int cmp_fcn(...);
>>>> int (*fcmp)() = &cmp_fcn;
>>>> qsort(..., fcmp);
>>>>
>>>> then everything works. But if instead I code qsort as:
>>>>
>>>> qsort(..., &cmp_fcn);
>>>>
>>>> the compiler complains about incompatible pointer type.
>>>
>>> qsort is expecting a pointer to a function which returns an int and
>>> gets passed two const void * parameters. However, you are passing
>>> it a pointer to a function which returns int and gets passed a
>>> variable number of unknown parameters.

>>
>> No, he's not. A function that takes a variable number of arguments
>> must have at least one named argument before the "...". Note also his
>> use of "..." in the call to qsort. The ellipsis isn't being used as C
>> syntax; it's just an ellipsis.
>>
>> He's just not showing us exactly what he's doing -- which means we
>> can't guess what the problem is.

>
>Mea culpa. I had forgotten about the C syntax and used "..." to
>represent stuff I _thought_ irrelevant to the question.
>
>Here's an example which illustrates the way I've been using
>qsort:
>-------------------------------------
>#include <stdio.h>
>#include <stdlib.h>
>
>int val[] = { 3, 2, 1, 4, 5 };
>
>int cmp_fcn ( int *one, int *two )


cmp_fcn has the wrong type for a function whose address is to be
passed to qsort. The two parameters need to be const void *.

>{
> return (*one < *two) ? -1 :
> (*one > *two) ? 1 : 0;
>}
>
>int main ( void )
>{
> int (*fcmp)() = &cmp_fcn;


fcmp has the wrong type for a pointer to be used as an argument to
qsort. fcmp is a pointer to function (returning int) about whose
arguments (type and quantity) absolutely nothing is known. qsort
needs a pointer to function returning int about whose arguments
everything is known.

> qsort((void *)val, 5, sizeof(int), fcmp);
> printf("%d %d %d %d %d\n",
> val[0], val[1], val[2], val[3], val[4]);
> return 0;
>}


Try increasing the warning level on your compiler.


<<Remove the del for email>>
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-20-2005
Charles Sullivan <> writes:
> On Mon, 19 Sep 2005 20:12:17 +0000, Keith Thompson wrote:
>> Kenneth Brody <> writes:
>>> Charles Sullivan wrote:
>>>> The library function 'qsort' is declared thus:
>>>> void qsort(void *base, size_t nmemb, size_t size,
>>>> int(*compar)(const void *, const void *));
>>>>
>>>> If in my code I write:
>>>> int cmp_fcn(...);
>>>> int (*fcmp)() = &cmp_fcn;
>>>> qsort(..., fcmp);
>>>>
>>>> then everything works. But if instead I code qsort as:
>>>>
>>>> qsort(..., &cmp_fcn);
>>>>
>>>> the compiler complains about incompatible pointer type.
>>>
>>> qsort is expecting a pointer to a function which returns an int and
>>> gets passed two const void * parameters. However, you are passing
>>> it a pointer to a function which returns int and gets passed a
>>> variable number of unknown parameters.

>>
>> No, he's not. A function that takes a variable number of arguments
>> must have at least one named argument before the "...". Note also his
>> use of "..." in the call to qsort. The ellipsis isn't being used as C
>> syntax; it's just an ellipsis.
>>
>> He's just not showing us exactly what he's doing -- which means we
>> can't guess what the problem is.

>
> Mea culpa. I had forgotten about the C syntax and used "..." to
> represent stuff I _thought_ irrelevant to the question.
>
> Here's an example which illustrates the way I've been using
> qsort:
> -------------------------------------
> #include <stdio.h>
> #include <stdlib.h>
>
> int val[] = { 3, 2, 1, 4, 5 };
>
> int cmp_fcn ( int *one, int *two )
> {
> return (*one < *two) ? -1 :
> (*one > *two) ? 1 : 0;
> }
>
> int main ( void )
> {
> int (*fcmp)() = &cmp_fcn;
> qsort((void *)val, 5, sizeof(int), fcmp);
> printf("%d %d %d %d %d\n",
> val[0], val[1], val[2], val[3], val[4]);
> return 0;
> }
> -----------------------------------


Yup, the stuff you deleted was exactly what's relevant to the problem.

The "compar" argument to qsort must be a pointer to a function taking
two arguments of type "const void *" and returning a result of type
int. You're providing a pointer to a function taking two arguments of
type int* and returning a result of type int. The types are
incompatible.

You need to declare your cmp_fcn() function as:

int cmp_fcn(const void *one, const void *2);

Here's a modified version of your program:

#include <stdio.h>
#include <stdlib.h>

int val[] = { 3, 2, 1, 4, 5 };

int cmp_fcn ( const void *one, const void *two )
{
return (*(int*)one < *(int*)two) ? -1 :
(*(int*)one > *(int*)two) ? 1 : 0;
}

int main ( void )
{
qsort(val,
sizeof val / sizeof val[0],
sizeof val[0],
cmp_fcn);
printf("%d %d %d %d %d\n",
val[0], val[1], val[2], val[3], val[4]);
return 0;
}

Note that I've changed all four arguments to qsort().

For the first argument, I dropped the cast to void*. As long as
qsort's prototype is visible (which it is, since you have the
"#include <stdlib.h>", the conversion is done implicitly.

For the second argument, I compute the size of the val array rather
than assuming it's 5. This lets you change the size without having
to modify the call.

Similarly, the third argument is "sizeof val[0]" rather than
"sizeof(int)", allowing you to change the type of the array without
changing the qsort call (though you would have to change the
cmp_fcn function).

Finally, I pass the name of the function directly to qsort() rather
than storing it in a variable. The name of a function is implicitly
converted to a pointer-to-function in most contexts. (The exceptions
are the argument to sizeof, which makes "sizeof func" illegal rather
than yielding the size of a function pointer, and the argument to a
unary "&" operator, which makes &func nearly equivalent to func.)

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Charles Sullivan
Guest
Posts: n/a
 
      09-20-2005
On Mon, 19 Sep 2005 17:44:30 -0700, Barry Schwarz wrote:

> On Mon, 19 Sep 2005 23:36:43 GMT, Charles Sullivan
> <> wrote:
>
>>On Mon, 19 Sep 2005 20:12:17 +0000, Keith Thompson wrote:
>>
>>> Kenneth Brody <> writes:
>>>> Charles Sullivan wrote:
>>>>>
>>>>> The library function 'qsort' is declared thus:
>>>>> void qsort(void *base, size_t nmemb, size_t size,
>>>>> int(*compar)(const void *, const void *));
>>>>>
>>>>> If in my code I write:
>>>>> int cmp_fcn(...);
>>>>> int (*fcmp)() = &cmp_fcn;
>>>>> qsort(..., fcmp);
>>>>>
>>>>> then everything works. But if instead I code qsort as:
>>>>>
>>>>> qsort(..., &cmp_fcn);
>>>>>
>>>>> the compiler complains about incompatible pointer type.
>>>>
>>>> qsort is expecting a pointer to a function which returns an int and
>>>> gets passed two const void * parameters. However, you are passing
>>>> it a pointer to a function which returns int and gets passed a
>>>> variable number of unknown parameters.
>>>
>>> No, he's not. A function that takes a variable number of arguments
>>> must have at least one named argument before the "...". Note also his
>>> use of "..." in the call to qsort. The ellipsis isn't being used as C
>>> syntax; it's just an ellipsis.
>>>
>>> He's just not showing us exactly what he's doing -- which means we
>>> can't guess what the problem is.

>>
>>Mea culpa. I had forgotten about the C syntax and used "..." to
>>represent stuff I _thought_ irrelevant to the question.
>>
>>Here's an example which illustrates the way I've been using
>>qsort:
>>-------------------------------------
>>#include <stdio.h>
>>#include <stdlib.h>
>>
>>int val[] = { 3, 2, 1, 4, 5 };
>>
>>int cmp_fcn ( int *one, int *two )

>
> cmp_fcn has the wrong type for a function whose address is to be
> passed to qsort. The two parameters need to be const void *.
>
>>{
>> return (*one < *two) ? -1 :
>> (*one > *two) ? 1 : 0;
>>}
>>
>>int main ( void )
>>{
>> int (*fcmp)() = &cmp_fcn;

>
> fcmp has the wrong type for a pointer to be used as an argument to
> qsort. fcmp is a pointer to function (returning int) about whose
> arguments (type and quantity) absolutely nothing is known. qsort
> needs a pointer to function returning int about whose arguments
> everything is known.
>
>> qsort((void *)val, 5, sizeof(int), fcmp);
>> printf("%d %d %d %d %d\n",
>> val[0], val[1], val[2], val[3], val[4]);
>> return 0;
>>}

>
> Try increasing the warning level on your compiler.
>


OK, if I change the function as suggested by you all to:
--------------------
int cmp_fcn ( const void *x1, const void *x2 )
{
const int *one = x1; const int *two = x2;
return (*one < *two) ? -1 :
(*one > *two) ? 1 : 0;
}
--------------------
then it works both ways. (Thanks guys.)

But I've yet to find a (gcc-3.2.2-5) compiler warning level that
grunts even a little with my original (working) code. As far as
I can remember I've used that syntax on a variety of Unix-like
systems over the years and never got a warning about it.

Thanks for all your help.

Regards,
Charles Sullivan


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Variable argument function as a parameter of a variable argument function AikidoGuy C Programming 11 11-21-2011 10:43 PM
function argument dependent on another function argument? Reckoner Python 11 01-19-2009 03:31 AM
Passing a function as an argument and using the evaluated functionas an argument User1014 Javascript 1 11-30-2006 12:13 PM
Passing pointer to template function as argument to pointer to template function Vijai Kalyan C++ 4 11-08-2005 07:53 PM
Passing a function pointer as an argument to an overloaded >> operator. glen stark C++ 3 09-30-2003 08:25 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57