I was reading a mergeSort from standard library in c and found that it has a compare function as an argument(i.e void msort(void *base, size_t nitems, size_t size, int (*compar)(const void , const void)) when it's defined). However, in actual use when the msort function is called, compar function didn't have an argument passed to it(even though it had two parameters, which are (const void *, const void *) as parameters. look the ff code snippet and I would appreciate how it's possible for a function with parameters to be used without arguments in the time it's called??
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
msort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
This is a so called a function pointer: you're basically passing the function cmpfunc() as a parameter, which will then be used by the msort() function internally, with the proper arguments.
A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior.
Function pointers are the precursors of function closures.
To be more clear: the reason why it has no arguments is because you don't know them yet.
Let me explain: cmpfunc() serves to compare 2 elements and tell which one precedes the other. But msort() will need to do many different comparisons, since it has to iterate over all the elements of values[]. Therefore, internally msort() is going to select 2 elements at a time, let's call them x and y, compare them cmpfunc(x, y) and swap them if needed.
void msort(void *base, size_t nitems, size_t size, int (*compar)(const void* , const void*))
The function msort takes a function pointer as its final argument. Just like regular paramters, this parameter tells the msort function that "an address of a function which itself takes two const void* as an argument and retuns an int" will be passed as a parameter. When called like:
msort(values, 5, sizeof(int), cmpfunc);
without the paranthesis at the end of cmpfunc, you are just passing the address of cmpfunc and not actually calling it, therefore it doesn't make sense to pass parameters anyway. You are merely telling the msort where to find the function.
Who actually calls the cmpfunc is the msort. If you have access to its source, you probably can see when and how it calls it (with appropriate parameters passed).
I won't repeat what others have correctly described about "passing the address of a function as a parameter to another function."
A "use case" may help you understand "WHY?"
From your example:
int cmpAscending (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
Now, a "twin" of that:
int cmpDescending (const void * a, const void * b) {
return ( *(int*)b - *(int*)a ); // NB: subtle difference
}
Now, a program can pass the address of the appropriate compare function to msort().
if( ascending )
msort( values, 5, sizeof(int), cmpAscending );
else
msort( values, 5, sizeof(int), cmpDescending );
There are even more economical ways to achieve this:
msort( values, 5, sizeof(int), ascending ? cmpAscending : cmpDescending );
An example, in the main function, foo receives the address of the bar function. Then function foo can call function bar via the function pointer pbar that it received as an argument:
#include <stdio.h>
void bar(int x )
{
printf("%d\n", x);
}
void foo(void(*pbar)(int))
{
pbar(10);
pbar(20);
}
int main(void)
{
foo(bar);
return(0);
}
Related
Why when we use qsort(), int(*compar)(const void*,const void*) haven't add any paraments in, but can also do their functions?
Such as this :
double vals[NUM];
qsort(vals,NUM,sizeof(double),mycomp);
When you append parenthesis to the identifier representing a function, with a list of parameters between, you're calling the function.
In this case, you don't want to call the function, however. You want qsort to call the function to determine whether or not one element is larger or smaller than the other.
It seems you are asking about function pointers in general.
Here is a simple example of function pointer:
int compare(int i, int j)
{
return i > j ? i : j;
}
void process(int i, int j, int(*pfunc)(int, int))
{
printf("%d\n", pfunc(i, j));
}
int main(void)
{
process(1, 2, compare);
return 0;
}
In this example process is sort of like qsort, while compare is the function which we define ourselves. We need to tell qsort how to compare data, but we can't access qsort directly, so pass our own function to it which tells qsort how to compare.
qsort is generic. It doesn't know what type of data it is processing, so it can't simply compare elements using <. What it does instead is let you, the programmer, give it a function to use to compare elements. So, yes you do care about how mycomp works, you need to define it.
int mycomp(const void *a, const void *b) {
const double *lhs = a;
const double *rhs = b;
if (*lhs < *rhs) return -1;
if (*lhs > *rhs) return 1;
return 0;
}
inside of qsort, every time it needs to compare two elements it will pass them to your mycomp function and examine the result. If you define it wrong, your array will be incorrectly arranged (unsorted).
is there any way to use static array, defined in main(), in another function, without giving it to the function as a parameter?
For example:
main() has defined array:
int Array[10];
filled with integers. I'd like to create a comparing function for qsort, that has to have this header:
int compar (const void* a, const void* b);
and I would like it to decide like this:
if Array[a]<Array[b] return 1
etc...
This array cannot be given to qsort directly, but is required for exact sorting.
Also, this array has to be static (no reallocing).
Does anyone have any ideas?
The only way is, of course, so make the address of the array available as a global variable.
This is possible even if the array itself is inside main(), but you have to initialize the global to the properly scoped address, and watch the life-time, of course.
int *mains_array;
static int qsort_callback(const void *a, const void *b)
{
/* use mains_array */
}
int main(void)
{
int secret_array[100];
mains_array = secret_array;
qsort(something, something, qsort_callback);
}
It's a pretty ugly solution, it should be given more thought.
You can't access a local variable from another function. You need to make it global or file scoped.
Global:
/* Declare Array outside any function */
int Array[10];
int main(...
or, file scoped:
/* Declare Array outside any function */
static int Array[10];
int main(...
Note:
Your compare function will receive pointers to the elements to compare. If you are sorting an array of int you need to dereference the pointer in your compare function:
I'm assuming that Array isn't the array you want to sort, but an array that contains information on how to sort an array.
int compare (const void * ap, const void * bp)
{
int a = *((int*)ap);
int b = *((int*)bp);
if (Array[a] < Array[b]) {
return 1;
}
if (Array[a] > Array[b]) {
return -1;
}
return 0;
}
qsort requires the address of the array, so you don't have a choice. But where is defined the array, that does not matter. You just need to be able to refer to it.
The qsort signature is:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
So you will call it by:
qsort(Array, 10, sizeof(int), compar);
And you'll do the compare function as usual:
int compar (const void* a, const void* b) {
return *((int*)a) - *((int*)b);
}
You need to understand that the values passed to compar are not the indexes but the address of the cells of your array. So you don't have to use Array from the compar function, you already have what you need.
You're already giving him your array by calling
qsort (a, numberOfElements, sizeOfEachElement, compare);
What you need to do in your compare function is this:
int compare (const void * a, const void * b)
{
//Here int can be other type
return ( *(int*)a - *(int*)b );
}
I already have a list of strings read in from a text file into a 2D array named word ready to be sorted.
The list looks like:
I
like
cherry
pie
and
chocolate
pie
I want the list to look like this after sorted:
and
cherry
chocolate
I
like
pie
pie
The function prototype is below. int counter is the amount of strings, and MAX_CHAR_LEN = 1024 in case you were wondering.
void alphabetize(char word[][MAX_CHAR_LEN], int counter)
{
return;
}
Notice that sorting by the first character alone is not sufficient, as the list contains two strings that start with "ch"
Can someone provide a function that can do this? Thanks in advance.
You want to use the qsort() function.
qsort(base, num_of_elements, element_size, my_compare);
The comparison function my_compare takes two arguments, each a const void *, and returns a number indicating the relative order of the arguments. A negative number means the first argument is before the second argument. A positive number means the first argument is after the second argument. A zero is returned if the arguments have compared to be equal.
As your string comparison is case insensitive, you will need to create your own comparison function, or find one provided to you by your system that is not part of the C library proper. POSIX provides strcasecmp() for this purpose (Google tells me that _stricmp() is available on Windows).
int my_compare (const void *a, const void *b) {
return strcasecmp(a, b);
}
Defining the comparison function is usually the trickiest part of using qsort(). You have to understand the context of the pointers that are being passed into that function. When an array of TYPE is passed into qsort(), it will pass a pointer to const TYPE to each argument of the comparison function.
In your case, you would be passing in an array of array of MAX_CHAR_LEN chars. So, each argument to the comparison function is a pointer to const array of MAX_CHAR_LEN chars. This means that technically, the my_compare function should be written like this:
int my_compare (const void *a, const void *b) {
typedef char TYPE[MAX_CHAR_LEN];
const TYPE *aa = (const TYPE *)a;
const TYPE *bb = (const TYPE *)b;
return strcasecmp(*aa, *bb);
}
The cast on the arguments would normally not be necessary, except that C doesn't really support the notion of a constant array. It converts such a thing into an array of constants, so the cast is required to reflect that.
However, the address of an array is equal to the address of its first element. That is, for the code above, the following assertions would be true:
assert(aa == (const void *)*aa);
assert(bb == (const void *)*bb);
So, because the dereference of a pointer to an array equals the decayed address value of the same array, the first implementation of my_compare() is sufficient for your 2-D array.
You can use the qsort function to sort. You also need to create a compare function that compares two arrays of chars, and then pass that function pointer as an argument.
Example that sorts ints:
/* qsort example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */
int values[] = { 40, 10, 100, 90, 20, 25 };
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int n;
qsort (values, 6, sizeof(int), compare);
for (n=0; n<6; n++)
printf ("%d ",values[n]);
return 0;
}
The above code can easily be adapted to sort arrays of chars instead of ints.
If you want to write your own sort function, something like this is pretty straight forward.
for (int i = 0; i < array.size(); i++)
{
for (int j = i+1; j < array.size(); j++)
{
if (array[i] > array[j])
swap(array[i],array[j]);
}
}
qsort is Good Option. See it's detail here
You can also try Bubble Sort. It's implementation in C is easy - See this Good answer for help
Code below taken from here.
* qsort example */
#include <stdio.h>
#include <stdlib.h>
int values[] = { 40, 10, 100, 90, 20, 25 };
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int n;
qsort (values, 6, sizeof(int), compare);
for (n=0; n<6; n++)
printf ("%d ",values[n]);
return 0;
}
We have a compare function with parameters in its signature but when we call it in qsort no arguments are passed. How are the values of a and b passed to the function? Thanks
In the context of this expression:
qsort (values, 6, sizeof(int), compare);
the subexpression compare that identifies a function decays into a pointer to that function (and not a function call). The code is effectively equivalent to:
qsort (values, 6, sizeof(int), &compare);
This is exactly the same thing that happens to arrays when used as arguments to a function (which you might or not have seen before but is more frequently asked):
void f( int * x );
int main() {
int array[10];
f( array ); // f( &array[0] )
}
When calling qsort, you're passing a pointer to the function which is why you don't specify any parameters.
Inside the qsort implementation choses values from the 'values' array and calls the 'compare' function. That's how 'a' and 'b' get passed.
qsort passes the addresses of whichever items in the array it wants to compare. For example, &values[3] and &values[5].
Since it doesn't really know the actual types of the items in the array, it uses the size parameter to correctly compute the addresses. See this implementation for example: http://insanecoding.blogspot.ie/2007/03/quicksort.html
This question already has answers here:
Use of function pointer in C
(5 answers)
Closed 8 years ago.
I'm looking through one of my textbooks, and I see the following line of code for a C function:
node_t* func(node_t* n, int f(node_t *))
What exactly does this mean? There is a function as an argument in there. What is the point of that? Shouldn't you just be able to call any function in the file as long as it's been declared?
Also, in terms of assembly, is it the memory location of int f() that is being referenced?
Thank you.
node_t* func(node_t* n, int f(node_t *))
Is a function, called func that takes two parameters: n, a pointer to a node_t, and f, a pointer to a function that takes a node_t pointer and returns an int. The function func returns a pointer to a node_t.
Anyway, the most common use of this that comes to mind is for generic algorithms.
"Shouldn't you just be able to call any function in the file as long as it's been declared?"
As long as the function has been declared in the compilation unit, and the linker can find it at link time, that is true. However, function pointers are used when you want to be able to decide at run time which function to use (or compile time if you just want a generic function).
As a tangible example, consider qsort:
void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );
Now consider this:
typedef struct Student { int id; char* name; }
Student students[10];
//populate students
int sortByName(void* a, void* b)
{
Student* sa = a;
Student* sb = b;
return strcmp(a->name, b->name);
}
int sortById(void* a, void* b)
{
Student* sa = a;
Student* sb = b;
return a->id - b->id;
}
//sort by name:
qsort(students, 10, sizeof(Student), sortByName);
//sort by id:
qsort(students, 10, sizeof(Student), sortById);
The important part is that the sorting code didn't have to be changed. The sorting implementation is effectively generic. It's one algorithm that operates on different data types, and in this case, this generic-ness is facilitated by a function pointer.
There's other uses of function pointers as well (quite a few of them), such as call backs, or branching based on a map that maps something to a function.
The second argument is a function pointer to a function with signature int(node_t *). This way you can pass a call-back to func, like this:
int foo(node_t * p) { /* ... */ }
node_t n;
func(&n, foo); // note: the second argument is the function pointer
Here's a very stupid example to use this to move around a fictitious array:
T * array_next(T * arr, int n) { return arr + n; }
T * array_prev(T * arr, int n) { return arr - n; }
T * move_in_array(T * arr, T * (*f)(T *, int))
{
return f(arr, 1);
}
Now you can write code that moves around in an array in a run-time determined fashion using the callbacks:
T * p = move_in_array(some_array, flag ? array_next : array_prev);
The key design idea here is that we have a generic action function move_in_array whose specific implementation is passed as an argument in form of a function pointer.