0

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

  • `int *arr` is a pointer to a single `int`. The question would be more clear if you would give different names to `arr` in `main` and `arr` in `foo` – 463035818_is_not_an_ai Nov 09 '22 at 14:15
  • *Is it a pointer-to-int,* -- `void foo(int *arr)` --> It should be clear what it is, as it says right there what it is. It can't be anything else. – PaulMcKenzie Nov 09 '22 at 14:16
  • 2
    Why put all the effort in understanding pointer decay when you can use std::array and/or std::vector. In my experience using "C" style arrays only leads to bugs – Pepijn Kramer Nov 09 '22 at 14:16
  • `arr[3]` is syntactic sugar for `*(arr + 3)`. You could even do `3[arr]` for fun, but don't do that in real code. – Eljay Nov 09 '22 at 14:16
  • Example using std::array : https://onlinegdb.com/NB6b7ow_y1. In current C++ if you run into a pointer check if you can solve it in another way e.g. using one of the stl containers. – Pepijn Kramer Nov 09 '22 at 14:29
  • 1
    In the second, `*arr` is equivalent to `arr[0]`, which is an array with one element. That array behaves exactly like all other arrays. – molbdnilo Nov 09 '22 at 15:20

1 Answers1

2

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.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524