2

So here is the working version:

#include <stdio.h>

int main(int argc, char const *argv[]) {
    char myText[] = "hello world\n";
    int counter = 0;
    while(myText[counter]) {
        printf("%c", myText[counter]);
        counter++;
    }
}

and in action:

Korays-MacBook-Pro:~ koraytugay$ gcc koray.c
Korays-MacBook-Pro:~ koraytugay$ ./a.out 
hello world

My question is, why is this code even working? When (or how) does

while(myText[counter])

evaluate to false?

These 2 work as well:

while(myText[counter] != '\0')
while(myText[counter] != 0)

This one prints garbage in the console:

while(myText[counter] !=  EOF)

and this does not even compile:

while(myText[counter] != NULL)

I can see why the '\0' works, as C puts this character at the end of my array in compile time. But why does not NULL work? How is 0 == '\0'?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
  • 1
    `myText[counter]` is equivalent to `myText[counter] != '\0'`. checking nul character. `\0` is equivalent to `0` therefore `myText[counter] != 0` is valid too. – haccks May 29 '15 at 11:59
  • @MattMcNabb Why do you even bother to insult people? – Koray Tugay May 29 '15 at 12:04
  • 1
    @KorayTugay C is not well suited to learn by trial and error, because you never know if you are seeing standard behaviour or undefined behaviour. You really will save yourself a lot of time by learning from a good book – M.M May 29 '15 at 12:05
  • 1
    @ Koray That comment by @MattMcNabb has nothing personal, don't be offended, :-) – Sourav Ghosh May 29 '15 at 12:05
  • 1
    @MattMcNabb You did not answer my question. Why do you bother insulting people? – Koray Tugay May 29 '15 at 12:07
  • You can increase the quality of the post and answers by posting different questions as separate posts. – Matthias May 29 '15 at 12:10
  • 1
    `EOF` doesn't work because `'\0'==0` but `EOF==-1` – Spikatrix May 29 '15 at 12:11

5 Answers5

5

AS for your last question,

But why does not NULL work?

Usually, NULL is a pointer type. Here, myText[counter] is a value of type char. As per the conditions for using the == operator, from C11 standard, chapter 6.5.9,

One of the following shall hold:

  1. both operands have arithmetic type;
  2. both operands are pointers to qualified or unqualified versions of compatible types;
  3. one operand is a pointer to an object type and the other is a pointer to a qualified or unqualified version of void; or
  4. one operand is a pointer and the other is a null pointer constant.

So, it tells, you can only compare a pointer type with a null pointer constant ## (NULL).

After that,

When (or how) does while(myText[counter]) evaluate to false?

Easy, when myText[counter] has got a value of 0.

To elaborate, after the initialization, myText holds the character values used to initialize it, with a "null" at last. The "null" is the way C identifies the string endpoint. Now, the null, is represented by a values of 0. So, we can say. when the end-of-string is reached, the while() is FALSE.

Additional explanation:

  • while(myText[counter] != '\0') works, because '\0' is the representation of the "null" used as the string terminator.

  • while(myText[counter] != 0) works, because 0 is the decimal value of '\0'.

Above both statements are equivalent of while(myText[counter]).

  • while(myText[counter] != EOF) does not work because a null is not an EOF.

Reference: (#)

Reference: C11 standard, chapter 6.3.2.3, Pointers, Paragraph 3

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

and, from chapter, 7.19,

NULL
which expands to an implementation-defined null pointer constant


Note: In the end, this question and realted answers will clear the confusion, should you have any.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
2

When (or how) does this work?

while(myText[counter])

Any built-in with value zero will evaluate to false in a boolean context. So this while(myText[counter]) is false when myText[counter] is '\0', which has the value 0.

How is 0 == '\0'?

It is defined that way in the language. '\0' is an int literal with value zero. 0 is also an int literal with value zero, so both compare equal, and they both evaluate to false in a boolean context

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

In C, any non-zero value evaluates to true. C strings are null-terminated. That is, there is a special zero-value character after the last character in the string.

And so when the null terminator is reached, the zero value evaluates to false, and the loop terminates.

I can see why the '\0' works, as C puts this character at the end of my array in compile time. But why does not NULL work? How is 0 == '\0'?

0 has the same value as '\0' because '\0' is a character with the value zero. (Not to be confused with '0', which is the zero digit and has a value of 48.)

Regarding NULL, that actually can work since it also evaluates to zero. However, NULL is a pointer type so you may have to type cast to avoid errors. (Hard to say for certain since you didn't post the error that you got.)

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
  • complie time error is: warning: comparison between pointer and integer ('int' and 'void *') – Koray Tugay May 29 '15 at 12:12
  • 3
    Yes, as I indicated you may need a type cast to convert `NULL` to an integer. But that's kind of silly since `NULL` is basically zero cast to a pointer. Makes more sense to compare against 0. – Jonathan Wood May 29 '15 at 12:17
1

How is 0 == '\0'?

All characters have an 8-bit numeric value, for example, 'a' is 97 (decimal). The backslash in the character literal '\0' introduces an "escape" to directly specify the character through its numeric value. In this case, the numeric value 0.

Bruno De Fraine
  • 45,466
  • 8
  • 54
  • 65
1
  1. The termination of a string is \0
  2. NULL is used to initialise a pointer to a determined value

while(myText[counter]) evaluates to false as soon as counter points to the zero byte.

In the end there is nothing different than a zero byte at the end of the string. Actually NULL would mean the same but it is used for notation purposes only in the context of pointers.

If something is not 100% clear from a coding perspective, you might want to look inside your debugger watch window, what are the bits and bytes actually during program execution.

Matthias
  • 1,386
  • 3
  • 24
  • 59
  • "*... and a pointer not yet being initialised NULL*" this somehow is incomplete, isn't it? I simply do not get what you want to express. – alk May 29 '15 at 12:36
  • Yes, it was not complete. I rewrote the first paragraph. – Matthias May 29 '15 at 12:40
  • "*A pointer which is not yet initialised is NULL*" this not correct. An unitialised variable has an *undetermined* value. To have a pointer carry `NULL` it explicitly needs be assigned: `char * p = NULL;`. And since C99 you also could to `char * p = 0;` – alk May 29 '15 at 12:47
  • What I want to say is: NULL is used to initialise a pointer to a determined value :) – Matthias May 29 '15 at 12:54