0

So I read online that if you have an array like

int arr[3] = {1,2,3}

I read that if you take (arr+n) any number n it will just add sizeof(n) to the address so if n is an integer(takes up 4 bytes) it will just add 4 right? But then I also experimented on my own and read some more stuff and found that arr[i] = *(arr+i) for any i, which means it's not just adding the sizeof(i) so how exactly is this working? Because obviously arr[0] == *(arr+0) and arr[1] == *(arr+1) so it's not just adding sizeof(the number) what is it doing?

  • 1
    *"I read that if you take (arr+n) any number n it will just add sizeof(n)"* - that's wrong. it will offset `n * sizeof(Type)` from the base address, in octets, where `Type` is the underlying type of the array (in this case, `int`). So, wherever you read that, lets not go back there for further "information". – WhozCraig Mar 07 '22 at 12:35

1 Answers1

2

I read that if you take (arr+n) any number n it will just add sizeof(n) to the address

This is wrong. When n is an int (or an integer literal of type int) then sizeof(n) is the same as sizeof(int) and that is a compile time constant. What actually happens is that first arr decays to a pointer to the first element of the array. Then sizeof(int) * n is added to the pointers value (because elements type is int):

1    2    3
^         ^
|         |
arr       arr+2

This is because each element in the array occupies sizeof(int) bytes and to get to memory address of the next element you have to add sizeof(int).

[...] and read some more stuff and found that arr[i] = *(arr+i)

This is correct. For c-ararys arr[i] is just shorthand way of writing *(arr+i).


When you write some_pointer + x then how much the pointer value is incremented depends on the type of the pointer. Consider this example:

#include <iostream>

int main(void) {
    int * x = 0;
    double * y = 0;
    std::cout << x + 2 << "\n";
    std::cout << y + 2 << "\n";
}

Possible output is

0x8
0x10

because x is incremented by 2* sizeof(int) while y is incremented by 2 * sizeof(double). Thats also the reason why you get different results here:

#include <iostream>

int main(void) {
    int x[] = {1,2,3};
    std::cout << &x + 1 <<"\n";
    std::cout << &x[0] + 1;
}

However, note that you get different output with int* x = new int[3]{1,2,3}; because then x is just a int* that points to an array, it is not an array. This distinction between arrays and pointers to arrays causes much confusion. It is important to understand that arrays are not pointers, but they often do decay to pointers to their first element.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Okay and I have another question int a[5] = { 0, 1, 2, 3, 4 }; cout << *(&a + 1) << '\n'; cout << *(a + 1) << '\n'; So I am pretty sure that when I just use 'a' like this it implicitly gets converted into &a[0] hopefully that's right? Now these two things though output totally different things one outputs an address one outputs a[1]. So what exactly is happening? I think it's because &a technically has the same address as a[0] but it has a different type so how does the arithmetic work here? – jayblosem11 Mar 07 '22 at 12:57
  • 1
    `&a` is a pointer to an array of 5 ints, `&a[0]` is a pointer to the first element of `a`. c-arrays are confusing, you will have a hard time to understand them by experimenting only, you should rather take a look here: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list. The good news is that you almost never need to use them in C++, because there is `std::vector` and `std::array` – 463035818_is_not_an_ai Mar 07 '22 at 13:05
  • Well I already have a C++ book and I don't wanna learn too much about them as I understand I won't really need to use them too much but I still wanna try to understand this now that I have encountered it. Why is (&a+1) != (a+1)? Because technically &a also has the same address as the first element of a right so what is happening here? – jayblosem11 Mar 07 '22 at 13:06
  • `&a` is a pointer to the array. In `a+1`, a first decays to a pointer to the first element (that is `&a[0]`) and is then incremented accordingly – 463035818_is_not_an_ai Mar 07 '22 at 13:07
  • 3
    `&a` and `&a[0]` have the same value, but they are of different type. Adding 1 to `&a` increments it by the size of the whole array. Adding 1 to `&a[0]` increments it by the size of one element – 463035818_is_not_an_ai Mar 07 '22 at 13:09
  • @jayblosem11 see edit – 463035818_is_not_an_ai Mar 07 '22 at 13:16
  • And is there like a simple explanation for how this works specifically though? I'm assuming `&a[0]`'s type is just `*int` right..? And `&a`'s type is `*int[5]` or something..? Not sure but then so is it fair to say something like in `(a+1)`'s case it sees the pointer type is just an int so it adds `1*sizeof(1)` but in `(&a+1)`'s case because &a is something like `*int[5]` it does something like `(&a[0] + 5*sizeof(1))` – jayblosem11 Mar 07 '22 at 13:18
  • Ok thanks I saw the edit and another tiny question how come I have this char* c = 0; cout << c; And when I try to run this it doesn't work and gives me this error: Exception thrown at 0x5B8B08F0 (ucrtbased.dll) in x.exe: 0xC0000005: Access violation reading location 0x00000000. But it works perfectly final with ints or doubles – jayblosem11 Mar 07 '22 at 15:01
  • @jayblosem11 https://stackoverflow.com/questions/10869459/why-does-streaming-a-char-pointer-to-cout-not-print-an-address – 463035818_is_not_an_ai Mar 07 '22 at 15:23