7

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**?

  • 11
    *Is foo really a point to the first element of the array?* - No, it's an array. *Is foo now a int\*\*?* - No, it's a 2D array. See [arrays](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c) – chris Dec 05 '14 at 13:27
  • @chris, so if I wanted to iterate over it using pointer notation, I'd need to make a `int* ptr = &foo[0]`? –  Dec 05 '14 at 13:29
  • @maxmackie `int* ptr = foo` would be enough. –  Dec 05 '14 at 13:29
  • 3
    Have a look here: http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c?lq=1 – Stefan Dec 05 '14 at 13:31
  • Why do you prefer to use `*(foo+2)` over `foo[2]` ? (also valid for pointer BTW). – Jarod42 Dec 05 '14 at 13:32
  • @Stefan, that's an amazing FAQ - thank you. –  Dec 05 '14 at 13:34
  • @Jarod42, the parallel between both pointers and arrays are a little confusing to me. So I guess it was my logical conclusion to assume declaring an array was giving me a pointer to the first element. I get it now though. –  Dec 05 '14 at 13:35
  • 2
    @maxmackie - There is a difference between the `syntax` you can use, and the actual type. An array is not a pointer, and a pointer is not an array. Yes, you can use array/pointer `syntax` to get to the various elements, but the types are not the same. – PaulMcKenzie Dec 05 '14 at 13:39
  • In this case C++ works the same as C: http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c/1641963#1641963 – Thomas Padron-McCarthy Dec 05 '14 at 14:16

2 Answers2

6

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'.

AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
  • Generally correct answer, but it could be improved: 1. You should probably say that the array *decays* into a pointer instead of "it's implicitly casted to one". The word cast usually implies that the programmer forces the compiler to do something against its better knowledge, not that something implicitly and effortlessly changes type under the hood. You could also improve the readability of the large code block significantly by drastically shortening the comments. Something like: `//error: wrong type` or `//ok: foo decays into int*`. – cmaster - reinstate monica Dec 05 '14 at 17:59
  • `decay` is the keyword. Should put that in the beginning – SwiftMango Dec 05 '14 at 18:21
-3

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;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335