Lets analyze it the dry but depth way!
Or as D. Ritchie would say: Let's do it with the power of assembly language and the convenience of … assembly language.
I'll try to explain all necessary aspects by referencing the ISO/IEC:9899 (emphasis mine)- C99 standard.
(The post style is motivated by Donald Knuth's phrase "Science is what we understand well enough to explain to a computer. Art is everything else we do. ")
First of all, lets inspect what exactly is the for
-loop supposed to do!
Referring to ISO/IEC:9899 6.8.5 "Iteration statements"
Semantics
4 An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
So far nothing new I guess, so lets get it on:
6.8.5.3 The for statement
1 The statement
for ( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. ...
So we now know the body (in your case // Code
) will be executed as long the beforehand evaluated value of your *p
is not zero.
... The expression expression-3 is evaluated as a void expression after each execution of the loop body.[...]
So now we know, (I assume digging up p++
's definition is not necessary?!) that for each iteration p
increments, so there may be a change in *p
.
The following point is not related, but I'm adding it since this makes the Semantic part of for
complete and its well to know since its the reason, why for(;;)
is a inf-loop.
2 (---) Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.
Ok, that's the dry but information-enriched part of what the for
loop does in your case.
Now lets get over to pointer arithmetic:
6.5.6 Additive operators
Constraints
2 For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)
So in your case you are adding 1 (integer) to the "pointer to an object"-type.
What is equivalent to increasing the Address by the sizeof its pointed to type like shown in this picture of tomislav kostic:

Now lets see what *p
actually does.
6.5.3.2 Address and indirection operators
Constraints
[...]
2 The operand of the unary * operator shall have pointer type.
Semantics
[...]
4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
This is a bit dry again1 but for better understanding this can be reverse engineered by:
6.5.2.1 Array subscripting
[...]
Semantics
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
So *((p)+(0))
what is(since p+0
is same as p
... obvious) is equal to p[0]
, is doing nothing else as evaluating p
's object.
And since we know, expression-2
of a for loop is interrupting the iteration if it is evaluating 0
, we can say it is the same as p[0] != 0
.
Now the final step
Lets just look onto the C-Coder's Friend; JSSCA... No, wait...our friend was called... ASCII Now as that's clarified, we can figure out what the 0
is representing.
It is the NULL-token that in C is designating the end of a string.
So conclusive:
All, this is doing is:
Iterating the body of that for
-loop, until p
is actually pointing to the address, where the object evaluates to the "end of string"-token.
Or:
Let p
go through the string until the end is reached.
And now just to cite my self; Something you never should forget:
(emphasis mine.....)
A variable is declared through a declarator(type-specifier) that precedes the identifier which names an lvalue object that can be evaluated to its value
It is neither more nor less!
1That is, what I promised! ;)