Reputation: 99
I just read some question about pointer. Here is the code:
int a[5]={1, 2, 3, 4, 5};
int *p = (int*)(&a + 1);//second line
cout<<(*p)<<endl;
My compiler output is 0
. What is *p
? Is it the pointer to array a
? and what is &a+1
means?
Upvotes: 3
Views: 12133
Reputation: 1306
int *p = (int*)(&a+1);
*p
? :In your code, *p
is a pointer to an unknown element of type int
.
Lets reason it out:
&a
is a valid pointer expression. An integer can be added to a pointer expression.
Result of &a
: points to the whole array a[5]
. Its type is int (*)[5]
Result of sizeof *(&a)
is 5
, which is the size of the array.
Result of &a +1
is pointer expression which holds the address of the 1st int
beyond the one &a
currently points to.
Hence, 1
object past the &a
is what *p
points to. Hence it is unknown element of type int
. So, accessing unknown element
is undefined behaviour. This also answers why your output is zero.
Side Note:
If you really wanted to access the second element in the array, you should add 1
to pointer which points to the first element of array. a
points to the first element in the array and size is sizeof(int*)
.
Result of a+1
is the address of the second element in the array.
Result of *(a+1)
is the value of the second element in the array. 2
Upvotes: 1
Reputation: 4357
This is what your declaration statement means:
p
|
v
a[0] a[1] a[2] a[3] a[4] | a[5]
---------(Length)------->
But you're trying to get this (I assume):
p
|
v
a[0] a[1] a[2] a[3] a[4] |
---------(Length)------->
You need to remove the second set of parenthesis from your declaration statement to get a[1]
:
int * p = (int *)(&a + 1);
// change to this:
int * p = (int *) &a + 1;
The reason you're getting the wrong value has to do with the sizeof
operator, operator precedence, and pointer arithmetic. Let me explain those before I explain the error.
The sizeof
operator evaluates the size (in bytes) of a datatype. Immediate example:
sizeof (char) // always returns 1
sizeof (int) // usually returns 4 or 8
sizeof (int *) // usually returns 4 or 8
And note this interesting example:
int a[5];
sizeof (a) // returns sizeof (int) * 5
Operator precedence is the order in which a series of operators are evaluated. Anything in parenthesis will be evaluated first. After parenthesis are evaluated, it's up to the operator precedence to determine what order the expression will be solved.
Here's the relevant operators and they're order in the precedence table:
Operator Description Associativity
() Parenthesis Left-to-right
(cast) Cast Right-to-left
& Address of Right-to-left
+, - Plus, Minus Right-to-left
Pointer arithmetic is mostly about adding, subtracting and multiplying pointers with integers (or other pointers). What you need to know (for the scope of this question) is this:
int * p;
p = p + 1;
Even though it says + 1
, it is actually adding sizeof (int)
to the pointer.
This was a design choice by the writers of the C standard because it is much more common
that programmers want to add sizeof (int)
to the pointer (which brings them to the next integer in an array) than to add 1
(which brings the pointer in between the first and second element in the array).
More generally put:
datatype p;
p = p + 1;
// actually means
p = p + sizeof (datatype);
Here's a relevant example:
int a[5];
a = a + 1;
// actually means
a = a + sizeof (a);
// remember that sizeof (a) is going to be sizeof (int) * 5?
Back to your declaration statement:
int * p = (int *)(&a + 1);
You may already see what's wrong with it: a + 1
really means a + sizeof (a)
, which brings you out of scope of the array. This may be 0
(often it is) or it may be some other random value.
What you might not have noticed is that this:
int * p = (int *) &a + 1;
Actually gives you the second element in the array. This has to do with operator precedence. If you look at the operator precedence table that I put in a link, casts have a higher precedence than &
and +
operators. So if a
is cast as a (int *)
instead of a[5]
before the rest of the expression is evaluated, then it becomes equivalent to this:
int * a;
a = a + 1; /* and this would
give you the second element
in the array */
So simply put, if you want to access the second element in your array, change:
int * p = (int *)(&a + 1);
// to this:
int * p = (int *) &a + 1;
Upvotes: 10
Reputation: 21213
The operator &
is used to take the address of a variable. Thus, &a
is of type pointer to array of 5 ints: int (*)[5]
.
Pointer arithmetic means that when you have a pointer p
, then p+1
will point to the next element, which is sizeof(*p)
bytes away. This means that &a+1
points to 5*sizeof(int)
blocks away, namely, the block after the last element in the array.
Casting &a+1
to int *
means that now you want this new pointer to be interpreted as a pointer to int
instead of pointer to array of 5 ints. You're saying that, from now on, this pointer references something that is sizeof(int)
bytes long, so if you increment it, it will move forward sizeof(int)
units.
Therefore, *p
is accessing a[5]
, which is an out of bounds position (one beyond the last), so the program has undefined behavior. It printed 0, but it could have crashed or printed something else. Anything can happen when undefined behavior occurs.
Upvotes: 5
Reputation: 95958
&a
is the address of the array.
&a + 1
is also an address, but what is this 1? It's a pointer that points sizeof a
bytes from a
. So it's like writing int *p = &a[5];
, then you're casting it to int *
.
Now why 0? Because a[5]
happens to be 0
- Note that it's out of bounds and could be anything else (Undefined behavior).
Note that arrays are zero-based, meaning that the indexes are from 0
. So actually a[4]
is the last element, a[5]
is out of bounds.
Upvotes: 8