Sanjay Verma
Sanjay Verma

Reputation: 101

consider the following code segment of pointer

#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

Answers (4)

Eraklon
Eraklon

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

Tom Karzes
Tom Karzes

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

Sourav Ghosh
Sourav Ghosh

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.
  • Same way, ptr, which is char*, after subtracting 1, points to &(x[4]), and dereferencing that gives the value.

Upvotes: 1

bruno
bruno

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

Related Questions