52

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?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
MeChris
  • 717
  • 1
  • 7
  • 11
  • google for "c string". – user3528438 Nov 20 '15 at 14:51
  • 4
    actually `c string terminator` as search keyword is more helpful. – user3528438 Nov 20 '15 at 14:52
  • 6
    The comparison has been omitted. It is `*p != 0`. `0` is the value which your char pointer points to when the string ends, because it is the string terminator. See [this question](http://stackoverflow.com/q/16955936/96780) for more details, in particular whether to use `0` or `'\0'`. – Daniel Daranas Nov 20 '15 at 14:53
  • @DanielDaranas `*p` behaves equally to `*p != 0` in this case as `for` only cares if the value is nonzero (i.e. not a NULL pointer). – fuz Nov 20 '15 at 14:57
  • 3
    @FUZxxl `*p` or `*p != 0` dereferences `p`... so it's not checking for a NULL pointer, but whether it points to a value of zero. – Dmitri Nov 20 '15 at 15:19
  • Yeah, should have been “resp.” instead of “i. e.” – fuz Nov 20 '15 at 15:24
  • @FUZxxl I know. It behaves equally. That's why I said the comparison "has been omitted". And no, it is not checking for a NULL pointer at all. – Daniel Daranas Nov 23 '15 at 08:18
  • having `X` as the second condition is equivalent to `(X) != 0`, for all `X`. – M.M Dec 15 '15 at 08:40
  • `*p` in this context in the for-loop means: _please do it until the pointer is `nil`_, as the string is closed by `\0`, obviously the loop ends when the cycle reaches the end of the string. – holex Dec 17 '15 at 21:14
  • 1
    Is this bounty just for creativity or you need some additional information? @Ike – haccks Dec 18 '15 at 14:41
  • 1
    @haccks I'd be amazed if you could contribute new info! I'm judging the bonuses as lesser to the educational value of answer, they're superficial challenges that hopefully prevent answers from becoming too simple or quick (and also hopefully a little fun to read/write -- C tag has gotten a bit dull lately). If you think you can contribute new info (ex: assembly breakdown maybe, compiler design perspective, history, anything?) I'd be really impressed to say the least. –  Dec 18 '15 at 14:44
  • 1
    OK. On SO I am among lazy guys, but will try to add some additional information with some creativity :) @Ike – haccks Dec 18 '15 at 14:47
  • 1
    @Ike I am surprised you are awarding bounties, and changing the conditions, before the period is even closed. – Weather Vane Dec 23 '15 at 20:10
  • @WeatherVane Felt bored and generous over the holiday season. :-D But even with this kind of basic question, the diverse characteristics of the answers surprise me quite a bit. Hence the rewards for surprising me with each new bounty. I wanted, as an experiment, to see if we could get interesting answers out of a basic question with a few forced constraints that require people to take some time in answering. –  Dec 23 '15 at 20:18
  • @Ike that's generous, but you didn't seem to notice my answer ;( I know Kaiku does not usually rhyme, but I can't quite divorce myself from limerick abilities. – Weather Vane Dec 23 '15 at 20:21
  • @WeatherVane I did! ... And up-voted it. Though you missed the timing by a little bit -- apologies for that! But I'm keeping this last one open for the extended duration (running out of rep), hopefully that will help more people notice your fine answer. –  Dec 23 '15 at 20:22
  • @Ike thankyou but -- oops "Kaiku" -- that's me down even though it rhymes with "Haiku", but is not supposed to. – Weather Vane Dec 23 '15 at 20:46

14 Answers14

61

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ergysdo
  • 1,139
  • 11
  • 20
  • Thanks a lot! Explained very very well. I was really confused because pointer was alone there. – MeChris Nov 20 '15 at 15:00
  • Note that by definition, a string is a sequence of zero or more non-null bytes terminated by a null byte. – Jonathan Leffler Nov 20 '15 at 15:09
  • Please note that there's a 100-rep bounty on this question. –  Dec 16 '15 at 05:27
  • Note there is nothing evaluating to false regarding to a for loop. Have a look on my answer, the standard just simply says the 2nd expression has to be scalar-type and is interupting the iteration when its evaluated value is zero. so even if using stdbool.h, it is false what evaluates to 0 to interupt not vise versa ;) – dhein Dec 16 '15 at 08:09
43

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 :

