0
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.

6
  • Have you tried it to see what happens? Commented Jan 7, 2016 at 7:30
  • Yes. You are almost correct. **ptr has address of feb should be ptr has address of feb. Commented Jan 7, 2016 at 7:31
  • Of course @gr I have tried to understand that's why I have explained the steps but I am not quite sure whether I am wrong or right that why I asked question. Commented Jan 7, 2016 at 7:33
  • @haccks Thanks for response. I agree with you . But --ptr refer to address of jan ? What I am thinking is if we do --ptr the address of ptr is decremented not address of feb. So how it will go to address of jan ? Commented Jan 7, 2016 at 7:35
  • --ptr subtracts sizeof(char *) from its value, so it will point to the previous char * which is "jan". Commented Jan 7, 2016 at 7:50

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

6 Comments

What an explanation :-) . Thanks you I am really satisfied
@PunitVara Thanks. This is a bit off-topic for this question, but you should also know that declaring table as char *table[] instead of const char *table[] is a bit "dangerous" because in your example, ++**ptr is valid (compiler will be ok with that), but is wrong (you are trying to modify a read-only value), and thus your program is going to crash miserably.
Thank you :-) .It added crystal clear info to my brain. This is actually workbook problem I will not use this for any production code as you warned me about it.
and you asked me to guess table[0]. Is it 'jan' right ?
@PunitVara No, printf("%s", table[0]) will only output an because you modify the content of table[0] when you did *ptr = *ptr + 1 (in the memory, you see that at the beginning table[0] contains 0x1241, which points to 'j', thus outputing jan, but at the end it contains 0x1242, which points to 'a', thus outputing only an).
|
2

**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

Comments

2

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.

4 Comments

I thought of it while writing the answer, :D :D
Thank you for awesome answer
--ptr subtracts sizeof(char *) from its value, so it will point to the previous char * which is "jan". can you please include this line in answer ? Thanks @grc for this comment. It improved my understanding
Thanks for it. Above answer is really crystal clear to me Sorry I did not accept your answer . But thanks for efforts you have made

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.