njg
njg

Reputation: 45

Change signature of function pointer in C when one argument is constant

I want to use quicksort in C, which has a function signature of void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)), but the signature of my comparison function is int (*compar)(const void *, const void*, const int) with the third argument being constant during one call to quicksort.

As an illustration, assume that I want to sort an array of vectors according to different norms (L0, L1, L2 and Linifinity norm for example). Which norm it actually is, is passed as a third argument to the comparison function, but remains constant during the call of qsort. Is it possible to do an assignment in a form like

//Function declaration for parametric comparison
int cmp3(int* a_vec, int* b_vec, int x);

// Somewhere in main
int (*cmp2)(int, int);
cmp2 = cmp3(int*, int*, 2);//2 could mean L2 norm

to be able to call something like

qsort(a, 100, sizeof(a), cmp2);

I know this does not work, but I hope it gives an idea what I want to accomplish. Also it is not possible to make different comparison functions and calls to qsort as the number of different ways of comparing is too big.

Upvotes: 2

Views: 504

Answers (2)

ForceBru
ForceBru

Reputation: 44868

This is called partial function application, and you can only achieve something like this with wrappers in C:

int cmp3(int *a, int *b) {
    return cmp2(a, b, 2);
} 

If you're into partial function application or maybe mappings or pure functions, you may want to look into functional programming languages, like Haskell.

Upvotes: 4

gwerners
gwerners

Reputation: 66

The main problem is that the function signature expects 3 elements in the stack before being called. Old C compilers were "smart" and if you don't pass enough parameters, then they "complete" the stack with empty variables (zeroed).

Nowadays if you do that (assuming the compiler accept),it will have a 3rd variable with undefined value in the stack and not the value you are expecting.

You should do a "proxy" function as a previous comment said:

int cmp3(int *a, int *b) {
    return cmp2(a, b, 2);
}

Upvotes: 0

Related Questions