enter image description here

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
  1. 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.
  2. 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 of 0x74. After that you have the string's null character 0x00. 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)
  3. 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"

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • 2
    This answer has great potential, but I feel like it's missing a picture, a quote from Knuth, one from Ritchie, and one from yourself (in italics). That would definitely get my bounty, since you already have a cool hat. –  Dec 14 '15 at 23:06
  • 1
    `*p != NULL` is not equivalent to the others. `NULL` may be defined as `(void *)0`, which means this is a comparison between *integer* and *pointer*. This comparison requires a cast unless the integer is a *null pointer constant* , which `*p` is not (even if it happens to hold value `0`). See C11 6.5.9/2 for reference (earlier versions of C have a similar rule). – M.M Dec 15 '15 at 08:36
  • The diagrammed text `*p = NULL` is incorrect; this should be `*p = 0` or `*p = '\0'` – M.M Dec 15 '15 at 08:37
  • 1
    @M.M You are correct. I erroneously remember seeing it used like this but actually it was `NUL` (non-standard). – Manos Nikolaidis Dec 15 '15 at 09:02
  • This post really seems to be the perfect answer. I'm forced to wait a little longer before I can award the bounty, but it is so close to perfect! The only thing missing is a personal and original quote from yourself -- some one-liner perhaps which captures your philosophy on this subject and stands out (could be poetic and just about programming in general or the life of a programmer or anything like that, or it could be about C, about pointers in general, about expressions, etc.). –  Dec 15 '15 at 09:18
  • @Ike not good with poetry or philosophy I am afraid :-( I did add a pun though. – Manos Nikolaidis Dec 15 '15 at 10:48
  • @ManosNikolaidis That is perfect! Now I just have to wait 11 hours, but this answer is, by far, my favoritest one. –  Dec 15 '15 at 10:53
  • @ManosNikolaidis I upped the antes though. Now there's a 100-point bounty on this Q. –  Dec 16 '15 at 05:19
  • 2
    @Ike: it would be even better if ManisNikolaidis would add a third line with a hex dump, to illustrate how characters are encoded in memory and how a null character, spelled `'\0'` and encoded as `00` terminates the string. – chqrlie Dec 17 '15 at 18:01
  • I try to achieve the same thing with a `while(*p){...}` loop, but the loop won't stop at the end of the `str`. There are more values after that. Is that because of the same reason you mentioned in the answer? (random values after the null character) – Bojie Shuai May 05 '21 at 01:07
20

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 a true value otherwise. That is, whenever one writes

if(expr)

where expr is any expression at all, the compiler essentially acts as if it had been written as

if((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'.

enter image description here

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:

enter image description here


1 When *p evaluates then the value of *p is fetched from memory. This value is the value of expression *p.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • OMG, I have to wait a couple of hours to +1 (exhausted my votes), but did you make that animation yourself? And if so, how??? –  Dec 19 '15 at 21:18
  • 1
    @Ike; Yes of course. Actually I am on bed rest theses days so have plenty of time. Created 36 images for this gif :) – haccks Dec 19 '15 at 21:23
  • 2
    I feel like I have to make another bounty just for this answer -- as I think it has the most educational value I've seen yet. –  Dec 19 '15 at 21:24
  • 1
    @Ike; Thanks for your appreciation. I am glad you really liked it. – haccks Dec 19 '15 at 21:27
  • 1
    Have all my up-votes! I taught CS 101/102 for a brief period in my life (late 90s) so I think this is one of the most effective ways to teach people out there (always wished I could draw animations on a whiteboard). This doesn't quite fit my current bounty requests but I think I'll make another one just for this after for the most educational answer. I've always wanted to do more visual answers like this to explain topics but was always too lazy. –  Dec 19 '15 at 21:32
  • 1
    I made a new bounty which is pinned to your answer. I want to let the timer run out on that one to give all of these people who contributed answers as much exposure as possible, but this bounty is reserved for this answer for surprising me so much with an animated GIF answer to the question. –  Dec 19 '15 at 21:40
  • 2
    Wow! Now I feel like I have to make jessica speak :P – terence hill Dec 19 '15 at 21:53
  • By the way: where is your quote from? Can't find it in any of my standard copys. – dhein Dec 20 '15 at 09:25
  • @Zaibis; It is quoted from c-faq. Link is attached there. – haccks Dec 20 '15 at 09:30
  • this animation makes me dizzy xD – holzkohlengrill Jun 06 '17 at 13:27
  • 1
    what if an actual '0' occurs in the middle of array? – Henry Jun 14 '17 at 15:08
  • 1
    @Henry; Then loop will stop at that `0`. – haccks Jun 14 '17 at 15:19
19

This could be rewritten like this

for (p = str; *p != '\0'; p++)
{
    // Code
}

In C, a string must always be terminated by a null character, which is the same as '\0' or 0.

Lundin
  • 195,001
  • 40
  • 254
  • 396
KeylorSanchez
  • 1,320
  • 9
  • 15
  • While my bounty is encouraging very detailed questions with headings and stuff so that they might educate a wide range of people and also give them more stuff to look up, this answer is pretty nice... short and sweet, and noteworthy in its conciseness. My only gripe is that it can be provided quite rapidly. But it is a wonderful answer nevertheless -- bravo! –  Dec 16 '15 at 15:47
14

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:

CC BY-SA 3.0 by 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! ;)

Community
  • 1
  • 1
dhein
  • 6,431
  • 4
  • 42
  • 74
  • 1
    This is amazing! I feel like it is a strong candidate for the new bounty. But I feel slightly like I am reading an answer from Spock. I would love to see some more humor, a personal view on the subject, a philosophy or some poetry (maybe a haiku or this subject). Think Butt-Ugly Fish Book. I really feel like this answer has great potential for this new bounty though -- also could use some headings and/or bullet points. If you can somehow cite Jessica Alba, it would be so perfect (though optional). –  Dec 16 '15 at 05:29
  • If you look at the previous answer that won the previous bounty, it had an "I C the point" joke in it which really biased me towards it. But it doesn't have to be humorous, it could be philosophical, just a quick personal story about when you started learning C, something to that effect. -- anything that gives it a more human touch.. oh and don't forget big, bold headings. Those really stand out. –  Dec 16 '15 at 05:34
  • About the personal quote, the citation doesn't have to be so blatant. You could just have a new line, italicized. Of course ideal would be like, `"I like cheese!" -- Ike` -- this kind of format, maybe with a footnote using below it stating that the bounty made you do it if you feel uncomfortable about citing yourself. –  Dec 16 '15 at 05:38
  • Now if you are having difficulty imagining how to possibly go the extra mile and cite Jessica Alba, some hints.... think about how she is very beautiful, toned, graceful, firm, perky, cute, small, a dancer... these kinds of characteristics should be easy to tie to C, and why it's still around in spite of all these other languages. –  Dec 16 '15 at 05:46
  • 1
    @Ike: I'll try my best over the day. But I'm kind of humor handicaped so I'll probably have trouble with that. But maybe I'll be able to make something out of the fact itself. '^.^ – dhein Dec 16 '15 at 08:01
  • 1
    @Ike For now I changed my Profilpicture into a stone just designed for you and therefor a perfect fitting head. Isn't that awesome anyway?:D – dhein Dec 16 '15 at 09:45
  • Oh wow, definitely bonus points for the hat and avatar. I think this is the strongest candidate for the new bounty, by far. My most immediate suggestion to improve it a bit is to break up the text a bit into sections through headings. We want to add some flash in there, make the info pop out, since otherwise people might overlook this gem. –  Dec 16 '15 at 09:48
  • 1
    @Ike: done so far. And a cite of my own is incomming soon. Just looking for something I'm really expressing very often about C and I hope I'll find a highvoted post of me containing it to refere to :P – dhein Dec 16 '15 at 12:56
  • How'd you get so comfortable navigating your way around the ISO/IEC standard documentation? Do you have a printed version around that you can skim through from time to time? BTW -- awesome edit! –  Dec 16 '15 at 13:06
  • 1
    @Ike: sorry, I'm not quite sure I got that question right. Are you asking how I'm able to navigate my self that well through the document? (if so, thanks for the compliment, if not, could you rephrase the question?) – dhein Dec 16 '15 at 13:10
  • Oh sorry, I mean I noticed in your answers in general that you seem to have the uncanny ability to cite the ISO standard for many topics. I've never been able to do that -- it would take me ages to find the relevant section, so I was wondering if you have a printed copy that you kind of browse through from time to time, improving your familiarity of where relevant information is located in the document. –  Dec 16 '15 at 13:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/98119/discussion-between-zaibis-and-ike). – dhein Dec 16 '15 at 13:19
  • 1
    @Ike: And there is the cite to my self :P – dhein Dec 16 '15 at 14:12
  • @Zaibus OMG, there is a fierce competitor who actually *embedded* a picture of Jessica Alba! I believe you have the edge when it comes to technical precision, but there is some competition brewing. Maybe it would help to also embed a picture of Jessica Alba with text along side of it? –  Dec 16 '15 at 14:44
  • 1
    @Ike: Well, what you are going to do is absolutely your decision. ;) I like my letter gambling from ASCII to JSSCA and I'm really not good in intersocial stuff like humorfully representing a picture of some one expressing something or such. Also remember your actuall wording just gives "bias" to the Jessica Alba part ;P – dhein Dec 16 '15 at 14:54
  • 1
    BTW, have you ever read the Butt Ugly Fish Book? http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298. It might not suit your taste as it's a book on C filled with anecdotes and little jokes and stories everywhere. But it's a nice example to me of how something can be fun and actually very educational and reasonably precise all at once. From this little bounty game I'm playing, it was originally inspired by boredom -- but I used to teach computer science in the early 2000s. I'm hoping the resulting Q&A will show that even the most basic question doesn't have to... –  Dec 18 '15 at 19:20
  • 2
    ... require simple, routine answers, that even a basic question can tackle complex subjects and territories a lot of people aren't aware about if we want to take them as technically far as you do, or as fun as some others took it -- and fun sometimes is a prerequisite, at least for some students, to help them learn subjects without being bored. There's a very diverse range of learning styles out there -- from visual to mathematical to very technical and literal -- lots of people benefit from different styles. And I'm hoping the variety in these answers can show that to future readers. –  Dec 18 '15 at 19:23
  • While explaining about pointer arithmetic you should consider the pic for character arrays. @Zaibis – haccks Dec 20 '15 at 22:16
  • @haccks: agreed. I'll see when I have the time for that. – dhein Dec 21 '15 at 11:16
