3

Is comparing a pointer to '\0' legal?

On the trunk version of clang++ (25836be2c)

const char *a = "foo";

if(a == '\0')

gives an error: comparison between pointer and integer ('const char *' and 'int')

whereas

if(a == 0)

does not give any error as expected.

Isn't the null character equivalent to the null pointer for comparisons with pointer? Is this a compiler bug?

Another point is that this error does not show up with "-std=c++03" flag but shows up with "-std=c++11" flag. However, I don't get the error in both standards when I use g++ (v4.8.5)

Ajay Brahmakshatriya
  • 8,993
  • 3
  • 26
  • 49
MIA
  • 130
  • 7
  • 1
    Note that newer versions of GCC *do* give an error. – Sebastian Redl Dec 18 '17 at 09:26
  • Before C++11 they were the same; post C++11 the first one is an error – M.M Dec 18 '17 at 10:26
  • 2
    _"Isn't the null character equivalent to the null pointer for comparisons with pointer?"_ - no. This has always been a bad habit, and was never a good idea. There isn't a "null" character, but there is a NUL character. There is a `nullptr`, but that isn't a character. There's absolutely no reason to mix the two concepts up. – Useless Dec 18 '17 at 10:37
  • @Useless Other way around: there's no NUL in Standard C++ (that is an ASCII thing). However there is the null character, which is defined as the character with value 0 – M.M Dec 18 '17 at 18:57
  • @M.M - fair point, I really don't like the way "null" and "NULL" are named, as it seems to encourage confusion, so I got in the habit of calling the character `nul` to slightly reduce ambiguity. OP: there _is_ a "null" character, but it's still not useful to compare that to a pointer. – Useless Dec 18 '17 at 21:33

2 Answers2

5

This was a change from C++03 to C++14. In C++03, [conv.ptr]p1 says:

A null pointer constant is an integral constant expression rvalue of integer type that evaluates to zero.

A character literal is an integral constant expression.

In C++14, [conv.ptr]p1 says:

A null pointer constant is an integer literal with value zero or a prvalue of type std::nullptr_t.

A character literal is not an integer literal, nor of type std::nullptr_t.

The originally published version of C++11 didn't contain this change; however, it was introduced due to defect report DR903 and incorporated into the standard sometime after January 2013 (the date of the last comment on that DR).

Because the change is the result of a DR, compilers treat it as a bugfix to the existing standard, not part of the next one, and so Clang and GCC both made the behavior change when -std=c++11, not just when -std=c++14. However, apparently this change wasn't implemented in GCC until after version 4.8. (Specifically, it seems to have only been implemented in GCC 7 and up.)

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
4

From [conv.ptr]§1:

A null pointer constant is an integer literal with value zero or a prvalue of type std​::​nullptr_­t. [...]

'\0' is not an integer literal, it's a character literal, thus the conversion does not apply.

Quentin
  • 62,093
  • 7
  • 131
  • 191
  • In the C standard, character constants are said to have type int. Is it not so in C++? Can you please give me a reference to the section where it says that '\0' is a character type and not an integer type – MIA Dec 18 '17 at 09:41
  • @Pratik - Not a standard reference, but a related question https://stackoverflow.com/questions/2172943/size-of-character-a-in-c-c – Bo Persson Dec 18 '17 at 09:52
  • 5
    @PratikBhatu C is **not** C++. They are different languages, hence you shouldn't expect the same behavior. – Algirdas Preidžius Dec 18 '17 at 09:52
  • @PratikBhatu It is not so in C++ but *the type is irrelevant*. A character literal is *syntactically* different from an integer literal, regardless of type. – n. m. could be an AI Dec 18 '17 at 10:51
  • @PratikBhatu [[lex.ccon]§2](http://eel.is/c++draft/lex.ccon#2): "A character literal that does not begin with `u8`, `u`, `U`, or `L` is an *ordinary character literal*. An ordinary character literal that contains a single *c-char* representable in the execution character set has type `char`, [...]" – Quentin Dec 18 '17 at 12:28