What does this C declaration int *(*table())[10] do? - c

I am trying to write C code to create a two-dimensional array of function pointers, where every function takes no arguments and returns int.
I have already tried this code:
int *(*table())[10];
but it didn't work. Do you have any idea how can I fix it?

C declarations are built such that typing the declarators as an expression yields the type. So, let's assume we already have such a 2D array a. How to get int out of it?
Index once, getting a 1D array: a[10].
Index again, getting a pointer to function: a[10][10]
Dereference the pointer, getting a function: *a[10][10]
Call the function, getting an int: (*a[10][10])()
So the final declaration is:
int (*a[10][10])(void);
Of course, as usual, it's much easier with typedefs:
typedef int Fun(void);
typedef Fun *FunPtr;
FunPtr a[10][10];

Regarding what the declaration you came up with does, that's a pretty icky declaration. You can unwind it with the clockwise/spiral rule.
Basically the table() part means there's a a function. The () is obsolete C, meaning a function taking any parameter. You should be using (void) instead.
The int* (* ... ) [10] part means that you have a function returning an array pointer to an array int* [10]. Such an array pointer is normally declared as int* (*name)[10] when written outside a function return value.
So you have a function declaration, of a function returning an array pointer, to an array of 10 int*, the function is taking an obsolete style parameter list.
You can understand it better with this example:
typedef int* (*arrptr)[10]; // to illustrate, typedef an array pointer int* (*)[10]
typedef arrptr func_t (void); // typedef a function type returning said array pointer
void func (func_t* x){}
// dummy function to demonstrate type compatibility, funct_t* is a function pointer
int *(*table(void))[10]; // function declaration
int main (void)
{
func(table); // table is of same type as the function pointer func_t*
return 0;
}
int *(*table(void))[10]
{
return 0;
}
Please note that hiding arrays and pointers behind typedefs is normally bad practice.
Regarding how to get an array of function pointers, it is way more straight-forward than interpreting the above gibberish.
int* func (void) This is a function.
int* (*func) (void) This is a function pointer to such a function.
int* (*func[10][10]) (void) This is a 2D array of function pointers.
Or preferably:
typedef int* func_t (void) This is a function type.
func_t* fptr This is a function pointer to such a function.
func_t* fptr[10][10] This is a 2D array of function pointers.

Related

pass the location of a an array in a function

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

pointer to an array of pointers to functions taking int argument and returning void

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.

Typedefs for complex data types

