This is one of the very basic pointer usage in C and to understand it let us start with a very simple example. Suppose we have a program like:-
int main(void) { char *p = "Hello"; while(*p++) printf("%c", *p); return 0; }
In this case the first statement:
char *p = "Hello";
declares p as a pointer to char. When we say “pointer to a char“, what does that mean? It means that the value of p is the address of a char; p tells us where in memory there is some space set aside to hold a char.
The statement also initializes p to point to the first character in the string literal “Hello”. For the sake of this post, it’s important to understand p as pointing NOT to the entire string, but only to the first character, ‘H’. After all, p is a pointer to one char, not to the entire string. The value of p is the address of the ‘H’ in “Hello”.
Then we set up a loop:
while (*p++)
What does the loop condition *p++ mean? Three things are at work here that make this puzzling:
- The precedence of the two operators, postfix ++ and indirection *
- The value of a postfix increment expression.
- The side effect of a postfix increment expression.
1. Precedence:- A quick glance at the precedence table for operators will tell you that postfix increment has a higher precedence (16) than dereference / indirection (15). This means that the complex expression *p++ is going to be grouped as: *(p++). That is to say, the * part will be applied to the value of the p++ part. So let’s take the p++ part first.
2. Postfix expression value:-The value of p++ is the value of p before the increment. If you have:
int i = 7; printf("%d\n", i++); printf("%d\n", i);
The output will be:-
7 8
because i++ evaluates to i before the increment. Similarly p++ is going to evaluate to the current value of p. As we know, the current value of p is the address of ‘H’.
So now the p++ part of *p++ has been evaluated; it’s the current value of p. Then the * part happens. *(current value of p) means: access the value at the address held by p. We know that the value at that address is ‘H’. So the expression *p++ evaluates to ‘H’.
Now hold on a minute, you’re saying. If *p++ evaluates to ‘H’, why doesn’t that ‘H’ print in the above code? That’s where side effects come in.
3. Postfix expression side effects:- The postfix ++ has the value of the current operand, but it has the side effect of incrementing that operand. Take a look at that int code again:
int i = 7;
printf("%d\n", i++);
printf("%d\n", i);
As noted earlier, the output will be:
7 8
When i++ is evaluated in the first printf(), it evaluates to 7. But the C standard guarantees that at some point before the second printf() begins executing, the side effect of the ++ operator will have taken place. That is to say, before the second printf() happens, i will have been incremented as a result of the ++ operator in the first printf(). This, by the way, is one of the few guarantees the standard gives about the timing of side effects.
In your code, then, when the expression *p++ is evaluated, it evaluates to ‘H’. But p has incremented, and thus you will only get ello on the screen.