2

I have written this simple program

 #include <iostream>

 using namespace std;

 int main (){
     int arr [5] = {1,2,3,4,5};

     cout<<arr<<endl; //Line 1
     cout<<&arr<<endl; //Line 2

     cout<<sizeof(arr)<<endl; //Line 3
     cout<<sizeof(&arr)<<endl; //Line 4
 }

What I expected was:

  • Line 1: arr is the name of the array, and it is a pointer to the first element arr = &arr[0], hence address of &arr[0] will be printed out
  • Line 2: address of arr[0] will be printed out, &arr = arr
  • Line 3: sizeof(arr) is getting the sizof(a pointer) since arr is a pointer, and I should get 4 bytes

  • Line 4: sizeof(&arr) is the same as Line 3, since &arr is of type pointer, and I should get 4 bytes

But instead in Line3: I get 20 bytes (sizof(int)*number of integers)

enter image description here

How come in Line2: arr acts like a pointer, and in Line3 it acts as an array

I know that an array is not a pointer, but when passed to a function it decays to a pointer, sizeof(..) is an operator, and hence it treats arr as an array, but so is <<, it is an operator not a function

schorsch312
  • 5,553
  • 5
  • 28
  • 57
Embedded_Dude
  • 227
  • 3
  • 9
  • I'm confused. You state that you know that an array is not a pointer (it is not indeed), and then you carry on saying that `arr` is a pointer. It's not a pointer, it's an array! `sizeof` does not trigger array-to-pointer decay. – Quentin Mar 26 '18 at 07:50
  • 2
    "*but when passed to a function it decays to a pointer*" If the function parameter is a pointer. – juanchopanza Mar 26 '18 at 08:00
  • @Forat - Specifically look at [this answer](https://stackoverflow.com/a/8916698/597607) to see why the array and its first element can have the same address. – Bo Persson Mar 26 '18 at 10:54

2 Answers2

4

I know that an array is not a pointer, but when passed to a function it decays to a pointer, sizeof(..) is an operator, and hence it treats arr as an array

That's right. Hence you got 20 bytes on line 2.

but so is <<, it is an operator not a function

In fact, when << is used with anything except built-in integer types, it's a user-defined function (see operator overloading). So it works as expected.

Matt
  • 13,674
  • 1
  • 18
  • 27
  • so since, `<<` is user defined, and won't work properly with integers, arr will decay to a pointer to the first element, did I get that correctly? – Embedded_Dude Mar 26 '18 at 07:50
  • @Forat `<<` works with integers, but here there's no integer at all. So this one is an equivalent of `cout.operator<<(arr);`, where `operator<<` is a special function. – Matt Mar 26 '18 at 07:53
  • @Forat no relation to the integers in the array, it could be an array of any type (okay, except *cv* `char`). The overload of `<<` that's getting picked up is for `void*`. Passing the array itself would require an `int (&)[N]` overload. – Quentin Mar 26 '18 at 07:54
  • There is nothing to do with functions. For example, there is a decay in `arr+1` while `+` is a builtin operator, and there is no decay in `f(arr)` for `void f(int(&)[5]);` even if `f` is a function. – xskxzr Mar 26 '18 at 09:07
2

To understand Line2 you really need to understand the difference between an array and a pointer. First off when you declare an array you declare the type that array holds (int) then you reserve a multiple of (int) sized bytes that make up the array. Make no mistake an array is THE ENTIRE ARRAY STRUCTURE.

int arr[5] = {1, 2, 3, 4, 5};

If you wanted to figure out the size (in bytes) of an int on your current machine you could ask for the size of an individual element of your array just as you did in Line4.

sizeof &arr
// this is equivalent to ...
sizeof &arr[0]
// you could also ask for just ...
sizeof arr[0]

These would all return you 4 bytes (the size of an int on your machine).

Understand that an arr itself does not have an address. Think about when you pass an array to a function, you are only passing the address of the first element. Therefor these two function declarations are exactly the same:

int foo(char *arr);
int foo(char arr[]);

So when in Line3 you ask for the size of the array you are asking for the size of THE ENTIRE array. (5*4 bytes) = 20 bytes

Also extremely important to understand is that when you pass an array to a function you are passing ONLY the address of the first element in the array. So if you created a function:

int array_size(char arr[]) { return sizeof arr; }

int main() {
    int foo[5] = { 1, 2, 3, 4, 5 };
    std::cout << "Foo size: " << array_size(foo) << std::endl;
    std::cout << "Foo size: " << sizeof foo << std::endl;
    return 0;
}

The result:

Foo size: 4
Foo size: 20
Spencer Duball
  • 531
  • 2
  • 6
  • 18