0

I am a beginner to data structures and algorithms, started studying the pointers now and before asking the question here I read this recommended post but I couldn't understand it so I am asking the query here.

I have been told by a friend that array's name is a pointer to the first value in the array, as arr returns the address of arr[0], arr+1 returns address of arr[1], so when I write this

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int i = 10;
    int arr[3] = {1, 2, 3};
    int *ptr = &i;
    cout << arr << "   " << &arr << endl;
    cout << ptr << "   " << &ptr;
    return 0;
}

Both arr and &arr give same result

0x61ff00 0x61ff00

While ptr and &ptr give different results

0x61ff0c 0x61fefc

Can someone tell me why is this happening ?

  • 5
    Because arrays and pointers are not the same thing, even if your teacher said they were. – user253751 Jun 01 '22 at 13:39
  • No, a friend told me that but thank you for clarifying this. – Itachi Uchiha Jun 01 '22 at 13:42
  • You should read about [_array-to-pointer-decay_](https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay) to figure out what your friend actually meant. – πάντα ῥεῖ Jun 01 '22 at 13:44
  • 1
    The address of an array is the same address as the first element of the array. A pointer is a unique variable that holds an address. The address it holds need not (and often isn't) be the same as the address of the pointer itself. – NathanOliver Jun 01 '22 at 13:45
  • The `arr` is of type `int [3]`. An `int *` is of type `int *`. An `int[3]` is not an `int *`. – PaulMcKenzie Jun 01 '22 at 13:45
  • 1
    *Both `arr` and `&arr` give same result* Actually, they don't. The address value is the same, but the **type** is different. – Eljay Jun 01 '22 at 13:51
  • Good question. Arrays and pointers are two different types, but the name of an array in almost all situations "decays" into a pointer to the first element, so they often do the same thing. But not always... – Pete Becker Jun 01 '22 at 13:54
  • @NathanOliver when can it be same and when not ?? – Itachi Uchiha Jun 01 '22 at 13:55
  • @PeteBecker when do they do same thing and when do they don't ? If there's a text please share I'll read it to not make mistake again. – Itachi Uchiha Jun 01 '22 at 13:56
  • @ItachiUchiha I take it back, I don't think they can ever be the same, without resorting to undefined behavior. – NathanOliver Jun 01 '22 at 13:57
  • @πάνταῥεῖ ohh so unless I typecast it for some reason arr will not behave like a pointer right. It will have separate properties. edit :- I read the second answer ( and comments on it ) in your referred link, guy was bashed for writing "Arrays are basically the same as pointers in C/C++, but not quite." So I guess I'll treat them differently now. Thanks – Itachi Uchiha Jun 01 '22 at 13:58
  • @ItachiUchiha -- Another difference -- `std::cout << sizeof(arr) << "\n" << sizeof(ptr);` -- You will see different values. – PaulMcKenzie Jun 01 '22 at 14:03
  • @PaulMcKenzie yeah sizeof (arr) gives ( length of array * size of array's datatype ) while ptr just gives size of the datatype ( which is int here ) it is referring to – Itachi Uchiha Jun 01 '22 at 14:05
  • @ItachiUchiha Pretty much every time that using the array doesn't make sense but a pointer does make sense, `arr` is short for `&arr[0]`. E.g. if you try to give it to a function, return it, or assign it to a pointer variable – user253751 Jun 01 '22 at 14:14
  • @ItachiUchiha The data type for an `int *` is an `int *`, not `int`. For example, if you are on Windows and run a 32-bit application, `sizeof(int *)` gives you 4, while on a 64-bit application, `sizeof(int *)` gives you 8. The `sizeof(int)` does not change if you run 32-bit or 64-bit apps (it will give you 4, regardless of the bitness of the OS). – PaulMcKenzie Jun 01 '22 at 14:25

2 Answers2

2

Arrays are not pointers!

Arrays do decay to a pointer to their first element in all sorts of circumstances. For example std::cout << arr; actually prints the memory address of the first element of the array. std::cout << &arr; prints the memory address of the array. As the address of the first element is the same as the address of the array you see the same value.

However, just because they have the same value, does not mean they are the same. arr can decay to a int*, while &arr is a pointer to an array, a int(*)[3].

I hope the following will help to clear things up a little:

#include <iostream>
#include <type_traits>


void make_it_decay(int x[]) {
    std::cout << std::is_same_v< decltype(x), int*> << "\n";
}

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

    //std::cout << (arr == &arr) << "\n";  // does not compile !
    std::cout << (arr == &(arr[0])) << "\n";

    std::cout << std::is_same_v< decltype(arr), int[3]> << "\n";
    std::cout << std::is_same_v< decltype(&arr),int(*)[3]> << "\n";
    std::cout << std::is_same_v< decltype(&arr[0]), int* > << "\n";
    make_it_decay(arr);
}

output:

1
1
1
1
1

I use decltype to infer the type of certain expressions and std::is_same_v to see if the expressions are of same type.

arr is of type int[3]. It is an array. It is not a pointer.

&arr is the address of the array. It is a pointer to an array with three elements, a int(*)[3].

&arr[0] even though it has the same value as &arr is of different type. It is a pointer to int, an int*.

When we pass arr to a function then it decays to a pointer to the first element of the array. And we can see that inside the function x is int*.


Now to your quesiton...

Above I tried to lay out what happens when you write std::cout << arr. Pointers are different, because ... well arrays are not pointers.

std::cout << ptr;  // prints the value ptr
std::cout << &ptr; // prints the address of ptr

Perhaps some visualization helps. The difference in types gets most apparent when incrementing the pointers

 -------------------
 | arr             |
 -------------------
 |  1  |  2  |  3  |
 -------------------
   ^       ^         ^
   &arr    |         &arr + 1 
   &arr[0] |
           &arr[0] + 1
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

array's name is a pointer to the first value in the array

The above statement is not technically correct. What happens is that in many contexts the array decays to a pointer to its first element due to type decay. This means, in your example, when you wrote std::cout << arr, there was an implicit array-to-pointer conversion which converted your array arr of type int[3] to a pointer to its first element which is the type int*.

Note

Note also that even though the decayed pointer and the address of the array both have the same value their types are different. The decayed pointer is of type int* while the &arr is of type int (*)[3].

Jason
  • 36,170
  • 5
  • 26
  • 60