9

The *p Haiku

Poetically, I tried to represent the struggling of *p in the loop:

Brave C *p(rogrammers)

In the loop of whilederness

The NUL will stop them

This is an haiku poem, it consists of three lines, with the first and last line having 5 syllable, and the middle line having 7. Another example by @Samidamaru (a Master Haiku Poet, see comment below): First p equals str, Then p is incremented, Until *p is NUL.


A little bit of pop

enter image description here

Hour of Code ambassador, Jessica Alba


What does the *p do in the loop?

Following the imaginary advice of Jessica (who is citing D. Knuth (1)), we will try to see the meaning of *p in the for loop:

for (p = str; *p; p++)

To this goal we first examine how the unary operator "*" works in C: “The unary operator * is the indirection or deferencing operator; when applied to a pointer, it access the object the pointer points to.” (B. Kernighan and D. Ritchie (2))

So *p is simply the value pointed by p:

enter image description here

1.1 A closer look to the for loop

The for loop is composed of three instructions:

  1. p = str
  2. *p
  3. p++

In 1. we assign the pointer to the array str to p. In C the following assignments have the same effect:

p = &str[0];
p = str; 

“By definition, the value of a variable or expression of type array is the address of element zero of the array” (K & R (2)). Moreover we have that “In evaluating a[i], C converts it to *(a+i) immediately. …. it follows that &a[i] and a+i are identical” (K & R (2)). If we put i = 0, we obtain the above assignments.

