Please explain to me how the b pointer shows the last element.
Every time, it prints out the last element, no matter how long the array is. If you use *b alone in cout, it shows a number out of array.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int a[] = {1,2,3,4,5,6,7,8,9,10,11};
int *b =(int*) (&a+1);
cout << *(b-1) << endl;
return 0;
}
This expression
&a+1
has the type int ( * )[11] and points to the memory after the last element of the array a.
In this declaration
int *b =(int*) (&a+1);
you interpreted the expression as having the pointer type int * that points to after the last element of the array a. Instead you could write
int *b = a + 11;
So the expression
b - 1
points to the last element of the array a.
Thus you may imagine the expression *( b - 1 ) the following way
*( a + 11 - 1 ) => *( a + 10 ) => a[10]
Per pointer arithmetic rules, incrementing/decrementing a pointer by N elements will adjust the value of the pointer by N * sizeof(T) bytes, where T is the dereferenced type of the pointer.
&a is a pointer to the array itself, which has a type of int[11], so you have a pointer of type int(*)[11] to the beginning of the array. Lets call this A1 in the diagram below.
Adding +1 to that pointer will advance it by sizeof(int[11]) (aka sizeof(int)*11) bytes, thus producing a new int(*)[11] pointer to the memory address immediately following the entire array. Let's call this A2 in the diagram.
You are then type-casting that new pointer, so now you have a pointer of type int* to the end of the array. This is the memory address you are assigning to your int *b pointer variable. Lets call this B1 in the diagram below.
Subtracting -1 from that pointer will reduce it by sizeof(int) bytes, thus producing a new int* pointer to the memory address of the last int element in the array. Lets call this B2 in the diagram below.
So, when you dereference b to print the int that it is pointing at, you are printing the value of the last int in the array. If you don't decrement b, it is pointing past the end of the array, and you have undefined behavior. You might just print out random garbage, or you might crash your app. Anything could happen.
---------------------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---------------------------------------------------------------------
^ ^ ^
| | |
|_A1 --------------------------------------------------------|----->|_A2
+1 | |
|_B2 <-|_B1
-1
Related
In http://www.fredosaurus.com/notes-cpp/arrayptr/array-diagrams.html website, it states that
Pointers hold the memory address of other data and are represented by a black disk with an arrow pointing to the data it references.
For example,
int a[5]; // Allocates memory for 5 ints.
. . .
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
would result in.
My question is how can I print the address of the pointer pointing to the array?
I know that &a or &a[0] gives us the address of the first element. But how can I access the pointer pointing the array?
An array and a pointer are not the same thing. What the memory really looks like is this:
a
-------
| 1 | a[0]
-------
| 2 | a[1]
-------
| 4 | a[2]
-------
| 8 | a[3]
-------
| 16 | a[4]
-------
So if you were to print a and &a, you would see that they print the same value.
If the array is on the stack as it would be in your example code then the image below is a more accurate representation of how the memory would be laid out. I've also added an additional pointer to hopefully add some clarification.
int a[5];
a[0] = 1;
for (int i=1; i<5; i++)
a[i] = a[i-1] * 2;
int* b = a;
It may be easier to think of the [] notation of defining an array as a little syntactic sugar. When calling functions and passing in a the function will be called with the address of a[0] being passed in.
When passing b to a function it's the value that will be passed in, which is the address of a.
You can have lots of pointers pointing to a[0].
Just as for a pointer to the array, create a pointer variable pointing to a[0] and then take a pointer to it. You will have one pointer to one pointer pointing to the array.
I know that &a or &a[0] gives us the address of the first element.
Technically. &a is in fact the address of the array itself. It just has the same value as address of the first element. But note that the type of the expression is different. &a is a int (*)[5] (pointer to an array of 5 integers), while &a[0] is a int* (pointer to an integer).
My question is how can I print the address of the pointer pointing to the array?
First step is to have a pointer. You don't have any pointer variables in your example. An array is not a pointer. The sentence "The actual array variable, a in this example, is a pointer to the memory for all of its elements." of the page is very misleading, as an array is not a pointer object. The drawn diagram is not correct for the program.
Here is a program that is correct according to the diagram:
int array[5]; // Allocates memory for 5 ints.
int* a = array; // a pointer to the first element of the array
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
Here we actually have a pointer. Now you can print the address of the pointer:
std::cout << &a;
I thought a[] and *a are the same thing because they work like pointers. Yet I encountered something unexpected in the following code:
#include <iostream>
using namespace std;
class F {
public:
bool a[];
F();
};
F::F() {
*a = new bool[5];
a[2] = true;
}
int main() {
F obj;
if(obj.a[2])
cout << '?';
return 0;
}
This code prints ?, but I don't understand how it works. When:
*a = new bool[5];
is changed into:
a = new bool[5];
compiler reports:
F:\main.cpp|11|error: incompatible types in assignment of 'bool*' to 'bool [0]'|
I found this behaviour weird, so I was playing around with this code. When I changed the type of a from bool to int compiler always reports an error
F:\main.cpp|11|error: invalid conversion from 'int*' to 'int' [-fpermissive]|
Why does this work the way it does?
I thought a[] and *a are the same thing because they work like pointers.
Let's talk about this piece of declaration:
int a[4] = { 1, 2, 3, 5 };
int *b = NULL;
This is how they land in memory in the executable:
+----+----+----+----+
a: | 1 | 2 | 3 | 5 | <-- 4 integers
+----+----+----+----+
+----------+
b: | NULL | <-- 1 pointer that points to nowhere
+----------+
As you can see, they are not the same thing.
What happens after b = new int[4];?
The new memory layout of b is something like this:
+----------+
b: | 0xacf3de | <-- 1 pointer that points to a block of 4 integers
+----------+
Somewhere else in memory (at address 0xacf3de)...
+----+----+----+----+
0xacf3de: | ? | ? | ? | ? | <-- 4 integers
+----+----+----+----+
But wait, somebody told me that arrays work like pointers...
No, that's not true. The arrays do not work like pointers.
An array name (a, f.e.) can be used as a shortcut for its address in memory (which is, in fact, the address of its first element). The following notations are equivalent:
a
&a
&a[0]
The value of all of them is the address in memory where the first element of a (the 1 in the example above) is stored.
a[0] is an int, &a[0] is an int *. This is the complete form. The other two are shortcuts that the language provides in order to make the code easier to read and understand.
The things are different for pointers.
b is the value stored in the b variable (NULL or 0xacf3de in the example above. It is a value of type int * -- the address in memory where an int is stored. &b is the address in memory where (the value of) b is stored. Its type is int ** -- a pointer to a pointer to an int; or "the address in memory where is stored the address of an int".
But wait, they can be replaced one for another in some contexts
Up to some point, yes, a pointer and an array are interchangeable. As you can see above, there is a common data type involved: int *. It is the type of b (which stores the address of an int) and also the type of &a[0] (which is also the address of an int).
This means that where b can be used, a (a short of &a[0]) can be used instead, and vice-versa.
Also, where *b can be used, *a can be used instead. It is the short for *&a[0] and it means "the value (*) stored at the address (&) of a[0]" and it is, in fact, the same as a[0].
But, where &b can be used, &a cannot be used instead; remember that &a is the same as &a[0] and its type is int * (but the type of &b is int **).
The line:
*a = new bool[5];
is equivalent to:
a[0] = new bool[5];
You are not initialiazing your array, but allocating an array of bool which is then implicitly converted into bool to be assigned to a[0]: the value should be true since the pointer returned by new should be different from 0. This implicit conversion does not apply with ints: that is why you are getting an error when changing the type of a.
Now, considering this line:
a = new bool[5];
Here you are trying to assign your dynamically allocated array to a, in other words assigning a pointer to an array bool* to a static array bool[0]: as the compiler says, the types are incompatible. A static array a[] can be used as a pointer, e.g. in the following code:
int foo(bool* a) { /* ... */ }
bool my_array[5];
foo(my_array);
But pointers can not be converted into static arrays as you are trying to do.
Type of value returned from new Type[x] is Type * i.e pointer of that type
examle:
So Right syntax is
bool a;
*a = new bool[x];
so it is wrong to do like is
a=new bool[x] wrong syntax as it is invalid to assign pointer to a normal varibale
see for more details
For instance,
int array[5] = {1}: // array of 5 integers
int (*ptr)[5] = &array; // pointer to an array of 5 integers
The following have the same value:
*ptr;
ptr;
If I were to call printf("%p, %p", *ptr, ptr); both outputs would be exactly the same. Why is this?
In this statement
int (*ptr)[5] = &array;
pointer ptr is initialized by the address of the array. The address of the array is the address of its first element that is of the first row.
Expression
*ptr;
gives you reference to this first element that is to the one-dimensional array - the first row or more precisely to the original array..
In turn in expressions arrays are converted to pointers to their first elements and *ptr that is equivalent to expression array is converted to rvalue of type pointer that points to the first element of array *ptr.:)
That is expression *ptr will have type int *
The address of the first row and the address of the first element of the first row is the same.
Now you have two pointers, ptr and *ptr the first one has type int ( * )[5] while the second one has type int * but the both have the same value.
If you look at the memory layout of a 1D array such as
int array[5];
it will make sense.
array
|
V
+---+---+---+---+---+---+
| | | | | | |
+---+---+---+---+---+---+
array[0]
|
V
+---+---+---+---+---+---+
| | | | | | |
+---+---+---+---+---+---+
Address of array
|
V
+---+---+---+---+---+---+
| | | | | | |
+---+---+---+---+---+---+
Address of array[0]
|
V
+---+---+---+---+---+---+
| | | | | | |
+---+---+---+---+---+---+
i.e. &array == &array[0] == array decayed to a pointer
With a pointer declared as:
int (*ptr)[5] = &array;
ptr == &array
*ptr == array decayed to a pointer == &array[0] == &array
That's why you see the same value printed when you use:
printf("%p, %p", *ptr, ptr);
Since printf is a variadic function, the ellipsis conversion sequences are applied to the arguments. In particular, arrays are decayed to a pointer of the underlying type : IOW, it is implicitly converted to a pointer to the first element of the array. Thus, when you call printf("%p, %p", *ptr, ptr);, *ptr, which is of type int[5] is converted to an int* with value &array[0].
In C++ Primer, Chapter 2, "Variables and Basic Types", it says:
it is possible for a pointer to an object and a pointer one past the end of a different object to hold the same address.
I'm not a native speaker, and I think that's why I'm a bit confused by the sentence "a pointer one past the end of an object". Would anyone one tell me what it means please?
It means that after
int a[] = { 1, 2 };
float b;
it's possible that (void *) &a[2] == (void *) &b may compare as true.
&a[2] (or equivalently, a+2) is a pointer just past the end of a, because the array only contains elements with indices 0 and 1.
Normally, out-of-range array indices are completely invalid (accessing a[2] is not allowed, nor is even computing &a[3]), but there is a special exception for computing the address just past the end of an array, because as it turned out, that is quite useful, for example when iterating over an array and you need an end value to know when to stop the loop.
Suppose you have an array, int foo[5] = {1,2,3,4,5};. It's laid out in memory like this:
-----------
|1|2|3|4|5|
-----------
It's legal to have a pointer that points to any member of the array; but it's also legal for a pointer to point one past the end of the array (usually to signal that it has reached the end of the array when doing an STL algorithm using iterators) - although it isn't legal to dereference that pointer. Like so:
-------------
|1|2|3|4|5|?|
-------------
^ ^
| |
p q
p is a pointer into the array; q is a pointer one-past-the-end.
Now, suppose you also have an array const char bar[3] = "Hi";. It's possible that the two arrays have been allocated next to each other in memory, like so:
<--foo---> <-bar->
-----------------
|1|2|3|4|5|H|i|0|
-----------------
^ ^
| |
p q
Then q is both a one-past-the-end for foo, and also pointing to the physical location for bar[0].
"one past" means "+1 operation on the pointer". The following code generates:
0x7ffffcf6a848
0x7ffffcf6a84c
0x7ffffcf6a84c
As you can see, the address of "one past a", i.e., &a + 1 is the same as &b.
int a = 2;
int b = 3;
cout<< &a << endl << &a + 1 << endl << &b <<endl;
I thought array and pointer are basically the same thing, until I run this program:
int main() {
int* a = new int(19);
int b[1];
b[0] = 19;
printf("*a: %d\n a: %p\n &a:%p\n", *a, a, &a);
printf("*b: %d\n b: %p\n &b:%p\n", *b, b, &b);
delete a;
}
output is:
*a: 19
a: 0x7f94524000e0
&a:0x7fff51b71ab8
*b: 19
b: 0x7fff51b71ab4
&b:0x7fff51b71ab4
can someone please explain why the output of &b is the same as b?
Thanks!
-Erben
Well, b is an array. Under the slightest excuse it will decay into a pointer to the first element of b. Note, however, that the expression b and &b are not equivalent: b decays into a pointer the first element, i.e., it is of type int* while &b is a pointer to the array, i.e., it is of type int(*)[1].
Arrays and pointers are not the same. A pointer can behave like an array (e.g. accessing by index).
&b is a pointer to the whole array and b is a pointer to the first element. They may point to a same address in memory but they are totally different things.
+-------------------------------+
|+-----+-----+-----+-----+-----+|
|| | | | | ||
&b---->|| 0 | 1 | 2 | ... | N ||
|| | | | | ||
|+-----+-----+-----+-----+-----+|
+---^---------------------------+
|
b
a is a variable. You are allocating memory using new and assigning the result to this pointer. You might decide to store something else in a later in your program.
b is different. It's not a variable in the sense that it cannot store different addresses. It's an array, having a fixed start location.
Thus, b and &b are same. But the contents of a and the actual address of a are different.