Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

difference between pointer to an array and pointer to the first element of an array

int (*arr)[5] means arr is a pointer-to-an-array of 5 integers. Now what exactly is this pointer?

Is it the same if I declare int arr[5] where arr is the pointer to the first element?

Is arr from both the examples are the same? If not, then what exactly is a pointer-to-an-array?

like image 751
Nasif Imtiaz Ohi Avatar asked Jun 08 '14 08:06

Nasif Imtiaz Ohi


3 Answers

Theory

First off some theory (you can skip to the "Answers" section but I suggest you to read this as well):

int arr[5]

this is an array and "arr" is not the pointer to the first element of the array. Under specific circumstances (i.e. passing them as lvalues to a function) they decay into pointers: you lose the ability of calling sizeof on them.

Under normal circumstances an array is an array and a pointer is a pointer and they're two totally different things.

When dealing with a decayed pointer and the pointer to the array you wrote, they behave exactly the same but there's a caveat: an array of type T can decay into a pointer of type T, but only once (or one level-deep). The newly created decayed type cannot further decay into anything else.

This means that a bidimensional array like

int array1[2][2] = {{0, 1}, {2, 3}};

can't be passed to

void function1(int **a);

because it would imply a two-levels decaying and that's not allowed (you lose how elements of the array are laid out). The followings would instead work:

void function1(int a[][2]);
void function1(int a[2][2]);

In the case of a 1-dimensional array passed as lvalue to a function you can have it decayed into a simple pointer and in that case you can use it as you would with any other pointer.


Answers

Answering your questions:

int (*arr)[5]

this is a pointer to an array and you can think of the "being an array of 5 integers" as being its type, i.e. you can't use it to point to an array of 3 integers.

int arr[5]

this is an array and will always behave as an array except when you pass it as an lvalue

int* ptrToArr = arr;

in that case the array decays (with all the exceptions above I cited) and you get a pointer and you can use it as you want.

And: no, they're not equal otherwise something like this would be allowed

int (*arr)[5]
int* ptrToArr = arr; // NOT ALLOWED

Error cannot convert ‘int (*)[5]’ to ‘int*’ in initialization

they're both pointers but the difference is in their type.

like image 175
Marco A. Avatar answered Oct 16 '22 20:10

Marco A.


At runtime, a pointer is a "just a pointer" regardless of what it points to, the difference is a semantic one; pointer-to-array conveys a different meaning (to the compiler) compared with pointer-to-element

When dealing with a pointer-to-array, you are pointing to an array of a specified size - and the compiler will ensure that you can only point-to an array of that size.

i.e. this code will compile

int theArray[5];
int (*ptrToArray)[5];
ptrToArray = &theArray;    // OK

but this will break:

int anotherArray[10];
int (*ptrToArray)[5];
ptrToArray = &anotherArray;    // ERROR!

When dealing with a pointer-to-element, you may point to any object in memory with a matching type. (It doesn't necessarily even need to be in an array; the compiler will not make any assumptions or restrict you in any way)

i.e.

int theArray[5];
int* ptrToElement = &theArray[0];  // OK - Pointer-to element 0

and..

int anotherArray[10];
int* ptrToElement = &anotherArray[0];   // Also OK!

In summary, the data type int* does not imply any knowledge of an array, however the data type int (*)[5] implies an array, which must contain exactly 5 elements.

like image 10
Ben Cottrell Avatar answered Oct 16 '22 20:10

Ben Cottrell


A pointer to an array is a pointer to an array of a certain type. The type includes the type of the elements, as well as the size. You cannot assign an array of a different type to it:

int (*arr)[5]; 
int a[5];
arr = &a; // OK
int b[42];
arr = &b; // ERROR: b is not of type int[5].

A pointer to the first element of an array can point to the beginning of any array with the right type of element (in fact, it can point to any element in the array):

int* arr; 
int a[5];
arr = &a[0]; // OK
int b[42];
arr = &b[0]; // OK
arr = &b[9]; // OK

Note that in C and C++, arrays decay to pointers to the type of their elements in certain contexts. This is why it is possible to do this:

int* arr; 
int a[5];
arr = a; // OK, a decays to int*, points to &a[0]

Here, the type of arr (int*) is not the same as that of a (int[5]), but a decays to an int* pointing to its first element, making the assignment legal.

like image 7
juanchopanza Avatar answered Oct 16 '22 18:10

juanchopanza