user623990
user623990

Reputation:

C++ pointer vs array notation

When I declare a new array like this:

int foo[5]

Is foo really a pointer to the first element of the array? Would I be able to do this:

*(foo+2)

to access the third element of the array? Let's say I'm making a 2D array:

int foo[3][4]

Is foo now a int**?

Upvotes: 7

Views: 3275

Answers (2)

AnArrayOfFunctions
AnArrayOfFunctions

Reputation: 3744

No, 'foo' is an array type in both cases but when a pointer is expected in expression with 'foo', it's implicitly converted to one (which points to the array first element). All arrays have this behavior. In the case, as addition can be done via pointer types, but not with arrays, 'foo' is converted to 'int *'.

*(foo+2) // 'foo' is implicitly converted into 'int *', pointing to 'foo' first element

foo + 1 //same as above

But now you may ask, what are the properties of the 'array' type and why we should ever use it, instead of the implicit pointer to first element cast. The things is that they are not much. You can tell the size of an object with type array like this:

sizeof(foo) //returns the size which array 'foo' occupies 

And get it's address by using the '&' operator:

&foo // '&foo' has type of 'int (*)[5]'

You can also create functions with parameters of 'array' reference (or pointer) type in order to accept only ones with specified size (which is not possible if they are just pointers and expect arrays passed to decay into such). Example:

void func(int (&)[5]);

void func1(int (*arg)[5]); // should be accessed by '*arg', allow the use of null-pointers

void func2(int *); //same as the misleading 'void func2(int [5])' or 'void func2(int [6])' etc.

int foo[5];

int foo1[6];

func(foo); // 'foo' type is ('int [5]') - ok

func1(&foo); // '&foo' type is ('int (*)[5]') - ok

func(foo1); // 'foo1' type is ('int [6]') - not allowed, param type is 'int (&)[5]' !

func1(&foo1); // '&foo1' type is ('int (*)[6]') - not allowed, param type is 'int (*)[5]' !

func2(foo); // 'foo' is implicitly converted to 'int *' - ok

func2(foo1); // 'foo1' is implicitly converted to 'int *' - ok

In the second case when the array is 2D - the same properties are applied. It's declaration means this: 'an array of 3 elements with type array of 4 elements with type int' So it's actually just an array of arrays and nothing more. It's implicit pointer to first element conversion is not of type 'int **' but instead of 'int (*)[4]', as each element of it is another array.

The declaration can be written this way too:

int (foo[3])[4];

Also note 'arrays' cannot be assigned, so they can't be passed by value or returned by functions. What I mean is:

int funcReturningArray()[2]; //not allowed

int funcAcceptingArray(int [2]); //just converted into pointer

int funcAcceptingArray(int *); //same as above

Although array parameters are syntactically accepted because of legacy reasons (or because something else ?), their real meaning is never tolerated and they are just 'adjusted' to pointers.

Note: The implicit conversion of array type to a pointer of it's first element is sometimes called 'Array to pointer decay'.

Upvotes: 6

Vlad from Moscow
Vlad from Moscow

Reputation: 310970

No arrays are not pointers but in expressions they are converted to rvalue pointer to their first elements. So in this expression

*(foo+2)

at first foo is converted to rvalue pointer and then the pointer arithmetic is used.

For this array declaration

int foo[3][4];

name foo used in expressions is converted to rvalue pointer of type int ( * )[4]

The word rvalue means that for example you may not write ++foo

That is the compiler for the array name used in expressions creates a temporary object that is a poimnter to the first element of the array.

Take into account that if you are using for example operator sizeof with an array name then the last will not be converted to a pointer. So for your last array definition

sizeof( foo )

will be equivalent to

3 * 4 * sizeof( int )

while

sizeof( int ( * )[4] )

will return the size of the pointer itself.

And at last if you will apply operator & to an array name then you will get a pointer to the array itself. For example

int foo[3][4];

int ( *ptr_to_foo )[3][4] = &foo;

Upvotes: -3

Related Questions