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.
**ptrhas address offebshould beptrhas address offeb.--ptrrefer to address ofjan? What I am thinking is if we do--ptrthe address ofptris decremented not address offeb. So how it will go to address ofjan?--ptrsubtractssizeof(char *)from its value, so it will point to the previouschar *which is"jan".