Reputation: 101
#include <stdio.h>
int main(void)
{
char x[5] = { 1, 2, 3, 4, 5 };
char *ptr = (char*)(&x + 1);
printf("%d %d\n", *(x + 1), *(ptr - 1));
return 0;
}
I don't know why it prints 2 5, here i am confused with pointer working. can somebody help me to visualize the concept here?
Upvotes: 1
Views: 144
Reputation: 4288
Visualizing *(x + 1)
+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 5 | ? |
+-----+-----+-----+-----+-----+-----+
|
|
+--> x + 1 points to here
So you get the number 2
.
+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 5 | ? |
+-----+-----+-----+-----+-----+-----+
|
|
+--> &x + 1 points to here
&x + 1
is pointing 5 bytes away since &x
type is char (*)[5]
. You convert this to char *
. With ptr - 1
you will point 1 byte backwards from the above location, so
+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 5 | ? |
+-----+-----+-----+-----+-----+-----+
|
|
+--> ptr - 1 points to here
So with *(ptr - 1)
you access the above element, which is 5
.
Upvotes: 1
Reputation: 24092
First, *(x + 1)
is easy. That's the same as x[1]
, which is just 2
. Nothing out of the ordinary there, although it's better form to write x[1]
than *(x + 1)
.
The ptr
assignment is more complicated. It's taking the address of x
, adding 1
to it, and casting the result to (char *)
. It's equivalent to char *ptr = *(&x + 1);
Even more concisely, one could simply write char *ptr = (&x)[1];
Either of these is better than using an unnecessary cast, which you should always try to avoid when doing pointer arithmetic unless absolutely necessary.
&x
is a pointer to an array of type char [5]
, so it has type char (*)[5]
. This is normally used to access a 2-dimensional array. Since sizeof(char [5])
is 5
, adding 1
to &x
actually adds 5
to the pointer, since it is scaled by the size of the item it points to. So &x + 1
has type char (*)[5]
and points to the first character after the array x
. Casting it to char *
is equivalent to dereferencing it - it just changes the type to char *
.
So the assignment to ptr
is equivalent to char *ptr = x + 5;
, or equivalently, char *ptr = &x[5];
. It points past the end of x
. But the code references it as *(ptr - 1)
, which is equivalent to ptr[-1]
, i.e. it's the character before the one pointed to by ptr
, i.e. it's 5
.
So it ends up printing 2 5
.
Upvotes: 1
Reputation: 134376
Yes, let's visualize. Let's assume the base address of the array starts at a value 1000
(absolutely hypothetical value) and we know that sizeof(char)
is 1
in C.
+----------+----------+-----------+-----------+-----------+
| | | | | |
| x[0] | x[1] | x[2] | x[3] | x[4] |
| | | | | |
+----------+----------+-----------+-----------+-----------+
1000 1001 1002 1003 1004 1005
This is how your array looks like. So, when you say
char *ptr = (char*)(&x + 1);
x
(which is the array), is of type char[5]
, and &x
is of type char(*)[5]
, so any pointer arithmatic on &x
will honor the data type, and increment and decrements will happen based on that.
So, ptr
actually points to the address 1005
, that's one past the array type, char[5]
.
Then, when you say
printf("%d %d\n", *(x + 1), *(ptr - 1));
x
is the same as &(x[0])
, adding 1
advances that to the next pointer, location 1001, as per the pointer arithmetic, honoring the type.ptr
, which is char*
, after subtracting 1
, points to &(x[4])
, and dereferencing that gives the value.Upvotes: 1
Reputation: 32596
about *(x + 1) : x is the address of the first element in the array, adding 1 it is a pointer to the next element, so dereferencing with '*' you extract the second element being 2
about char *ptr = (char*)(&x + 1); : &x is the address of the array itself (is the same for x but here the type is important), adding 1 you get a pointer just after the array, so ptr point after the array
about *(ptr - 1) : ptr is used as a char * so ptr - 1 point to the character just before so to the character valuing 5, dereferencing it with '*' you extract 5
When you add 1 to a pointer the type of the pointer is important because you progress of the size of the pointed type. If you add 1 to a pointer to a char you progress by 1 (by definition sizeof(char) is 1), but in &x +1 the size of the pointed element is 5. To say shortly pointer + 1 goes just after the pointed element
Upvotes: 3