I am attempting to understand the underlying mechanics of how C handles complex typedefs, from a syntax perspective.
Consider the following examples below (references included at end of the question).
typedef int (*p1d)[10];
is the proper declaration, i.e. p1d here is a pointer to an array of
10 integers just as it was under the declaration using the Array type.
Note that this is different from
typedef int *p1d[10];
which would make p1d the name of an array of 10 pointers to type int.
So, if I consider operator precedence for both examples (I'll rewrite them):
int *p1d[10]; // Becomes ...
int* p1d[10];
So, reading left-to-right, and using operator precedence, I get: "Pointer to type int, named p1d, of size 10", which is wrong. As for the other/first case:
int (*p1d)[10];
Which I read as "p1d is a pointer, of type int, and is an array of 10 such elements", which is also wrong.
Could someone explain the rules applied for determining these typedefs? I would like to apply them to function pointers as well, and I'm hoping this discussion will also explain the logic behind const casts (ie: pointer to constant data vs const pointer to variable data).
Thank you.
References:
C Tutorial: Pointers to Arrays: http://www.taranets.net/cgi/ts/1.37/ts.ws.pl?w=329;b=285
Operator Precedence: http://www.swansontec.com/sopc.html
One of my professors wrote this little guide to reading these kinds of declarations. Give it a read, it'll be worth your while and hopefully answer any questions.
All credit goes to Rick Ord (http://cseweb.ucsd.edu/~ricko/)
The "right-left" rule is a completely regular rule for deciphering C
declarations. It can also be useful in creating them.
First, symbols. Read
* as "pointer to" - always on the left side
[] as "array of" - always on the right side
() as "function returning" - always on the right side
as you encounter them in the declaration.
STEP 1
------
Find the identifier. This is your starting point. Then say to yourself,
"identifier is." You've started your declaration.
STEP 2
------
Look at the symbols on the right of the identifier. If, say, you find "()"
there, then you know that this is the declaration for a function. So you
would then have "identifier is function returning". Or if you found a
"[]" there, you would say "identifier is array of". Continue right until
you run out of symbols *OR* hit a *right* parenthesis ")". (If you hit a
left parenthesis, that's the beginning of a () symbol, even if there
is stuff in between the parentheses. More on that below.)
STEP 3
------
Look at the symbols to the left of the identifier. If it is not one of our
symbols above (say, something like "int"), just say it. Otherwise, translate
it into English using that table above. Keep going left until you run out of
symbols *OR* hit a *left* parenthesis "(".
Now repeat steps 2 and 3 until you've formed your declaration. Here are some
examples:
int *p[];
1) Find identifier. int *p[];
^
"p is"
2) Move right until out of symbols or right parenthesis hit.
int *p[];
^^
"p is array of"
3) Can't move right anymore (out of symbols), so move left and find:
int *p[];
^
"p is array of pointer to"
4) Keep going left and find:
int *p[];
^^^
"p is array of pointer to int".
(or "p is an array where each element is of type pointer to int")
Another example:
int *(*func())();
1) Find the identifier. int *(*func())();
^^^^
"func is"
2) Move right. int *(*func())();
^^
"func is function returning"
3) Can't move right anymore because of the right parenthesis, so move left.
int *(*func())();
^
"func is function returning pointer to"
4) Can't move left anymore because of the left parenthesis, so keep going
right. int *(*func())();
^^
"func is function returning pointer to function returning"
5) Can't move right anymore because we're out of symbols, so go left.
int *(*func())();
^
"func is function returning pointer to function returning pointer to"
6) And finally, keep going left, because there's nothing left on the right.
int *(*func())();
^^^
"func is function returning pointer to function returning pointer to int".
As you can see, this rule can be quite useful. You can also use it to
sanity check yourself while you are creating declarations, and to give
you a hint about where to put the next symbol and whether parentheses
are required.
Some declarations look much more complicated than they are due to array
sizes and argument lists in prototype form. If you see "[3]", that's
read as "array (size 3) of...". If you see "(char *,int)" that's read
as "function expecting (char *,int) and returning...". Here's a fun
one:
int (*(*fun_one)(char *,double))[9][20];
I won't go through each of the steps to decipher this one.
Ok. It's:
"fun_one is pointer to function expecting (char *,double) and
returning pointer to array (size 9) of array (size 20) of int."
As you can see, it's not as complicated if you get rid of the array sizes
and argument lists:
int (*(*fun_one)())[][];
You can decipher it that way, and then put in the array sizes and argument
lists later.
Some final words:
It is quite possible to make illegal declarations using this rule,
so some knowledge of what's legal in C is necessary. For instance,
if the above had been:
int *((*fun_one)())[][];
it would have been "fun_one is pointer to function returning array of array of
^^^^^^^^^^^^^^^^^^^^^^^^
pointer to int". Since a function cannot return an array, but only a
pointer to an array, that declaration is illegal.
Illegal combinations include:
[]() - cannot have an array of functions
()() - cannot have a function that returns a function
()[] - cannot have a function that returns an array
In all the above cases, you would need a set of parens to bind a *
symbol on the left between these () and [] right-side symbols in order
for the declaration to be legal.
Here are some legal and illegal examples:
int i; an int
int *p; an int pointer (ptr to an int)
int a[]; an array of ints
int f(); a function returning an int
int **pp; a pointer to an int pointer (ptr to a ptr to an int)
int (*pa)[]; a pointer to an array of ints
int (*pf)(); a pointer to a function returning an int
int *ap[]; an array of int pointers (array of ptrs to ints)
int aa[][]; an array of arrays of ints
int af[](); an array of functions returning an int (ILLEGAL)
int *fp(); a function returning an int pointer
int fa()[]; a function returning an array of ints (ILLEGAL)
int ff()(); a function returning a function returning an int
(ILLEGAL)
int ***ppp; a pointer to a pointer to an int pointer
int (**ppa)[]; a pointer to a pointer to an array of ints
int (**ppf)(); a pointer to a pointer to a function returning an int
int *(*pap)[]; a pointer to an array of int pointers
int (*paa)[][]; a pointer to an array of arrays of ints
int (*paf)[](); a pointer to a an array of functions returning an int
(ILLEGAL)
int *(*pfp)(); a pointer to a function returning an int pointer
int (*pfa)()[]; a pointer to a function returning an array of ints
(ILLEGAL)
int (*pff)()(); a pointer to a function returning a function
returning an int (ILLEGAL)
int **app[]; an array of pointers to int pointers
int (*apa[])[]; an array of pointers to arrays of ints
int (*apf[])(); an array of pointers to functions returning an int
int *aap[][]; an array of arrays of int pointers
int aaa[][][]; an array of arrays of arrays of ints
int aaf[][](); an array of arrays of functions returning an int
(ILLEGAL)
int *afp[](); an array of functions returning int pointers (ILLEGAL)
int afa[]()[]; an array of functions returning an array of ints
(ILLEGAL)
int aff[]()(); an array of functions returning functions
returning an int (ILLEGAL)
int **fpp(); a function returning a pointer to an int pointer
int (*fpa())[]; a function returning a pointer to an array of ints
int (*fpf())(); a function returning a pointer to a function
returning an int
int *fap()[]; a function returning an array of int pointers (ILLEGAL)
int faa()[][]; a function returning an array of arrays of ints
(ILLEGAL)
int faf()[](); a function returning an array of functions
returning an int (ILLEGAL)
int *ffp()(); a function returning a function
returning an int pointer (ILLEGAL)
Simplfying KepaniHaole's rules a bit, it boils down to:
Find the left-most identifer
Work your way out, remembering that absent explicit grouping by parentheses, function-call () and [] bind before *.
Apply recursively to any function parameters.
Thus, T *a[] is an array of pointer tp T, T (*a)[] 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.
Taking an example that gives a lot of people heartburn, we can look at the prototype for the POSIX signal function:
void (*signal( int sig, void (*func)( int )))( int );
which reads as
signal -- signal
signal( ) -- is a function with
signal( sig ) -- parameter sig
signal( int sig ) -- of type int
signal( int sig, func ) -- and parameter func
signal( int sig, (*func) ) -- of type pointer to
signal( int sig, (*func)( )) -- a function with
signal( int sig, (*func)( int )) -- an int parameter
signal( int sig, void (*func)( int )) -- returning void
(*signal( int sig, void (*func)( int ))) -- returning a pointer to
(*signal( int sig, void (*func)( int )))( ) -- a function with
(*signal( int sig, void (*func)( int )))( int ) -- an int parameter
void (*signal( int sig, void (*func)( int )))( int ) -- returning void

