1

I have the following code -

#include <stdio.h>
#define LENGTH 5
int main(){
    char* ch[LENGTH] = {"Zero", "One", "Two", "Three", "Four"};
    char* pc;
    char** ppc;
    for(int i=0; i<LENGTH; i++){
        ppc = ch+i;
        pc = *ppc;
        while(*pc != 0){
            printf("%c ", *pc);
            pc = pc +1;
        }
        printf("\n");
    }
    return 0;
}

It is an example of multiple indirection using string.

The output is

Z e r o 
O n e 
T w o 
T h r e e 
F o u r 

Here in while() loop instead of *pc != '\0', *pc != 0 is used.

But both the approaches give same output. Why is it so?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Suraj
  • 724
  • 1
  • 9
  • 17
  • 1
    Answers will explain why. I'd just like to agree that it makes no sense to compare a character to an integer while processing characters. It should be either `while (*pc != '\0')` or _`while (*pc)`_. – Tom Blodget Dec 15 '17 at 17:39

4 Answers4

8

A char is really nothing more than a small integer, and as such are implicitly convertible to int. Furthermore character literals (like e.g. 'A') are really represented by the compiler as int values (for example the literal character 'A' is represented by the int value 65 in ASCII encoding).

The C language allows one to insert any arbitrary integer (that can fit in a char) using escapes. There are two ways to escape such arbitrary values, using octal numbers, or using hexadecimal. For example, the ASCII value for A is 65, that can be represented as either 'A', '\101' in octal, '\x41' in hexadecimal, or plain 65.

Armed with that information it should be easy to see that the character literal '\0' is the octal representation of the integer 0. That is, '\0' == 0.

You can easily verify this by printing it:

printf("'\\0' = %d\n", '\0');

I mentioned that the compiler treats all character literals as int values, but also mentioned that the arbitrary numbers using escaped octal or hexadecimal numbers needs to fit in a char. That might seem like a contradiction, but it isn't really. A characters value must fit in a char, but the compiler will then internally convert it to an int when it parses the code.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    Note that in C they *are* `int`s. No conversion, however implicit, is therefore necessary. – Bathsheba Dec 15 '17 at 08:09
  • Could not follow. Can you please elaborate? – Suraj Dec 15 '17 at 08:13
  • @Suraj Every character can be represented by an ASCII value ranging from 0 to 255. The value of the ASCII of `NULL` is 0 so its return true when you compare it with it. The same goes for the letter 'a' which has an ASCII value of 97 for example, if you compare `'a'==97` it will return `true`. – Ahmed Karaman Dec 15 '17 at 12:08
  • @Someprogrammerdude I am sorry because my comment was obscure. I did follow your answer. What I could not follow is your first comment. – Suraj Dec 15 '17 at 13:33
  • @Suraj Updated the answer to hopefully make it easier to understand. – Some programmer dude Dec 15 '17 at 13:49
7

Line feed \n, tab \t etc has their own escape sequence characters, but actually there does not exist one for the null terminator.

The industry de facto standard way of represending the null terminator is therefore to write an octal escape sequence with the value zero. Octal escape sequences are defined as \ followed by a number. So \0 simply means zero, with octal representation. Since this looks similar to other character escape sequences, it has become the de facto standard way of representing the null terminator.

This is why a decimal 0 works just as fine, it is just another way of writing the value zero. You could as well write \x0 if you wish to be obscure.

Lundin
  • 195,001
  • 40
  • 254
  • 396
4

Adding to the existing answers, to look into the sentinel, quoting C11, chapter §5.2.1

In a character constant or string literal, members of the execution character set shall be represented by corresponding members of the source character set or by escape sequences consisting of the backslash \ followed by one or more characters. A byte with all bits set to 0, called the null character, shall exist in the basic execution character set; it is used to terminate a character string.

and from chapter §6.4.4.4/P12,

EXAMPLE 1 The construction '\0' is commonly used to represent the null character.

So, a constant \0 is the one which satisfies the aforesaid property. This is a octal escape sequence.

Now, regarding the value, quoting §6.4.4.4/P5, (emphasis mine)

The octal digits that follow the backslash in an octal escape sequence are taken to be part of the construction of a single character for an integer character constant or of a single wide character for a wide character constant. The numerical value of the octal integer so formed specifies the value of the desired character or wide character.

so, for a octal escape sequence '\0', the value is 0 (well, both in octal, as mentioned in §6.4.4.1, and decimal).

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 3
    Backslash followed by `0` is an octal escape sequence. `0` in octal is `0` (which actually is also octal for the same reason) – M.M Dec 15 '17 at 08:06
4

0 and '\0' are exactly the same value, and in C, are both int types. This is fixed by the C standard and is irrespective of the character encoding on your platform. In other words, they are completely indistinguishable. (In C++, the type of '\0' is a char.)

So while(*pc != 0), while(*pc != '\0'), and while(*pc) for that matter are all the same thing.

(Personally I find the last one I give the clearest, but some folk like to use the '\0' notation when working with C-style strings.)

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • No it's well-defined C++ too, although in that language you'd be advised to use the `std::string` class from the C++ Standard Library. Plus C++ compilers might complain more about the fact that the string literals decay to a `const char*` pointer, not a `char*` pointer. – Bathsheba Dec 15 '17 at 08:01
  • What is the disadvantage of "using namespace std;" ? – Suraj Dec 15 '17 at 08:04
  • @Suraj: That's a curve-ball for this question. Essentially it pollutes your global namespace. – Bathsheba Dec 15 '17 at 08:05
  • what is the meaning of "pollute global namespace"? – Suraj Dec 15 '17 at 08:06
  • @Suraj: Everything from `std` is available without the scope resolution operator. In large code bases that can cause clashes with other tokens and even wreak havoc with overload resolution. See https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – Bathsheba Dec 15 '17 at 08:08