Punit Vara
Punit Vara

Reputation: 4224

Working of pointer arithmetic

main()
{
char *table[] = {"jan","feb","march"};
char **ptr =&table[1];
printf("%c",(*++*--ptr));
}

* and prefix ++/-- same precedence and R-> L associativity

**ptr has address of feb

--ptr will go to jan address

*--ptr dereference ptr which point to jan

++*-- increment pointer value j to 1

*++*-- deference above value means a

Is my understanding correct ? If not please explain wrong understood statement. My doubt is whether --ptr go to address of jan or some other address. I am not sure about it.

Upvotes: 0

Views: 99

Answers (3)

Holt
Holt

Reputation: 37686

You should split the instruction on multiple lines if you want to be sure:

char *table[] = {"jan","feb","march"};
char **ptr = &table[1];
// This: 
*++*--ptr;
// Is the same as:
ptr = ptr - 1; // prefix --
*ptr = *ptr + 1; // prefix ++ on *--ptr
**ptr;

Since you know the precedence of all operators, you can easily do that, and now it is much more readable.

One way to understand what happen at this point is to look at what you memory could look like (assuming sizeof(void*) == 2, and all pointers type have same sizeof):

// Somewhere in the rodata segment (these are probably contiguous, but I don't really care).
// The 0 are for the null character at the end.
0x1241: jan0
0x1542: feb0
0x1712: march0

// Somewhere in your stack
0x8742: 0x1241 0x1542 0x171 // This is table (contiguous)
0x8844: 0x8744 // This is ptr

The first instruction is ptr = ptr - 1, since ptr is of type char **, ptr - 1 is going to decrement the value of ptr by sizeof(*ptr) (which is sizeof(char*)). So in our example, ptr is going to be decremented by 2:

0x8844: 0x8742 // after --ptr

You clearly see that ptr contains &table[0] (or the decay value of table to char **).

The second instruction is *ptr = *ptr + 1, so you are going to increment the value pointed by ptr, which is the value stored (in our example) at the address 0x8742, which is the first cell of table:

0x8742: 0x1242 0x1542 0x171

By how much did you increment the value of *ptr? Well, by sizeof(**ptr), which is sizeof(char) (assumed 1 in this example), so you get 0x1242 = 0x1241 + 1.

Finally the third instruction is simply **ptr, so you first get the value at the address pointed by ptr (which is 0x1242), and then you get the value at this address, which is 'a'.


Extra... If you want to check your understanding of the above, you should think of what would the following output (before and after your original printf):

printf("%s", table[0]);

Before, you are going to get jan (as expected), but after...

This is going to output only an (and not jan). Why? Because when you did ++*--ptr, which is the same as:

ptr = ptr - 1;
*ptr = *ptr + 1;

You modified the value pointed by ptr. What was this value? Well, after ptr = ptr - 1;, ptr was pointing to &table[0], so *ptr was table[0] so when you did *ptr = *ptr + 1;, you incremented table[0].

At the beginning, table[0] was pointing to the j in jan, but after incrementing it, it is pointing to the a.

Upvotes: 4

vish4071
vish4071

Reputation: 5287

Here are some pointers that I always keep in mind while solving these kind of problems.

Whenever you see * in the code (other than declaration or multiplication), say it as value of (loud, inside your head) and whenever you see &, say it as address of.

Now, I'm just changing your code a little:

main()
{
char *table[] = {"jan","feb","march"};
char **ptr;
ptr = &table[1];
printf("%c",(*++*--ptr));
}

Your code is correct, and so is mine (syntactically) and both are exactly same. When you initialize any pointer while declaring, it is done as you have, otherwise, any time later in the code, you don't attach ** to it.

So, **ptr has address of feb -> NO, because, ptr has it. Actually, **ptr = f, as it is (value at(value at(address of "feb"))), which is, (value at(address of "f")) , which is, f.

Now, since ptr holds address of feb, ptr - 1 will hold address of jan. So, *--ptr = jan as --ptr subtracts sizeof(char *) from its value, so it will point to the previous char * which is "jan".

Now, if *--ptr = jan, then, (*--ptr) + 1 holds address of a, which when you dereference it, gives you a.

Upvotes: 2

Magisch
Magisch

Reputation: 7352

**ptr has address of feb

Thats not true. ptr has adress of feb.

--ptr will go to jan address

Thats true. ptr is adress of feb so ptr-1 is adress of jan

  • and prefix ++/-- same precedence and R-> L associativity

correct

Upvotes: 2

Related Questions