Let's suppose that we have the following functions (in C):
int sum(int a, int b){
return a+b;
}
int diff(int a, int b){
return a-b;
}
So we know that we can declare an array of funtion pointers in the following way:
int (*test[2]) (int a, int b);
test[0] = sum;
test[1] = diff;
But the following is also valid (but we use heap allocation):
int (**test) (int a, int b) = malloc( 2*sizeof(*test));
test[0] = sum;
test[1] = diff;
So far so good. Now let remember that to declare a (dynamically allocated) array of two integers we can do:
int* test = malloc( 2*sizeof(int));
So why we cannot declare an array of function pointers as
int (*test) (int a, int b) = malloc( 2*sizeof(*test)); ?
Is the reason that as test is the same as *test
and **test
(and so on), malloc( 2*sizeof(*test))
is returning a pointer to a function pointer and therefore it cannot be assigned to (*test)
?
If this supposition is correct, can you explain in detail why we get the compilation error
error: lvalue required as left operand of assignment
when we try to do
int (*test) (int a, int b) = malloc( 2*sizeof(*test));
test=diff; //<--- This is ok.
test+1 = sum; //<--- This is what gives the error!
Disclaimer: I suppose that this is a basic question and the supposition is correct, but I would like a better explanation to have this kind of thing clear one and for all.
Edit:
Notice that this is equivalent to
int (*test) (int a, int b) = malloc( 2*sizeof(*test));
*test=*diff; //<--- This is ok.
*(test+1) = *sum; //<--- This is what gives the error!
as this is somewhat more similar to the case:
int *test = malloc(2*sizeof(*test));
*test = 0;
*(test+1) = 1;
Array of Function PointersWe declare and define four functions which take two integer arguments and return an integer value. These functions add, subtract, multiply and divide the two arguments regarding which function is being called by the user.
A pointer to a function points to the address of the executable code of the function. You can use pointers to call functions and to pass functions as arguments to other functions. You cannot perform pointer arithmetic on pointers to functions.
In C, we can use function pointers to avoid code redundancy. For example a simple qsort() function can be used to sort arrays in ascending order or descending or by any other order in case of array of structures. Not only this, with function pointers and void pointers, it is possible to use qsort for any data type.
A common misconception is that an array and a pointer are completely interchangeable. An array name is not a pointer. Although an array name can be treated as a pointer at times, and array notation can be used with pointers, they are distinct and cannot always be used in place of each other.
So why we cannot declare an array of function pointers as
int (*test) (int a, int b) = malloc( 2*sizeof(*test));
Because test
does not point to a function pointer; it is a function pointer. Thus it cannot point to the first element of an array of function pointers.
If you want an array of function pointers use the previous form:
int (**test) (int a, int b) = malloc( 2*sizeof(*test));
Here, *test
has function pointer type and thus test
can (and does) point to the first element of an array of function pointers. Further:
error: lvalue required as left operand of assignment
when we try to do
int (*test) (int a, int b) = malloc( 2*sizeof(*test)); test=diff; //<--- This is ok. test+1 = sum; //<--- This is what gives the error!
No matter what type test
has, test+1=anything
is always invalid C. test+1
can never be an lvalue. I don't see why you would expect this to work.
GCC is also papering over another bug in your program, sizeof(*test)
. Since *test
has function type, sizeof(*test)
is invalid, but GCC silently assigns it the value 1. This results in allocating too little memory for a function pointer, but it doesn't matter anyway because in the following line you throw away the memory you got from malloc
and assign something else to test
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With