For loop with pointer in C
I don't understand what a pointer does in the for
loop. What does the *p
do in the following loop?
char str[128] = "Some Text";
char *p;
for (p = str; *p /*what does this mean?*/; p++)
{
// Code
}
I do understand the rest, but why isn't *p
like p > 3
or something like that?
Why is it alone?
Why is it written that way?
Solution 1:
In a Boolean context such as the condition of a for
loop, each expression in C evaluates to true (non-zero) or false (zero).
You want the for
loop to terminate, when it reaches the end of the string.
In C, each string is terminated with the character '\0'
, which is practically 0
. So, when the for
loop reaches the end of string, *p
evaluates to '\0'
, which is 0
, which evaluates to false, which terminates the for
loop.
Solution 2:
The for loop will terminate if whatever lies between the two ;
in the statement is zero (false). *p
dereferences p and returns the char
, p
points to. According to Dennis Ritchie "C treats strings as arrays of characters conventionally terminated by a marker". That marker is the null character with (ASCII) value of zero. So, this for loop :
for (p = str; *p; p++)
is equivalent to these
for (p = str; *p != '\0'; p++)
for (p = str; *p != 0; p++)
for (p = str; p[0] != '\0'; p++)
Another name for the null terminating character is sentinel or according to Donald Knuth "dummy value" (Art of Computer Programming, Volume 1). Here is a diagram of the str
string, the indexes (offsets from the start) of each character and the values at each index :
For completeness and after a request at the comments here is what the debugger sees in the memory block that str
occupies :
0x00007fffffffe6a0:
0x53 0x6f 0x6d 0x65 0x20 0x54 0x65 0x78 0x74 0x00 0x00 0x00 0x00 0x00 0x00 0x00
S o m e T e x t
- The hex value at the first line is the address (64bit) of this memory block. That's where
p
points to at the start of the for loop. - On the 2nd line you see the hex values of the letters in your string. You can see an ASCII table here. The last char in your string is
t
with hex value of0x74
. After that you have the string's null character0x00
. Then you see a few more null characters because I built in debug mode and the compiler zero-initialized. Normally you would see garbage (seemingly random values) - On the 3rd line I added the chars of your string for reference
I understand you are on precipitous learning curve at the moment with pointers in C, but eventually you'll be able to say "I C the point"
Solution 3:
Before diving in, I would like to state a simple rule in C regarding an expression
When C requires the Boolean value of an expression, a
false
value is inferred when the expression compares equal to zero, and atrue
value otherwise. That is, whenever one writesif(expr)
where
expr
is any expression at all, the compiler essentially acts as if it had been written asif((expr) != 0)
Now coming to your question:
What does the
*p
do in the following loop?
In C, strings are terminated by a null character '\0'
.
Every character has a decimal equivalent. This '\0'
is an ASCII escape character. The decimal equivalent of '\0'
is 0
.
So, the expression *p
in loop just check that the decimal equivalent of character at the memory address pointed by p
is either a zero or non-zero. When p
reaches the end of the string and finds the first '\0'
character, the expression *p
returns1 a zero value. A zero means false
in C. This is equivalent to testing *p != '\0'
or *p != 0
as stated above.
This is how it works:
1 When *p
evaluates then the value of *p
is fetched from memory. This value is the value of expression *p
.