We can now state that, at the beginning of the for loop, p points to the first element of str.

1.2 The core of the question

Let's move to the point 2., the core of your question. The second expression of the loop controls the exit condition: the instruction "*p" is evaluated and if is false the loop exit. This means that "*p" is equivalent to "*p != 0" or in words: when the value pointed by p is zero, exit.

Now, to understand when *p is zero we recall that the array str has been initialised as follows:

char str[128] = "Some Text";

and: “all string constants contain a null termination character (\0) as their last character” (gnu-manual). So the string actually stored in memory has a \0 at the end: "Some Text\0".

In the third instruction, p++, the pointer p is advanced to the next element of the str array, thus, at the 9-th iteration *p became 0 (or \0, NULL, NUL, see the answer from @Joe) and the loop exits.

1.3 See to believe

A picture is worth a thousand words, here is a graphical representation of the loop:

enter image description here

1.4 A further example: the same usage of *p in a different example

In the following snippet *p is used the same way but in a while loop:

#include <stdio.h>
int main() {
    char str[128] = "We all scream for ice cream!";
    char *p = str;
    // here we see again the loop exit condition *p == '\0'
    while(*p) {
        printf("%c", *p);
        p++;
    }
    printf("\n");
}

May the for(;*C;)e be with you!


References

(1) Vol. I, Fundamental Algorithms, Section 1.1 (1968)

(2) The C Programming Language Pg 94-99

