Search code examples
c++arrayspointerscomputer-science

Array decay, passing and recieving pointers to arrays


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


Solution

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