Let's dissect this carefully, since array-to-pointer conversions are sometimes confusing.
int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
arr
is now an array of 3 arrays of 3 ints.
int *pArr = *arr;
*arr
uses the array arr in expression, so it decays to a pointer to the first element of arr -- that is pointer to array of 3 ints (the array containing {1,2,0}). Dereferencing that pointer (with *
) gives you the array of 3 ints. Now you're using that array in an expression and it decays to a pointer to int, which is assigned to pArr.
(&pArr[0])[1] = 3;
pArr[0]
gives the integer at which pArr is pointing (the number 1). &pArr[0]
makes a pointer at that integer (which is actually equal to pArr). Indexing that pointer with [1] gives a reference to the next integer after the number 1, which is the number 2. To that reference you're assigning 3. Here's the catch: pointer to an element of an array can only be used to access other elements of the same array. Your pointer points at an element of the array {1, 2, 0}, which you've changed to {1, 3, 0}, and that's fine, but
func(&pArr);
Now you're creating a pointer to pointer to int (since pArr was a pointer to int), and passing that to your function.
ptr[0][1] = 5;
And now you've taken ptr[0]
, which evaluates to the pointed-to object, which is your original pointer pArr. This line is equivalent to pArr[1] = 5;
, and that is still valid (changing your {1,2,0} array to {1,5,0}). However, ptr[1][...
would be invalid, because ptr is not pointing at an element of an array of any kind. It's pointing at a standalone pointer. Incrementing ptr will make it point at uninitialized memory and dereferencing that will be undefined behavior.
And for the additional questions:
You should not be able to write this:
int arr[] = { 1, 2, 3, 4, 5 };
int *pArr = *arr;
The array arr
decays to a pointer-to-int (pointing at the number 1), dereferencing that gives the integer, and an integer cannot be assigned to the pointer pArr. gcc says error: invalid conversion from 'int' to 'int'*.
Likewise, you cannot write this:
int arr[][3] = {{1, 2,}, {3, 4}, {5, 6}};
int *pArr = **arr;
for the same reason: *arr is the array of 3 ints {1, 2, 0}, **arr is the integer 1, and an integer cannot be assigned to a pointer.