terence hill
  • 3,354
  • 18
  • 31
  • I don't want to be pedantic, but first of all, there is no such thing as an "unity" operator in C. Especially not if you are refering to the pretty old ANSI C. Also I would love to check your quote that it was realy D. Ritchie who said/wrote "The unary operator * is the direct or deferencing operator; when applied to a pointer, it access the object the pointer points to." But the url you link to it with is simply... not even an url. Well I have to admit, your pictures and styl is pretty entertaining, well done. But the content it self is bad cited, incomplete and partial even incorrect. – dhein Dec 16 '15 at 13:06
  • Citation are in fact not link, just citations, but they are wrong as I saved them as links. Thanks. Unity it's a typo, thanks again to point it out, should be unary. The quote is from pag 94 of the C Programming Language. If you think that there are some other errors I appreciate if you can point them and I will try to correct them, I admit that I focused more on the entreating as well done and correct answers are already here. – terence hill Dec 16 '15 at 13:30
  • I belive you that it is in the book. But I'm not academic enough to say is it important to know which author wrote what or if 2 authors wrote one book you jsut can take one of them and assume he was it? IDK. But acording to the part you focused on: well done ;) – dhein Dec 16 '15 at 13:47
  • 2
    OMG, this is a magnificent answer and it actually has an *embedded* picture of Jessica Alba! Bravo! I don't know what to do now -- there is some tough competition going on between you and Zaibis! I feel like your answer is better suited for the beginner level of the question, but Zaibus has that dead-on technical precision. In any case, whatever happens, both of you are winners in my eyes! –  Dec 16 '15 at 14:42
  • 1
    @Ike wow, thanks for the comment, but especially for this funny game. I really enjoyed myself answering. I updated my answer, hope you will like it even more. – terence hill Dec 17 '15 at 08:41
  • @terencehill I think I'm leaning towards Zaibis' answer, since his has a very unusual characteristic -- but I'm chaining a bounty right after that which rewards fun factor and beginner-level appropriateness which has your name all over it. –  Dec 17 '15 at 08:50
  • @terencehill New bounty that currently has your name all over it! –  Dec 17 '15 at 08:55
  • 1
    @terencehill There is one new bonus challenge with the higher bounty which could give your answer the uber dominating edge (though it already has this for the most part) -- it is to include a haiku on the subject, 5-7-5 syllable form (not strict adherence beyond the syllables to the formalities of Haiku) -- just formatted that way. –  Dec 17 '15 at 09:07
  • 1
    I think your answer (besides Haiku) part could be even more awesome if the `for(;C;)` awesome joke was `for(;*C;)` to tune it for this question, though up to you -- props either way. One thing that might help is to put a comment in that `while` loop code version, especially around the `while(*p)` part. –  Dec 17 '15 at 10:59
  • 1
    Yes I also thought about the *C but was in doubt. – terence hill Dec 17 '15 at 12:23
  • 1
    @Ike I'll start thinking about the Haiku from my copy of "Goedel, Escher, Bach". – terence hill Dec 17 '15 at 12:29
  • Come on guys where are these haikus: First `p` equals `str`, Then `p` is incremented, Until `*p` is `NUL`. – Samidamaru Dec 18 '15 at 09:37
  • 3
    @Ike & terence hill, if you want to use that, I'll accept a reference and weekly payments to my paypal account: MasterHaikuPoet@paypal.com – Samidamaru Dec 18 '15 at 10:04
  • @Samidamaru let me know if i may join your circle of Msters! – terence hill Dec 18 '15 at 21:49
  • 1
    @ike updated answer with the haiku. I tried my best but I am not even sure about the syllable (as a non-english that was hard, I realised for the first time that I have no idea how syllable works in english). – terence hill Dec 18 '15 at 21:51
  • 1
    @terencehill Perfect! I'm going to leave the bounty going for this one quite a bit since it's starting to cost a lot of rep -- but mostly so that the question gets viewed. I think it would be very difficult to beat this answer, plus I couldn't stop laughing for hours the first time I saw the Jessica Alba pic. :-D –  Dec 18 '15 at 21:59
  • 1
    @Ike thanks, corrected. Yes, let it be ;). I hope we can see more answers (the one from chqrlie is really fantastic) and more comments like the one above from Samidamaru. – terence hill Dec 18 '15 at 22:00
5

It takes advantage of the fact that the terminator to the string (eventually found by that for loop) will be an ASCII NUL, which is a zero, which also happens to evaluate to false, thus terminating the for loop.

