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-20-2005
On Tue, 20 Sep 2005 00:46:40 +0000, Keith Thompson wrote:

> Charles Sullivan <(E-Mail Removed)> writes:
>> On Mon, 19 Sep 2005 20:12:17 +0000, Keith Thompson wrote:
>>> Kenneth Brody <(E-Mail Removed)> 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.)


Thanks Keith. I usually do what you've suggested in my actual
code, except for argument 3 (too easy to forget to change the
cmp-fcn function and start getting weird errors). And my
inability to follow your suggestion for argument 4 is what
prompted my original query.

Regards,
Charles Sullivan

 
Reply With Quote
 
 
 
 
Martin Ambuhl
Guest
Posts: n/a
 
      09-20-2005
Charles Sullivan wrote:
> int cmp_fcn ( int *one, int *two )


This is incorrect. The prototype for qsort demands that the
comparison function be of type
int cmp_fcn(const void *e1, const void *e2);

See my post
Message-ID: <PTCXe.690$(E-Mail Removed) t>
Date: Mon, 19 Sep 2005 17:50:39 GMT

for the correct way of doing this.
 
Reply With Quote
 
 
 
 
Emmanuel Delahaye
Guest
Posts: n/a
 
      09-20-2005
Charles Sullivan wrote on 20/09/05 :
> 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 )


Wrong prototype.

> {
> return (*one < *two) ? -1 :
> (*one > *two) ? 1 : 0;


Complicated. A simple difference is enough. The 3 domains are <0, 0, >0

> }
>
> int main ( void )
> {
> int (*fcmp)() = &cmp_fcn;


Useless pointer to function masking the parameters error.

> qsort((void *)val, 5, sizeof(int), fcmp);


USeless cast. Now, I have a 18 values array of doubles. What do I do ?

> printf("%d %d %d %d %d\n",
> val[0], val[1], val[2], val[3], val[4]);


Now, I have a 18 values array of ints. What do I do ?

> return 0;
> }
> -----------------------------------


stay stright, simple and conforming:

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

#define NELEM(a) (sizeof (a) / sizeof *(a))

static int cmp_fcn (void const *one, void const *two)
{
int const *p_one = one;
int const *p_two = two;

return *p_one - *p_two;
}

static void print (int const *a, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
{
printf ("%d ", a[i]);
}
printf ("\n");
}

int main (void)
{
int val[] =
{3, 2, 5, 1, 4};

print (val, NELEM (val));
qsort (val, NELEM (val), sizeof *val, cmp_fcn);
print (val, NELEM (val));

return 0;
}

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

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++


 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-20-2005
"Emmanuel Delahaye" <(E-Mail Removed)> writes:
> Charles Sullivan wrote on 20/09/05 :

[...]
>> int cmp_fcn ( int *one, int *two )

>
> Wrong prototype.


Yes.

