By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,466 Members | 1,309 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,466 IT Pros & Developers. It's quick & easy.

how do I pass a generic comparison function?

P: n/a
Howdy,

How do I pass some function a generic comparison
function? I figured out one non-generic case, but
since this code got parameter declarations in two places,
it's obviously not generic.

TIA

#include <stdio.h>

char comp1 ( int, int );
char comp2 ( char, char );
char comp3 ( char*, char* );

char comp1 ( int i1, int i2 ) {
if (i1 == i2) {
return '=';
} else if (i1 > i2) {
return '>';
} else {
return '<';
}
}

/* comp2 & comp3 omitted for brevity */

int some_func ( char (*comp)(int,int)) {
putchar((*comp) (7,8));
putchar((*comp) (8,8));
putchar((*comp) (8,7));
return 0;
}

int main () {
int i;
i = some_func((char (*)(int, int))(comp1));
return 0;
}
Nov 14 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
aurgathor <sp*****@if-you.com> wrote:
How do I pass some function a generic comparison
function? I figured out one non-generic case, but
since this code got parameter declarations in two places,
it's obviously not generic. #include <stdio.h> char comp1 ( int, int );
char comp2 ( char, char );
char comp3 ( char*, char* ); char comp1 ( int i1, int i2 ) {
if (i1 == i2) {
return '=';
} else if (i1 > i2) {
return '>';
} else {
return '<';
}
} /* comp2 & comp3 omitted for brevity */ int some_func ( char (*comp)(int,int)) {
putchar((*comp) (7,8));
putchar((*comp) (8,8));
putchar((*comp) (8,7));
return 0;
} int main () {
int i;
i = some_func((char (*)(int, int))(comp1));
return 0;
}