It's worth noting the difference and similarity between 0, false, NULL and ASCII NUL. See this question: What is the difference between NULL, '\0' and 0

Community
  • 1
  • 1
Joe
  • 7,378
  • 4
  • 37
  • 54
  • 1
    No problem. In all reality there's not much difference, but it's worth noting here as it is a piece of history that people come across, particularly with nasty code like the OP showed. – Joe Dec 15 '15 at 09:24
  • 3
    Using `*p` in a boolean context is *not* poor code, it is a standard idiom all C programmers are familiar with. – user4815162342 Dec 15 '15 at 10:30
  • @user4815162342 @Joe Perhaps it is a risky territory to suggest is to be a poor style. I've personally never used it in this context since I wasn't sure I could, with the widest portability, assume `'\0' == 0`. But those who know that for sure, or perhaps if that is guaranteed by the language standard, might very well use that shorthand justifiably. –  Dec 15 '15 at 10:39
  • 1
    I agree it is idiomatic C but I disagree that it is good code. The idiom does not make it more reliable, more maintainable, faster or less coupled. Certainly it should be understood, but I'm not sure it should be perpetuated. – Joe Dec 15 '15 at 10:44
  • 1
    It is generally considered that treating terminators such as `'\0'` and `NULL` as false values makes the code [more readable](http://stackoverflow.com/a/17774781/1600898). It is not only idiomatic C and C++, but endorsed by the language authors in *The C Programming Language*. Furthermore, "logical truth" continues to be present in mainstream languages created after C, such as Python, Perl, Ruby, or JavaScript. While it is not unreasonable to question any particular coding style, given the volume of existing practice, in this case the burden of proof is on the questioner. – user4815162342 Dec 15 '15 at 14:50
  • PLEASE do not edit this. I mean NUL. ASCII NUL, not NULL. – Joe Dec 21 '15 at 08:18
4

A long time ago, in a PDP far, far away, resources were scarce, names got short: i for index, p for pointer would please early Jedi programmers.

Implicit tests told the truth in for condition space. A single * was all they typed, trusting p and pushing it to the end of strings.

To this day, they use the for(e = s;*e;e++) most familiar and elegant loop to defy the C++ empire and its cohorts of ctors, dtors and vile iterators. Bare bits and bytes against templates, exceptions and obscure types, only the brave still dare for C to fight, and uncast the void *.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    OMG, I am giving this an up-vote from the rebel side (thinking I shouldn't) -- as both a C and C++ developer, but appreciating the C aesthetic a lot of minimalist elegance. This is an interesting stylistic angle -- props for its daring nature. –  Dec 17 '15 at 20:55
  • 1
    This answer is terrifying to me in terms of its sheer (and great) boldness -- I feel the need to cast protection against potentially angry C++ devs. To those viewing, keep in mind that this contributes a totally unique aesthetic angle to the question, that experience causes us to diverge in aesthetics, and even through the choice of languages we use. This is an idiomatic C aesthetic. And, at the end of the day, the only thing that matters is results -- look at Linus Torvalds, he despises C++, and we can't argue with the magnificent results he achieved nevertheless. –  Dec 17 '15 at 21:28
  • 1
    I'll follow you thru the dark C++, we'll defeat the templates to C the *. – terence hill Dec 18 '15 at 00:05
  • Funny +1 from me aswell. But remember, even this is a nice idea, remember this is still SO with its on- and off-topics. It feels difficult for me to see a real answer in it. :/ – dhein Dec 18 '15 at 08:39
  • @Zaibis It's focused from a stylistic perspective of why the code might be written in such a way in C, which does address the part of op's question about why it is written that way. There's also a brief answer there about the logical behavior of iterating through to the end of the string. Some variety in answers is a good thing for future readers as I see it (redundancy would be terribly dull and time-consuming to read through), even if there can only be one accepted! –  Dec 18 '15 at 13:14
  • @Ike: I don't want to say anything bad about this. But you can't deny that this is on the edge to off-topicness. Just said, to improve it somehow so it isn't too close to this edge anymore ;) – dhein Dec 18 '15 at 14:39
  • @Zaibis It is dangerously close -- though I think it's only really clear that questions that blatantly call for subjectivity are OT, not subjective answers. Maybe one way to look at this is that this describes a C aesthetic -- embracing it is subjective, but languages and aesthetics aren't divorced from each other. To embrace a C++ mindset wholeheartedly often requires somewhat disliking some of the lack of safety in C, e.g., while embracing C wholeheartedly often requires seeing a lot of these mechanisms in C++ as obstacles to get closer to the bits and bytes of the machine. –  Dec 18 '15 at 14:54
  • @Ike Thats true but that is exactly the point with or without headline. Because it is something opinion based (you see even in your first comment's reactions). And that is something what is strictly tryed to be avoided on SE. got me? edit to your second comment: the point is the way you give by bount every time new aspects to a OP is kind of out of the SO scope. So hard to categorize it. But dont try to convince me I'm fine. Just noted it so you all are aware and OP may edit. – dhein Dec 18 '15 at 15:07
  • 2
    @Zaibis Agreed -- though I'm unclear on whether a subjective leak in an answer warrants it as OT. I think the reason POB questions are OT is in an attempt to *discourage* too much subjectivity in the answers (not to avoid them outright with an iron hammer, since most of us would have great difficulty there answering anything, though you might be able to do it perfectly!). But if an answer chooses to do it anyway, I think it's in a gray zone which puts it more in the voting rather than flagging territory. Oh well, this might be like a meta topic! :-D But for now, I think this answer is fun! –  Dec 18 '15 at 15:16
4

I have tried to satisfy the bounty awarder's desires which were mentioned at various times. To keep it simple I have restricted my answer to three sections of three lines each, and because (as The Bellman said in his Rule Of Three) "What I tell you three times is true" (the theme of this answer).

Technical

The truth of your for loop terminates it when the expression *p evaluates to 0 and this evaluation is performed before every iteration of the loop, note that in C 0 is false and anything else is true - that's a very expansive definition in other worlds!

The pointer variable p is initialised once, to point to the start of the array with p = str, and p is incremented at the end of every iteration, so *p is accessing successive elements of the array in each iteration.

The expression *p will thus evaluate to 0 (false) when the array element read by *p is the 0 or '\0' terminator that signals the end of a C "string", but you can't see this zero in the initialisation of str because it is supplied by the compiler automatically.

Lyrical

Expressions of truth

Are not understood by youth

Read Ritchie and Knuth

Whimsical

Jessica Alba is a fine actress who is very knowledgeable, having taken on board truths from observing the development of computer technology, as these quotes reveal:

"Every five years I feel like I'm a completely different person."

"It's all about your product and how it performs. Either it works, or it doesn't."

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • *So `*p` is pointing to successive elements of the array in each iteration.*: I think you mean to say `p`, isn't it? – haccks Dec 20 '15 at 18:43
  • @haccks I debated with myself which to use, I put `*p` in this sentence because `*p` refers to the array element's value, not to its address. Tricky to phrase perhpas? I'll edit it in a minute. – Weather Vane Dec 20 '15 at 18:45
  • Yup. `*p` represents the successive elements rather. – haccks Dec 20 '15 at 18:46
  • 1
    @haccks thanks, I made a slightly different edit, so it remains my work ;) – Weather Vane Dec 20 '15 at 18:49
  • +1 For the Lyric! Well done. You may consider to enter our circle of Master Haiku Poets? And I also liked the citations from my dear friend Jessica. – terence hill Dec 21 '15 at 14:41
3

A haiku:

WHY   for (p=str; *p;        p++)
IS    for (p=str; p[0] != 0; p++)
THINK for (i=0;   str[i];    ++i)

EDITED

Here is some additional detail:

The second line of code of the "haiku" is equivalent to the first line. The original post asks "what does this mean" in a code-comment. The second line demonstrates the answer by equivalence. *p means p[0]. The second clause in the for loop cares about whether or not p[0] is equivalent to zero.

The third line of code of the "haiku" is a line of code which can be used conceptually: You can think of the operation of the original line as behaving much like the third line ought to.

synthetel
  • 63
  • 5
2

String in str

As you can see from the picture, for loop starts with *p where p points the str. At this point *p has S.

When continuously looping the for, it finally reaches to str[9] which has '\0' which means NULL.

At this point the condition statement *p in for (p = str; *p; p++) is equal to NULL so the code will break from the for loop.

J. Sy
  • 31
  • 1
  • 1
    -1. Sorry but `NULL` is not the null character, `'\0'` is. `*p != NULL` will fail to compile on most C environments because `NULL` is the null pointer and as such usually defined as `((void*)0)`. C++ defines `NULL` as `0`, thus lets one write such confusing horrors as `*p != NULL`. Don't do it. – chqrlie Dec 17 '15 at 18:46
  • I meant `NULL` is ascii `NUL` (0) character here. Sorry for the confusion by mixing `NUL` character and `NULL` pointer. – J. Sy Dec 18 '15 at 00:34
2

That is the condition part of the loop.
If that condition is not met then the loop is not executed anymore.
*p dereferences the pointer p and returns the character pointed at in the string str.
The C-style string str is terminated by the value \0.
The loop iterates over each character (using p) until the condition is not met.

In C a value of 0 or \0 is like the meaning offalse, i.e. condition is not met.
Any other value is like the meaning of true, i.e. condition is met.

In short, p iterates over each character in str and stops as soon as it hits the string termination character \0.

Why not using p instead of *p?
Because p is a pointer and contains an address. It's sometimes hard or even not possible to use address arithmetic only. It's not good practice and makes code hard to read.
*p is the dereferenced pointer and contains the value that p points to. In this case it is easy to use the values that p points to, because you know the string is terminated by a \0. As a condition (if, while, etc.) *p is equivalent to *p != '\0'.

Ely
  • 10,860
  • 4
  • 43
  • 64
1

Firstly you need to grasp a concept of pointer, like name says they point to something. Pointer contains adress of variable.

    int var=0;
    int *p;
    int p=&var;

in this code p is a pointer and printf("%d",p); prints adress of variable var and printf("%d",*p); prints value of variable var which in this example is 0.

Secondly, you must understand how arrays works.Arrays are kind of data structure that can store a fixed-size SEQUENTIAL collection of elements of the same type.

        int array[3]={9,8,7};
        printf("%d",array[0]); //prints what is on 1st position,9
        printf("%d",array[1]); //prints what is on 2nd position,8
        printf("%d",array[2]); //prints what is on 3rd position,7

operator [] are just user-friendly work with arrays. Last three lines of code can be replaced with following lines(and they will do just the same):

        printf("%d",*(array+0)); //prints what is on 1st position,9 
        printf("%d",*(array+1)); //prints what is on 2nd position,8
        printf("%d",*(array+2)); //prints what is on 3rd position,7

array is pointer to first element of array(contains adress of first element in array), so dereferencing it we get value of first element e.g. *array. We know that arrays are seqential which means that array+1 points to second element of array,so dereferencing this you get value of second element e.g. *(array+1), and so on. Memory segment of array

Same also aplies for strings because they are array of char, except string has '\0' (null character) at the end of strings.

    char str[128] = "Some Text";
    char *p;

    for (p = str; *p; p++)
    {
        printf("%c",*p);
    }

This program prints string str.

p = str //assign address of first character of string str to p,we don't won't to lose a track of first char in string so we use p not str to iterate

*p //this expresion means *p!=0 so this is true until you arrive at the end of string,remember that '0' in ascii has integer value 48

p++ //at the end of for block you add +1 to p to obtain adress of next char

0

It can be explained as follows :

for( initialization ; Conditional Expression ; expression3)
{
    Code here will execute while 2nd Expression(Conditional Expression) is true
    true means non-zero value
    '\0' is equivelant to 0,so when *p equal '\0' : loop will terminate
}
machine_1
  • 4,266
  • 2
  • 21
  • 42
  • 1
    absoloutly wrong! your description of an for loop is simply incorrect. It is the way it is usually used. BUT you are simplyfing it in a way, that just excludes its mainfeatures and anyway the wording itself is dim in regards to the expressions you used. – dhein Dec 18 '15 at 08:44
  • 1
    @Zaibis & machine_1: keep in mind though that this is an absolute beginner-level discussion (though Zaibis' post might teach even pros a thing or two). We tend to simplify a lot, like when teaching a child about how babies are born. For `machine_1`, perhaps a good way to avoid getting into trouble with the oversimplification is to qualify that this is what the code the op posted logically means from a human perspective in *this context*, and is not a technical breakdown of how a `for` loop generally works. –  Dec 18 '15 at 13:02
  • @Ike: I have no trouble with simplyfications in generall and I even could live with the first expression beeing called initialization. but the 3rd beeing degraded to "increment" is simply not correct! – dhein Dec 18 '15 at 14:36
  • @Zaibis For sure, though perhaps `machine_1` was specifically just trying to describe what's meant logically by `for(p=str; *p; p++)`, in which case his answer is no longer so inaccurate (describing things in terms of human logic, and just for that one piece of code). So my suggestion to `machine_1` is to edit and make that qualification, that this is describing what the code does, and not at all a general `for` loop. That would make this acceptable to you, no? –  Dec 18 '15 at 14:39