>> {
>> return (*one < *two) ? -1 :
>> (*one > *two) ? 1 : 0;

>
> Complicated. A simple difference is enough. The 3 domains are <0, 0, >0


No. Subtraction invokes undefined behavior on overflow.

> stay stright, simple and conforming:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> #define NELEM(a) (sizeof (a) / sizeof *(a))
>
> static int cmp_fcn (void const *one, void const *two)
> {
> int const *p_one = one;
> int const *p_two = two;
>
> return *p_one - *p_two;
> }
>
> static void print (int const *a, size_t n)
> {
> size_t i;
> for (i = 0; i < n; i++)
> {
> printf ("%d ", a[i]);
> }
> printf ("\n");
> }
>
> int main (void)
> {
> int val[] =
> {3, 2, 5, 1, 4};
>
> print (val, NELEM (val));
> qsort (val, NELEM (val), sizeof *val, cmp_fcn);
> print (val, NELEM (val));
>
> return 0;
> }


Try changing the initial value of val to

{3, 2, 5, 1, 4, INT_MAX, INT_MIN}

(with "#include <limits.h", of course).

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <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 Tue, 20 Sep 2005 19:40:21 +0000, Keith Thompson wrote:

> "Emmanuel Delahaye" <(E-Mail Removed)> writes:
>> Charles Sullivan wrote on 20/09/05 :

> [...]
>>> int cmp_fcn ( int *one, int *two )

>>
>> Wrong prototype.

>
> Yes.
>
>>> {
>>> return (*one < *two) ? -1 :
>>> (*one > *two) ? 1 : 0;

>>
>> Complicated. A simple difference is enough. The 3 domains are <0, 0, >0

>
> No. Subtraction invokes undefined behavior on overflow.
>
>> stay stright, simple and conforming:
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> #define NELEM(a) (sizeof (a) / sizeof *(a))
>>
>> static int cmp_fcn (void const *one, void const *two)
>> {
>> int const *p_one = one;
>> int const *p_two = two;
>>
>> return *p_one - *p_two;
>> }
>>
>> static void print (int const *a, size_t n)
>> {
>> size_t i;
>> for (i = 0; i < n; i++)
>> {
>> printf ("%d ", a[i]);
>> }
>> printf ("\n");
>> }
>>
>> int main (void)
>> {
>> int val[] =
>> {3, 2, 5, 1, 4};
>>
>> print (val, NELEM (val));
>> qsort (val, NELEM (val), sizeof *val, cmp_fcn);
>> print (val, NELEM (val));
>>
>> return 0;
>> }

>
> Try changing the initial value of val to
>
> {3, 2, 5, 1, 4, INT_MAX, INT_MIN}
>
> (with "#include <limits.h", of course).


No need to nitpick the inner details - the code I posted was meant
only to illustrate the problem as simply as possible. (My first
attempt (with the "...") turned out to mask the real problem.)

Regards,
Charles Sullivan


 
Reply With Quote
 
Charles Sullivan
Guest
Posts: n/a
 
      09-20-2005
On Tue, 20 Sep 2005 06:26:45 +0000, Martin Ambuhl wrote:

> Charles Sullivan wrote:
>> int cmp_fcn ( int *one, int *two )

>
> This is incorrect. The prototype for qsort demands that the
> comparison function be of type
> int cmp_fcn(const void *e1, const void *e2);
>
> See my post
> Message-ID: <PTCXe.690$(E-Mail Removed) t>
> Date: Mon, 19 Sep 2005 17:50:39 GMT
>
> for the correct way of doing this.


Yes, I followed your example and resolved the problem. Many thanks
for taking the time to respond and to generate the example.

Regards,
Charles Sullivan

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      09-20-2005
Charles Sullivan <(E-Mail Removed)> writes:
> On Tue, 20 Sep 2005 19:40:21 +0000, Keith Thompson wrote:
>> "Emmanuel Delahaye" <(E-Mail Removed)> writes:
>>> Charles Sullivan wrote on 20/09/05 :

>> [...]
>>>> int cmp_fcn ( int *one, int *two )
>>>
>>> Wrong prototype.

>>
>> Yes.
>>
>>>> {
>>>> return (*one < *two) ? -1 :
>>>> (*one > *two) ? 1 : 0;
>>>
>>> Complicated. A simple difference is enough. The 3 domains are <0, 0, >0

>>
>> No. Subtraction invokes undefined behavior on overflow.

[...]
> No need to nitpick the inner details - the code I posted was meant
> only to illustrate the problem as simply as possible. (My first
> attempt (with the "...") turned out to mask the real problem.)


The nitpick was directed at what Emmanuel Delahaye posted, not at you
(and neither of you should take it personally). Questions here often
spawn lengthy discussion, sometimes raising points that have little to
do with the original question.

We comp.lang.c regulars are pathologically incapable of leaving an
error uncorrected. This is, IMHO, a good thing.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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-21-2005
Keith Thompson wrote on 21/09/05 :
> We comp.lang.c regulars are pathologically incapable of leaving an
> error uncorrected. This is, IMHO, a good thing.


Indeed. c.l.c. is my main source of C knowledge.


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

..sig under repair


 
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