Reputation: 4224
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
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
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
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