Reputation: 31
1) #include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));
return 0;
}
the output is 2 5. &a
means the address of a[0]
so &a+1
should be the address of a[1]
. So ptr
should hold the address of a[1]
. *(a+1)
will be 2 but *(ptr-1)
should also be 2. I can't understand how is it printing 5.
Upvotes: 0
Views: 164
Reputation: 11921
Firstly, you said: &a
means the address of a[0]
so &a+1
should be the address of a[1] ? No you are wrong. &a
means address of a
not a[0]
. And &a+1
means it increments by whole array size not just one elements size and a+1
means address of a[1]
.
Here
int a[5] = {1,2,3,4,5};
lets assume base address of a
is 0x100
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 ..
LSB
|
a
When you are doing
int *ptr = (int*)(&a+1);
Where ptr
points ? first (&a+1)
performed and it got increments by whole array size i.e
(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
== 0x120
So now ptr
points to
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120
a |
ptr points here
Now when you print like
printf("%d %d", *(a+1), *(ptr-1));
Here
*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
== *(0x104) /* value at 0x104 location */
== 2 (it prints 2)
And
*(ptr-1) == *(0x120 - 1*4)
== *(0x116) /* prints value at 0x116 memory location */
== 5
Note :- Here
int *ptr = (int*)(&a+1);
type of &a
is of int(*)[5]
i.e pointer to an array of 5 elements but you are casting as of int*
type, as pointed by @someprogrammerdude it breaks the strict aliasing and lead to undefined behavior.
Correct one is
int *ptr = a+1;
Upvotes: 1
Reputation: 409136
This expression is the important thing: &a+1
. That is actually (&a)+1
which is equal to (&a)[1]
which will be a pointer to one element past the end of the array.
If we look at it more "graphically" it looks like this, with relevant pointers added:
+------+------+------+------+------+ | a[0] | a[1] | a[2] | a[3] | a[4] | +------+------+------+------+------+ ^ ^ ^ | | | | &a[1] (equal to *(a + 1)) | | | &a[0] (equal to a) | | | &a &a+1
First of all, the type of &a
is int (*)[5]
, so your cast to int *
will break strict aliasing (which leads to undefined behavior).
Second of all, since ptr
is pointing, effectively, to what would be a[5]
then ptr - 1
will point to a[4]
.
Upvotes: 4
Reputation: 223699
&a
is not the address of a[0]
but the address of a
. The values may be the same but the types are different. That is important when it comes to pointer arithmetic.
In the expression &a + 1
, you first have &a
which has type int (*)[5]
, i.e. a pointer to an array of size 5. When you add 1 to that it actually adds sizeof(a)
bytes to the pointer value. So &a + 1
actually points to one byte past the end of the array. You then cast this expression from int (*)[5]
to int *
and assign it to ptr
.
When you then evaluate *(ptr - 1)
, the -
operator subtracts 1 * sizeof(int)
from the byte value of ptr
so it now points to the last element of the array, i.e. 5, and that is what is printed.
Upvotes: 2
Reputation: 213418
&a
gives the address of the array as an array pointer, int (*)[5]
. It is a pointer type that points at the array as whole, so if you do pointer arithmetic with it, +1
will mean +sizeof(int[5])
which is not what you intended.
Correct code:
int *ptr = a+1;
Notably, the cast (int*)
was hiding this bug. Don't use casts to silence compiler errors you don't understand!
Upvotes: 2