Correct C syntax for "address of" character pointer array?

I need to pass into a function the address of a character pointer array, what would be the correct function declaration/prototype syntax for that?
I tried:
void myFunc(char &*a[]);
But get an expected ; , or ) before & error.
I also tried:
void myFunc(char **a);
Since the pointer I would be passing in is indeed a pointer to a pointer, but I get yet another error. This time the error has to do with: expected char **, but got char *[]
Or something like that. I have since attempted other solutions so I not remember exactly the error.
Any suggestions?
Assuming you have an array declared as
char *a[N];
and you want to pass a pointer to the array, as in
foo( &a );
then the prototype for foo needs to be
void foo( char *(*aptr)[N] );
Note that in this case, the size of the array must be declared; a pointer to an N-element array is a different type from a pointer to an M-element array.
Normally, you don't want to do this; instead, you would normally just pass the array expression like so:
foo ( a );
and the corresponding prototype would be:
void foo ( char **aptr );
Except when it is the operand of thesizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer toT", and the value of the expression will be the address of the first element of the array.
Updated Answer For Modified Problem Statement
Given what you have said in comments, there is no need to pass a pointer to an array. You can simply pass a pointer to the first element of the array. Such a pointer suffices because the remaining elements of the array are obviously located after the first element.
To write a function that sets pointers in an array of pointers to char, do this:
void MyFunction(int NumberToSet, char *Pointers[])
{
for (int i = 0; i < NumberToSet; ++i)
{
Pointers[i] = SomeString;
}
}
In the above, SomeString must have type “pointer to char”. This could be a string, such as "Hello", or an array of char (which is automatically converted to a pointer to char), or some identifier x that has been declared as char *x (and has been initialized or assigned), for example.
To use this function, call it like this:
char *MyArrayOfPointers[SomeNumber];
MyFunction(NumberOfPointersIWantToSet, MyArrayOfPointers);
Original Answer
In most cases, to pass an array of pointers to char to a function, it suffices to pass the address of the first element. In this case, you would use either of these (they are equivalent):
void myFunc(char **a)
void myFunc(char *a[])
If you truly want to pass the address of the array, you would use:
void myFunc(char *(*a)[])
In this case, the type of a is incomplete, since the dimension is missing. Depending on what you intend to do with a, you may need to provide the dimension in the declaration.
When calling myFunc and passing it some array declared as char *array[N];, you would pass it, in the former case, as myFunc(array) and, in the latter case, as myFunc(&array).
try this as a function definition void myFunc(char *a[]) or void myFunc(char **a) then use it this way :
char *arr[20];
myFunc(arr);
Ok you are almost on the right path. void myFunc(char *a[]);
Example
void fun(char *a[]){
printf("%s",*a); //for accessing the next element do a+1
}
int main(void) {
char *x[3];
x[0]="abcd";
fun(x); // here you are passing the address first array element
return 0;
DEMO
Declaration
void myFunc(char &*a[]);
is not a valid C syntax.
To pass the address of character pointer arrays, use this instead
void myFunc(char *(*a)[]);
*(*a)[] in the above function declares a as pointer to array of pointers to chars. Must note that a has an incompatible type. A suffix is needed in [] to make it complete.
First of all, C is in general a "pass by reference" language. Some data items such as integers, floats, and single characters can be passed by value. But, arrays of those same data types are ALWAYS passed by reference.
Thus, when you say "I need to pass into a function the address of a character pointer array" then simply declare an array of character pointers in your function prototype as:
void myFunc(char *a[]);
Thus, char * declares a char pointer and a[] defines an array of them. To check this declaration refer to: http://www.cdecl.org/ which parses this expression as a "declare a as array of pointer to char".
The technical point is that the * binds with char rather than with a[].
So, C will pass a pointer to the data structure that you have declared. A discussion on this topic could delve into double pointers but for this question such a discussion is probably off topic.

Is it possible to assign a new value to an array name?

I read that;
Although an array name can be used as a pointer (after decaying into pointer), it's not possible to assign it a new value. Attempting to make it point elsewhere is an error:
while (*a != 0) // a is of (int *) type
a++; //wrong
On the other hand, when passed to a function, an array name is always treated as a pointer. The function call
largest = largest_num(b, n) // b is an array of int
for the function
int find_largest(int a[], int n)
{
....
....
}
causes a pointer to the first element of b to be assigned to a.
Above two statements ( in bold ) seems to me contradictory. I am confused.
In a function declaration, an array is treated as if you'd declared a pointer, so
int find_largest(int a[], int n) {
is processed as if it were
int find_largest(int *a, int n) {
So a is a pointer, not an array, and there's no contradiction.
Since it's a pointer, you can reassign a, e.g.
a++;
is allowed.
No contradiction there - you're still working with a pointer (to int), and int a[] notation is allowed only for convenience. Quoting the comp.lang.c FAQ:
Since arrays decay immediately into pointers, an array is never
actually passed to a function. You can pretend that a function
receives an array as a parameter, and illustrate it by declaring the
corresponding parameter as an array:
void f(char a[])
Interpreted literally, this declaration would have no use, so the
compiler turns around and pretends that you'd written a pointer
declaration, since that's what the function will in fact receive:
void f(char *a)
This conversion of array-like declarators into pointers holds
only within function formal parameter declarations, nowhere else. If
the conversion bothers you, you're under no compulsion to make use of
it; many programmers have concluded that the confusion it causes
outweighs the small advantage of having the declaration ``look like''
the call or the uses within the function.

Resources