views:

210

answers:

7

Although I use std::vector almost all the time, I am interested in understanding as much as I can about pointers. Examples of what I am talking about:

char* array[5]; // What does it mean?
// 1) pointer to an array of 5 elements!
// 2) an array of 5 pointers?

I am interested in the precise definition of this declaration.

+3  A: 

Not just pointers and arrays: How to interpret complex C/C++ declarations:

Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.

One small change to the right-left rule: When you start reading the declaration for the first time, you have to start from the identifier, and not the innermost parentheses.

You example:

char* array[5];

Is an array of 5 pointers to char.

Mitch Wheat
Thanks, nice article :)
AraK
+1  A: 

char * is the type and you have an array of 5 of them.

Philip Davis
+2  A: 

cdecl is a program which is nice for this sort of thing. (particularly when you add function pointers into the mix!)

Type `help' or `?' for help
cdecl> explain char* foo[5]
declare foo as array 5 of pointer to char
cdecl> declare bar as array 5 of pointer to function (integer, integer) returning char
char (*bar[5])(int , int )
Captain Segfault
Link to website: http://www.cdecl.org/
Casebash
+2  A: 

I learned the clockwise/spiral rule long ago from some magazine article. Here's an online article that describes the technique:

It's served me well, though I still struggle mightily with some of the monstrous template-based declarations I come across at times.

Michael Burr
+1  A: 

[] has higher precedence than *, that's why it's an array of pointers and not the other way around.

DevFred
+1  A: 

you always read pointers from right to left interpreting the '*' as a pointer. for example char** a[5] is an array of 5 pointers to pointers of characters...

Mustafa A. Jabbar
+1  A: 

The general procedure for reading a type in C/C++ is:

  1. Identify the final type, which can be a basic type or a typedef identifier, and which can have type modifiers such as const, volatile, etc. In your example that's "char".
  2. Apply the operators to the identifier in the same order of precedence as they have in expressions. These operators can be * (dereference), [] (index) and () (call function).

In the original philosophy of the syntax, your example would have been written "char *array[5]", the identifier is "array" and the operators are [] (index) then * (dereference).

The declaration then reads like a contract "if you apply these operators in that order, then you get an object of the final type".

In your case the full sentence is "if you index the variable "array", then dereference the resulting expression, you get a char".

You can also consider it like that "if you index the variable "array", then you get an object such that if you dereference it, you get a char"

The trick is mostly to keep track of the fact that [] and () have a higher precedence than *. You can control the operator order with parentheses just like for regular expressions.

lhenrygr