What is the difference between these two function pointer notations in C?
void (*a[]()) and void (*a)()[]
Do they both represent same - a as an array of pointers to functions - or does the second one represent a pointer to an array of functions?
How should I call these functions -
say void (*a[]()) = {swap, add, sub, prod};?
Does that mean that a is an array of function pointers of 4 elements and swap, add, sub, prod's address are there in the a[0]...a[3].
How should I invoke these functions, like this?
*a[i]()
or like this?
a[i]()
Use cdecl.org to figure this stuff out until you can do it without thinking about it.
void (*a[]()): declare a as array of function returning pointer to void
whereas
void (*a)()[]: declare a as pointer to function returning array of void
The latter is invalid C.
They're both invalid.
void (*a[]());
is interpreted as
a -- a
a[] -- is an array
a[]() -- of function
*a[]() -- returning pointer
void (*a[]()) -- to void.
You cannot declare an array of function type. Similarly,
void (*a)()[]
is interpreted as
a -- a
(*a) -- is a pointer
(*a)() -- to a function
(*a)()[] -- returning an array of unknown size
void (*a)()[] -- of void.
Functions cannot return array types, and you can't have arrays of void.
If you want to declare an array of pointers to functions returning void, you'd build it up as:
a -- a
a[N] -- is an N-element array
*a[N] -- of pointers
(*a[N])() -- to functions
void (*a[N])(); -- returning void
Thus, void (*a[N])(); declares a as an array of pointers to functions returning void. You'd call each individual function in the array as
(*a[i])();
or
a[i]();
although I prefer the first form, even if it is a little more cluttered.
So, given the list of functions swap, add, sub, and prod, you'd build up your array as
void swap() {...}
void add() {...}
void sub() {...}
void prod() {...}
...
void (*a[])() = {swap, add, sub, prod};
...
(*a[0])(); // calls swap
(*a[1])(); // calls add
Given the function names, I assume they take some kind of arguments. Note that all the function pointers in an array should have the same signature; that is, they should all have the same return type, as well as the same number and types of arguments.
When you call a function through a pointer, C allows you to drop the explicit dereference, so you could call those functions as
a[0]();
a[1]();
but I prefer the first form, even if it is visually more cluttered.
Remember that [] and function-call () have higher precedence than unary *, so T *a[N] declares an N-element array of pointer to T, T (*a)[N] declares a pointer to an N-element array of T, T *f() declares a function returning a pointer to T, and T (*f)() declares a pointer to a function returning T.
According to the Right-Left-Rule in C (other reference here), both expressions are considered invalid by the compiler (and probably by the standard as well).
The first one is a array of functions, the latter is an array of voids.
An array of pointers to functions returning void would be
void (*a[])()
.
The second expression is not valid in C, since first it doesn't allow for arrays of void and second it doesn't allow a function to return an array.
Related
In the book The C Programming Language(K&R2) Chapter 5, the author gives a general-purpose sorting routine with the following declaration.
void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
What kind of role does the pointer to void play in this declaration? Is it common to use pointer to void in C programs in this way? What is the advantage or disadvantage of this kind of code?
From the book you referenced:
As indicated by the function prototype, qsort expects an array of pointers, two integers, and a function with two pointer arguments. The generic pointer type void* is used for the pointer arguments. Any pointer can be cast to void* and back again without loss of information, so we can call qsort by casting arguments to void*
Since void* is used in the function prototype, you can use qsort to sort data of any type (int, double, char*, struct, etc.). All you have to do is provide a callback function that casts the void pointers to pointers of the correct type before dereferencing them and performing the comparison.
The use of a function that accepts different data types avoids unnecessary repetition in your code, which is always a good thing.
The pointer to void is usefull when you provide a function and don't want to limit the user of the function with a parameter type.
More generally, the void pointer is used when you don't know which type of pointer you are manipulating.
Is this example the function qsort will sort lines, but the function don't know the type of the line. So it lets you using the function with any type of lines using a void pointers array. The function qsort will call the fonction comp passed in parameters with the lines of the array. Here again the comp function take void pointers parameters, allowing you to create a comparison function which take any type of parameters.
How can I pass the location of an array of pointers in a function in c i.e.
I have an int* array[10]; and through a function I want to assign the array[0] to be the location of a particular number say, 5. What should the argument of the function look like. I have tried:
void insert(int* array);
but it didn't work.
Arrays are always passed as a pointer pointing to the beginning of the array, even if you don't write it explicitly. So given this declaration of an array from your question:
int *array[10];
Both the following functions will accept a pointer to such an array:
int foo(int *array[]);
int foo(int **array);
They are just equivalent and I would suggest you use the second form, because it makes it explicit what type really is passed to the function.
inside the function, you can access any element, because the indexers are define the same way on a pointer to an array as on the array itself:
int foo(int **array)
{
int *sixthElement = array[5];
// [...]
}
Additional stylistic note: In C, it's common practice to attach the * when declaring a pointer to the identifier, not to the type, ie better write
int *array[10];
instead of
int* array[10];
This is because in a C declaration, there's no such thing as a pointer type, there's a pointer declarator (consisting of the *, optional qualifiers and the identifier) and this declarator declares a variable to be a pointer to the specified type. It's a subtle difference, but if you ever try to declare more than one variable in one line (don't do this, it's just for explanation here), you will notice it:
int *a, b; // <- declares a as a pointer to int, b just as an int
Is the code I have written valid? I am trying to write an expression which is a pointer to an array of pointers to functions which takes a single argument int and return void. So function has return type void. But I am not sure if my expression of (**[]) is valid or should I write it as (*(*[]))? Because the later means array of pointers to a function which is a pointer to a function.
void(*(*[])(int));
Do it like this
typedef void (*fptr)(int)
fptr array[10];
it's clearer than trying to roll it all into one bit of syntax.
I am having difficulty trying to understand what the following declaration means. Is this declaration standard?
double* (*p[3]) (void* (*)());
Can anyone help me to understand the meaning of this declaration?
Rule for reading hairy declarations: find the leftmost identifier and work outward, remembering that () and [] bind before *, so T *a[N] is an array of pointers to T, T (*a)[N] is a pointer to an array of T, T *f() is a function returning a pointer to T, and T (*f)() is a pointer to a function returning T. Since a function prototype may omit parameter names, you may see things like T *[N] or T (*)(). The meaning is mostly the same1, just pretend that there's an identifier of 0 length.
Thus,
p -- p
p[3] -- is a 3-element array
*p[3] -- of pointers
(*p[3]) ( ) -- to functions
(*p[3]) ( (*)()) -- taking a pointer to a function
(*p[3]) ( * (*)()) -- returning a pointer
(*p[3]) (void* (*)()) -- to void
* (*p[3]) (void* (*)()) -- returning a pointer
double* (*p[3]) (void* (*)()); -- to double
The important thing to take away here is that you are declaring p as an array of ..., not a function returning ....
What would such a beast look like in practice? Well, first, you need three functions to point to. Each of these functions takes a single parameter, which is a pointer to a function returning a pointer to void:
double *foo(void *(*)());
double *bar(void *(*)());
double *bletch(void *(*)());
double *(*p[3]) (void *(*)()) = {foo, bar, bletch};
Each of foo, bar, and bletch would call the function passed to it and somehow return a pointer to double.
You would also want to define one or more functions that satisfy the parameter type for each of foo, bar, and bletch:
void *blurga() {...}
so if you called foo directly, you'd call it like
double *pv;
...
pv = foo(blurga);
So we could imagine a call like
double *pv = (*p[0])(blurga);
1 - the difference is that in the context of a function parameter declaration, T a[] and T a[N] are identical to T *a; in all three cases, a is a pointer to T, not an array of T. Note that this is only true in a function parameter declaration. Thus, T *[] will be identical to T **.
Just use http://cdecl.org:
declare p as array 3 of pointer to function (pointer to function returning pointer to void) returning pointer to double
For more info, see this MSDN article: Interpreting more complex declarators.
But typedefs would help:
typedef void *(*foo)(); // foo is a function-pointer type
typedef double *(*bar)(foo); // bar is also a function-pointer type
bar p[3];
(Obviously, use appropriate names in place of foo and bar!)
Your p is an array of 3 pointers to a function returning a double pointer, and taking as argument a pointer to another function that returns a void pointer and that takes no arguments.
But, don't use this syntax, try using typedef instead.
It is array (of size 3) of function pointers which returns pointer to double and take another function pointer as argument.
Type of function whose pointer can be stored in the array: double *(func)(void* (*)())
Type of function whose pointer can be passed as argument to func: void *(func1)(void)
"There is a technique known as the ``Clockwise/Spiral Rule'' which enables any C programmer to parse in their head any C declaration!"
Clockwise Spiral Rule - http://c-faq.com/decl/spiral.anderson.html
void (*(*f[])())() defines f as an array of unspecified size, of pointers to functions that return pointers to functions that return void.
What does this means in a very very very simple explanation
Imagine you have a function - let's call it a() - that returns void.
a() has an address in memory.
Now imagine you have a function pa() that returns a pointer to a(), i.e. pa() returns the address of a().
Now, you don't have just one pair of functions like this but several:
b() returns void, pb() returns the address of b()
c() returns void, pc() returns the address of c()
and so on.
Now you want to store the addresses of pa(), pb(), pc() etc in an array, but you don't know how many of them there are yet, so you declare an array of unspecified size to hold all those.
The type of that array, is an array of pointers to functions that return pointers to functions that return void.
If in doubt, typedef:
typedef void (*f1)(); // pointer to function returning void
typedef f1 (*f2)(); // pointer to function returning f1
f2 f[]; // your array (not valid C!)
The final definition is not valid, because f[] is an incomplete type, and you are only allowed to define objects of complete type. A declaration that's not a definition would be OK (extern f2 f[];), or you could have a complete type by implying the array size from an braced initializer list, as in f2 f[] = { a, b, c };, in which case f has (complete) type f2[3].
Note that the above typedef code contains the same number of opening parentheses, closing parentheses, brackets and asterisks as your declaration.
I don't know if it is simple, but cdecl(1) can pull it apart for you:
cdecl> explain void (*(*f[])())();
declare f as array of pointer to function returning pointer to function returning void
(Not using the code formatting because it introduces the hateful horizontal scrollbar with that long descriptive line.)