Skip to the content of the web site.

Understanding C type declarations

Understanding types declarations

Why is * used for both declaring pointers and dereferencing them? Basically, the notation of a variable declaration says what you must do to something to get something of the specified type. For example:

int x;
To get an integer, just use x.
int *x;
To get an integer, you must use *x.
int x[3];
To get an integer, you must use x[n].
int f(int, double);
To get an integer, you must call f(n, x) where n is an integer, and x is a double.
int *g(void);
To get an integer, you must call g() and then dereference the result.

This is always the way that variables are declared in C.

Now, how about the declaration

     int *r[10];

Is this

  1. A pointer to an array of integers, or
  2. An array of 10 pointers to integers?

At this point, you must look at an operator precedence table to determine that if you were to call

     *r[7];

then r[7] is evaluated first, so an array entry is accessed, and then it is dereferenced. Therefore, it must be an array of 10 pointers to integers.

How do you get the other? How do you declare a variable to be a pointer to an array of 10 integers? Like defining precedence for addition and multiplication, we too can use brackets for types:

     int (*r)[10];

That is, if you dereference r and then use brackets, you get an integer.

For more fun with C declarations, see cdecl.

int const *r versus int *const r

One of these declares that r cannot be changed, while the other declares that the value of r cannot be changed. From our reasoning above, we should be able to determine this:

int const *r
The thing that is const is *r, that is, the integer value is constant. Therefore, you can assign to r, but you cannot assign to *r.
int *const r
The thing that is const is r, that is, something that must be dereferenced before it can be interpreted as an integer. Therefore, you can assign to *r, but you cannot assign to r.

Note that const int *r is identical to int const *r.

Also note that int const *const r and const int *const r also both mean the same thing: you cannot assign to r and you cannot assign to *r, either.