Did you have a look at how it's done with the qsort() function? It
expects (as it's fourth argument) a function that has two 'const
void *' arguments. And I guess that's the only way to make the
function as generic as possible, i.e. you can pass all kinds of
data types to the comparison functions that way. If you use that
you would have something like

#include <stdio.h>

char cmp_as_ints( const void *a, const void *b ) {
if ( * ( int * ) a == * ( int * ) b )
return '=';
else if ( * ( int * ) a < * ( int * ) b )
return '<';
return '>';
}

int some_func( char ( *cmp )( const void *, const void * ) ) {
int dummy1 = 7, dummy2 = 8;
putchar( cmp( &dummy1, &dummy2 ) );
dummy1 = 8;
putchar( cmp( &dummy1, &dummy2 ) );
dummy2 = 7;
putchar( cmp( &dummy1, &dummy2 ) );
return 0;
}

int main( void ) {
int i = some_func( cmp_as_ints );
return 0;
}

Since you have to pass pointers to the comparison function you unfor-
tunately need two dummy variables in some_func() to be able to pass
their addresses. BTW, when you call a function via a function pointer
you can but don't have to dereference the function pointer, so both

cmp( &var1, &var2 )

and

( * cmp )( &var1, &var2 )

are perfectly valid ways to call the function 'cmp' points to.

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #2

P: n/a
aurgathor wrote:

How do I pass some function a generic comparison
function? I figured out one non-generic case, but
since this code got parameter declarations in two places,
it's obviously not generic.

#include <stdio.h>

char comp1 ( int, int );
char comp2 ( char, char );
char comp3 ( char*, char* );

char comp1 ( int i1, int i2 ) {
if (i1 == i2) {
return '=';
} else if (i1 > i2) {
return '>';
} else {
return '<';
}
}

/* comp2 & comp3 omitted for brevity */
int some_func ( char (*comp)(int,int)) {
putchar((*comp) (7,8));
putchar((*comp) (8,8));
putchar((*comp) (8,7));
return 0;
}

int main () {
int i;
i = some_func((char (*)(int, int))(comp1));
return 0;
}


You use void *. To compare ints:

int cmpint(void *left, void *right)
{
int *leftitem = left;
int *rightitem = right;

if (leftitem > rightitem) return '>';
else if (leftitem < rightitem) return '<';
else return '=';
|

and functions to compare other types need only vary the name and
the types of the local pointers. The calling will only vary the
name of the function passed:

typedef int cmpfunct(void *, void *);

void foo(cmpfunct cmp)
{
... cmp(leftthing, rightthing);
}

....
foo(cmpint);

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #3

P: n/a
You use void *. To compare ints:

int cmpint(void *left, void *right)
{
int *leftitem = left;
int *rightitem = right;

if (leftitem > rightitem) return '>';
else if (leftitem < rightitem) return '<';
else return '=';
|

should this not be
if( *leftitem > *rightitem) return '>';
or am i overlooking something??

Regards

Mike

Nov 14 '05 #4

P: n/a
Michael wrote:
You use void *. To compare ints:

int cmpint(void *left, void *right)
{
int *leftitem = left;
int *rightitem = right;

if (leftitem > rightitem) return '>';
else if (leftitem < rightitem) return '<';
else return '=';
}

should this not be
if( *leftitem > *rightitem) return '>';
or am i overlooking something??


Yes and no respectively. The dog ate the asterisks.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #5

P: n/a
On Sat, 26 Feb 2005 04:21:38 -0800, "aurgathor" <sp*****@if-you.com>
wrote:
Howdy,

How do I pass some function a generic comparison
function? I figured out one non-generic case, but
since this code got parameter declarations in two places,
it's obviously not generic. <snip> char comp1 ( int, int );
char comp2 ( char, char );
char comp3 ( char*, char* ); <snip: definition of comp1>
int some_func ( char (*comp)(int,int)) {

<snip: use (*comp)( 2 ints )>

Several others have given specific answers using void*. That's usually
the simplest way but not the only one. What matters is that type of
parameters declared by the routine is the same as that declared to the
code that does the call (here through a pointer passed as parameter).

For scalar types there are hierarchies where a 'higher' type can
(always) handle the values of a 'lower' one, which you can then
convert/cast back if and when desired. For example long can handle any
int and int any short, and short any char if char is signed always and
even unsigned on 'normal' (8-bit) machines. double can handle any
float. void * (perhaps qualified) can handle any data pointer; so can
char * but it doesn't convert silently.

More generally but clumsily, you can create and use a union type. This
requires creating dummy objects at the point of 'anonymization' in
C90; in C99 you can use a compound literal, and in GCC as an extension
you can just cast to a union type that has a suitable member. This
does require that all types to be used be known at coding time; with
void * you can later (maybe even dynamically) add (instances of) new
types that pass through unchanged middle code.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #6

P: n/a

"Dave Thompson" <da*************@worldnet.att.net> schreef in bericht
news:7b********************************@4ax.com...
On Sat, 26 Feb 2005 04:21:38 -0800, "aurgathor" <sp*****@if-you.com>
wrote:
Howdy,

How do I pass some function a generic comparison
function? I figured out one non-generic case, but
since this code got parameter declarations in two places,
it's obviously not generic.

<snip>
char comp1 ( int, int );
char comp2 ( char, char );
char comp3 ( char*, char* );

<snip: definition of comp1>
int some_func ( char (*comp)(int,int)) {

<snip: use (*comp)( 2 ints )>

Several others have given specific answers using void*. That's usually
the simplest way but not the only one. What matters is that type of
parameters declared by the routine is the same as that declared to the
code that does the call (here through a pointer passed as parameter).

For scalar types there are hierarchies where a 'higher' type can
(always) handle the values of a 'lower' one, which you can then
convert/cast back if and when desired. For example long can handle any
int and int any short, and short any char if char is signed always and
even unsigned on 'normal' (8-bit) machines. double can handle any
float. void * (perhaps qualified) can handle any data pointer; so can
char * but it doesn't convert silently.

More generally but clumsily, you can create and use a union type. This
requires creating dummy objects at the point of 'anonymization' in
C90; in C99 you can use a compound literal, and in GCC as an extension
you can just cast to a union type that has a suitable member. This
does require that all types to be used be known at coding time; with
void * you can later (maybe even dynamically) add (instances of) new
types that pass through unchanged middle code.

- David.Thompson1 at worldnet.att.net


you cannot

The best thing you can do is using char * and use strcmp I think

Johan

Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.