Please help me understand what happens here:
#include <iostream>
void foo(int *ar) {std::cout << sizeof(arr) << '\n' << arr[3];} // exceeding array bounds on purpose
int main()
{
int arr[2]{3, 5};
foo(arr);
return 0;
}
Is this an example of array decay? And what exactly is *arr? Is it a pointer-to-int, or is it a pointer-to-array (of int)? In case of the latter, does it carry information about the address of a memory block holding the array? If not, how is it possible to use array notation inside a function that only recieves a pointer to its first element?
Then,
#include <iostream>
void foo(int *ar) {std::cout << sizeof(arr) << '\n' << arr[1];}
int main()
{
int arr[2][1]{{3}, {5}};
foo(*arr);
return 0;
}
What happens in case of a 2D array? What does *arr represent here when passed? Is it the pointer to the first element of the right array? What does it represent when taken as an argument by a function?
edit: changed array name in foo
Yes, that is an example of an array decaying into a pointer.
int* arr
is a pointer to the first element of the array. The address is guaranteed to be the same as the address of the array, but the type is different.
In foo(*arr)
, you are dereferencing a int[2][1]
, an array of 2 elements where each element is an array of 1 element. This gives you a int(&)[1]
- a reference to an array of one elements. This then decays to a pointer to the first element of the 1 element array.
Now, why does int*arr; arr[2]
work? Well, ptr[n]
in C and C++ is defined to mean *(ptr+n)
. So much so that n[ptr]
works (!). (do NOT do n[ptr]
ever)
Array indexing on normal arrays even works this way. int arr[3]; arr[2]
is actually doing a decay-of-array-to-pointer, then doing +2
on that pointer, then dereferencing.
C was designed as a slightly portable assembly language. And in assembly, array indexing is adding (with some multiplication) then a load instruction.
pointer + int
in this model converts both to ints, then scales the int by the size of the pointed to thing, adds them up, then converts back to pointers and does a load.
The C++ and C standards doesn't actually say this is what is going on, because they both talk about things more abstractly to permit a variety of implementations to exist. But that is the model they are based off of.