Reputation:
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
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
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