If I write
int *columns[32];
am I defining an array with 32 pointers to int
s?
Or is it a pointer to an array of 32 int
s?
How do I differentiate between the two? Is there a difference?
If I write
int *columns[32];
am I defining an array with 32 pointers to int
s?
Or is it a pointer to an array of 32 int
s?
How do I differentiate between the two? Is there a difference?
When in doubt - ask cdecl
$> cdecl
Type `help' or `?' for help
cdecl> explain int *columns[32]
declare columns as array 32 of pointer to int
EDIT In response to comments: I found cdecl source on Google Code Search. It requires GNU readline library. I think it shouldn't be a problem to compile it on Mac OS X or Windows.
A test program is illustrative, especially to those of us who aren't language lawyers:
$ gcc -x c -
#include <stdio.h>
int main(void)
{
int *columns[32];
printf("%lu\n%lu\n", sizeof(columns), sizeof(columns[0]));
return 0;
}
$ ./a.out
128
4
$
It appears to be an array of pointers.
You are defining an array of 32 pointers.
To define a pointer to an array of 32 ints you have to do
int (*columns)[32];
The former declaration instantiates an array with space for 32 * sizeof(int). On the other hand, the latter instantiates a single uninitialized pointer which you can then use as follows:
int myintegers[32] = {0, 1, 2, ..., 31};
int (*columns)[32];
columns = &myintegers;
printf("%d\n", (*columns)[2]);
I hope I made the difference a little bit clear.
It is an array of 32 pointers to int
and yes it does matter.
The C grammar rules specify that array access ([]
) binds tighter than dereference (*
) and declarations mirror usage.
The declaration int *columns[32];
means that the expression *columns[n]
(where n
is a number between 0 and 31) is an int
. This expression is the same as *(columns[n])
. The declaration allocates the space for 32 pointers, but there are no int
s allocated and (assuming that this is a function local declaration) none of the pointers are initialized.
Had the declaration been int (*columns)[32];
then the expression (*columns)[n]
would have been an int
, meaning that the *
dereference happens before the array access, so columns would have been a pointer to an array of 32 int
s. The declaration would have allocated one pointer, but no arrays of int
s.
Here are some fun declarations for you:
int *arrayOfIntP[32];
int (*pointerToArrayOf32)[32];
For more fun with multidimensional arrays look at these posts:
One trick is to read from right to left.
Given int* cols[32];
All that left of array is the type of the elements in the array. So we read it as array of pointers to int (and of count 32).
Expanding on a comment to another answer:
There's a fairly straightforward procedure for reading C declarations. Start with the leftmost identifier in the declarator and work your way out, remembering that []
and ()
bind before *
. Given the declaration
int *columns[32];
break it down as
columns -- columns
columns[32] -- is a 32-element array
*columns[32] -- of pointers
int *columns[32] -- to int.
If the declaration had been
int (*columns)[32];
then it would break down as
columns -- columns
(*columns) -- is a pointer
(*columns)[32] -- to a 32-element array
int (*columns)[32] -- of int.
This will also help you build up complex declarations. Suppose you wanted to declare an array of pointers to functions returning pointers to arrays of char:
f -- f
f[N] -- is an N-element array
*f[N] -- of pointers
(*f[N])() -- to functions
*(*f[N])() -- returning pointers
(*(*f[N])())[M] -- to M-element arrays
*(*(*f[N])())[M] -- of pointers
char *(*(*f[N])())[M]; -- to char
cdecl is a nice tool, but after you'd done this exercise a few times, you shouldn't need it.
Refer to Question #5 of A 'C' Test: The 0x10 Best Questions for Would-be Embedded Programmers by Nigel Jones*
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
*Alas, the original article on embedded.com can no longer be found on their website.