Reputation: 55
I am new to C++ and to programming in general. I got confused when I learnt the concepts of pointer and array.
Takes int*p = arr; int arr[]={5,1};
as an example. I learnt that arr
is also a pointer.
p(a pointer) arr[0]
the thing it stores: [first element address: 601] [5]
its memory : 501 601
address(just make
some fake address)
However, arr(the pointer)
[first element address: 601]
601
Normally, a pointer should have a different address from the array. However, the arr
, as the pointer to the first element, has the same address as the first element. So I feel confused. And I wonder whether it is because the memory box of arr[0]
is split into two parts: one part for arr[0]
, and one part for the pointer arr
, so that they have the same address in memory.
Upvotes: 0
Views: 106
Reputation: 15941
I learnt that
arr
is also a pointer.
Then you were taught something wrong, which is probably the reason for your confusion.
If you have int arr[] = {5, 1};
then arr
is an array, not a pointer. An array can implicitly be converted to a pointer to its first element. But the array itself is still an array. For example, make an int arr[512];
and check what sizeof(arr)
is going to be. If arr
were a pointer, then that should be the same as sizeof(int*)
. But it isn't because arrays are not pointers. They are arrays…
If you write
int arr[] = {5, 1, 3};
int* p = arr;
what you end up with is something like this:
arr
+---+---+---+
0xA0: | 5 | 1 | 3 |
+---+---+---+
p
+-------+
0xB0: | 0xA0 |
+-------+
Somewhere in memory, let's say at address 0xA0, there will be an object that is an array of three int
. The identifier arr
is just a name that denotes this array object in you code. The array object contains three int
objects placed one after the other. The individual int
s (elements of the array) are subobjects of the complete array object. Note that the address of the complete array object is the same as the address of the subobject that is the first array element. Nevertheless, there is a difference between the array object arr
, which is of type int[3]
and encompasses the whole array, and the first element, which is of type int
.
Also in memory, let's say at address 0xB0, there will be another object of type int*
. The identifier p
is just a name that denotes this pointer object in your code. p
is a completely separate object from arr
. It exists at a completely different address. p
was initialized to point to the result of the expression arr
. The expression arr
denotes our array. Pointers and arrays are completely different things. In what way does it make sense to assign an array to a pointer!? What is going on?
To understand why int* p = arr;
works and what it does, let's back up a little and think about how we would actually access an element of arr
. If we know the address at which array elements start, we can simply compute the address of any element by just adding the element size times the element index. This is precisely how pointer arithmetic works in C++ (which is not a coincidence): given a pointer p
to the first element of an array, we can get a pointer to the i
-th element by just adding them together: p + i
. In fact, the subscripting operator []
for element access such as p[i]
is literally defined as just shorthand notation for *(p + i)
.
Thus, while arrays and pointers are completely different things, arrays only really become useful once pointers enter the picture. Using an array generally requires accessing its elements. Accessing the elements of an array generally requires pointers. Since you generally need a pointer to the first element to really use an array for anything, arrays can implicitly be converted to a pointer to their first element in C and C++.
When you write p = arr
what you're really writing is p = &arr[0]
. Because, while you cannot assign an array to a pointer, an array of int
can implicitly be converted to an int*
that points to the first element of the array. And that int*
can be assigned to a pointer. And that's why p
in our example above will contain the address of the first element of the array (which happens to be the same as the address of the array).
However, since arrays are arrays, not pointers (they just can be converted to a pointer to the first element if necessary), taking the address of an array like &arr
will result in a pointer to the array object itself (which, as we have seen, has the same address as the first element). The type of &arr
will be int(*)[3]
(pointer to array of three int
). Unlike &p
, which will actually be a pointer to a pointer to int
…
Note: When you write arr[2]
, what you're really writing is *((&arr[0]) + 2)
because the []
operator works on pointers. And arrays are not pointers but can implicitly be converted into a pointer to their first element…
Upvotes: 1
Reputation: 1403
I would suggest that pointers are not a beginner topic in C++, they are mostly just a carry over from C. If you can, you should avoid them and use the STL Containers.
In your code sample, the type of arr
is int[2]
. You should think of that in memory as looking something like this:
arr --+
|
v
+---+---+
| 5 | 1 |
+---+---+
The value contained in arr
is the location of the first element (the 5
). arr
is essentially a pointer to that 5
. The only difference being that the type (int[2]
) has also remembered how many elements there are.
The assignment statement p = arr
works because p
's type is int*
which int[]
can decay to.
Upvotes: 0