5

From time to time, I run into communications issue with other programmers, when we talk about NULL. Now NULL could be

a NULL pointer
the NUL character
an empty data element in some sort of database.


NUL seems to be the most confusing. It is the ASCII character 0x00.
I tend to use '\0' in my code to represent it. Some developers in my group
tend to prefer to simply use 0, and let the compiler implicitly cast it to a char.


What do you prefer to use for NUL? and why?

raven
  • 18,004
  • 16
  • 81
  • 112
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
  • \0 is NUL, not NULL. Thus, I reverted to the OP's original revision. – C. K. Young Oct 21 '08 at 00:54
  • 1
    Is your question about, clarity of conversation or clarity of code? Please clarify. – mxcl Oct 21 '08 at 00:59
  • It's both really. Verbally, it doesn't really do much to set the context. In code I prefer to avoid the extra code that is caused by the implicit cast. I am interested in seeing how other developers deal with this issue, or at least get some other viewpoints on how to think about it. – EvilTeach Oct 21 '08 at 01:49
  • What is the intent of each of these lines? char x = NULL;
    char *x = NULL;
    char *x = 0;
    char x = 0;
    char *x = '\0';
    char x = '\0';
    – EvilTeach Oct 21 '08 at 01:51
  • They all sort of deposit the same nice binary pattern, but the intent isn't clear. NULL has a pointer connotation with it, while 0 has an integer connotation while '\0' is closer to being NUL. – EvilTeach Oct 21 '08 at 01:55

15 Answers15

10

I use '\0' for the nul-character and NULL for pointers because it is clearest in both cases.

BTW, both 0 and '\0' are ints in C and either one will be converted to char when stored in a char variable.

Robert Gamble
  • 106,424
  • 25
  • 145
  • 137
  • humm. i was under the impression that a character in single quotes is a char in c. – EvilTeach Oct 21 '08 at 01:43
  • In C++ a character constant with a single character is type char, in C a character constant is type int. – Robert Gamble Oct 21 '08 at 01:54
  • 0 is _not_ `int` in C. It's a special integer literal which doesn't have type as such, but can be used in either `int` or pointer context (much like C# `null`). – Pavel Minaev Jul 23 '09 at 09:10
  • @Pavel: 0 *is* an int in C which is a regular integer value like any other. When the literal 0 is converted to a pointer the result is a null pointer and because of that 0 or (void *)0 is called a null pointer constant but that does not change the fact that before converting it to a pointer 0 is an integer and after converting it to a pointer it is no longer an integer but a null pointer. You might want to review section 5 of the c-faq (http://c-faq.com/null/index.html). – Robert Gamble Jul 23 '09 at 12:22
5

I like the pre-defined NULL macro, as it preserves the semantic meaning, rather than some other use of the number 0.

Matt J
  • 43,589
  • 7
  • 49
  • 57
4

There are many English words which are spelled or spoken alike, yet which have different meanings. Like in English, use the context in which the discussion is taking place to guide you toward the intended meaning.

yfeldblum
  • 65,165
  • 12
  • 129
  • 169
4
  • For dealing with strings, I alwayse represent the null character as '\0'.
  • For pointers, I try to use implicit-conversion-to-boolean (if (!myPtr) or if (myPtr)) for pointer nullity.
  • If I need a default value for a pointer, it's NULL, e.g. struct list_head = { 0.0, NULL };).

END_OF_STRING is silly, since it's extra indirection that simply confuses new readers (anyone who doesn't immediately recognize '\0' should step away from the keyboard).

One other thing—I think the difference between a null value and an empty value is extremely important when talking about data modeling. This is especially true when discussing C-style strings or nullable database fields. There's a huge difference between someone telling you "I have no name" and "My name is ."

Tom Barta
  • 1,264
  • 7
  • 3
  • 1
    And to increase clarity, I typically explicitly check against NULL when using an assignment statement as in an if-statement: if ((myPtr = GetData()) != NULL) { /* do work on myPtr */ } – Isak Savo Oct 22 '08 at 08:14
3

@BKB:

I see the point in his advice, but "NULL" makes it clearer that the context is pointers. It's like using "0.0" for floating-point values, as '\0' when dealing with characters. (Likewise, I prefer seeing 0 if a char is being used in an arithmetic context.)

Bjarne further states in this FAQ that NULL is #defined as 0 anyway, so standard code shouldn't have a problem with it. I agree that the all-caps notation is ugly, but we'll have to wait until 0x (where nullptr will be available, as a keyword.)

aib
  • 45,516
  • 10
  • 73
  • 79
3

If I remember correctly most C compilers define NULL like this:

#define NULL ((void*)0)

This is to ensure that NULL is interpreted as being a pointer type (in C). However this can cause issues in the much more type strict world of C++. Eg:

// Example taken from wikibooks.org
std::string * str = NULL; // Can't automatically cast void * to std::string *
void (C::*pmf) () = &C::func;
if (pmf == NULL) {} // Can't automatically cast from void * to pointer to member function.

Therefore in the current C++ standard null pointers should be initialized with the literal 0. Obviously because people are so used to using the NULL define I think a lot of C++ compilers either silently ignore the issue or redefine NULL to be 0 in C++ code. Eg:

#ifdef __cplusplus
#define NULL (0)
#else
#define NULL ((void*)0)
#endif

The C++x0 standard now defines a nullptr keyword to represent null pointers. Visual C++ 2005's CLI/C++ compiler also uses this keyword when setting managed pointers to null. In current compilers you can create a template to emulate this new keyword.

There is a much more detailed article on wikibooks.org discussing this issue.

orj
  • 13,234
  • 14
  • 63
  • 73
  • NULL and 0 are equivalent in C++. You can use NULL to initialize pointers without a problem in both languages. Any C++ library that defines NULL in the old C-style is nonconforming. – Dan Olson Jul 23 '09 at 09:20
3
A one-L NUL, it ends a string. 
A two-L NULL points to no thing. 
And I will bet a golden bull 
That there is no three-L NULLL. 



(The name of the original author is, alas, lost to the sands of time.)
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
1

NULL for databases, NIL for code.

JosephStyons
  • 57,317
  • 63
  • 160
  • 234
1

I quite like

#define ASCII_NUL ('\0')

I only very occasionally mistype '\0' as '0'. But when I have done it, I've found the error very hard to spot by code inspection, with hilarious consequences. So I don't like '\0' much, and prefer ASCII_NUL or 0 (of course the latter has the wrong type in C++). Obviously I use '\0' where demanded by consistency with existing code, or style guides.

The Google C++ style guide, which contains a few things I like and a few I don't, but seems mostly sound, prefers NULL to 0 for pointers. It points out that NULL might not be defined simply as 0 (or 0L), especially in implementations where sizeof(void*) might not be sizeof(int) (or sizeof(long int)).

0 and NULL are both specified to be of integral type, and when converted to a pointer type they both must yield a null pointer value. But they aren't necessarily of the same integral type. So you might conceivably get some useful warnings or errors in some situations by using NULL.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
1

While, on the whole, I would advice using named constants, this is one exception. To me, defining:

#define NULL 0
#define END_OF_STRING '\0'

makes as much sense as defining:

#define SEVEN 7

which is none. And yes, I am aware that NULL is already defined by the compiler, but I never use it. For pointers, 0; for chars, '\0'. Longer does not always mean more expressive.

Gorpik
  • 10,940
  • 4
  • 36
  • 56
  • The difference as I see it is that "7" is a symbol which always means "seven" (as a C token, at least). '\0' is of course used as a string terminator, but that isn't always and inherently what a 0 byte means, so it's not synonymous with end-of-string, any more than 200 is synonymous with success. – Steve Jessop Oct 21 '08 at 14:39
  • That said, I don't see anything wrong with using '\0' as a literal, just because it sometimes is used for other things as well. But I also don't think that using a name is pointless, since there is a semantic difference even though the value of end-of-string will of course be 0 in all C programs. – Steve Jessop Oct 21 '08 at 14:41
  • I guess I was thinking more C++ than C here. \0 is end-of-string only for null-terminated strings. So I think it is much clearer than END_OF_STRING, which might not actually be and end-of-string. And END_OF_NULL_TERMINATED_STRING is getting things too far. – Gorpik Oct 22 '08 at 08:16
  • Really Gorpik :) wouldn't that be END_OF_NUL_TERMINATED_STRING ? – EvilTeach Aug 03 '19 at 16:49
0

Sort of related: Slashdot recently had a story on the comp.lang.c FAQ section on null pointers, which I found quite interesting.

Martin Geisler
  • 72,968
  • 25
  • 171
  • 229
0

For communication I use NULL. If I'm working with a developer who cannot grasp the concept of NULL for different data-types then I'd be concerned.

For implementation it's case-specific. Numbers are 0 (post-fixed f for floating-point), pointers are NULL and character strings are 0.

Andrew Grant
  • 58,260
  • 22
  • 130
  • 143
0

Systems that don't use binary 0 for NULL are getting harder to find. They also tend to have various portability issues. Why? Because on these systems neither memset nor calloc can clear out a struct that contains pointers correctly.

Joshua
  • 40,822
  • 8
  • 72
  • 132
0
const char END_OF_STRING = '\0';

So when you say:

str[i] = END_OF_STRING;

or

if (*ptr == END_OF_STRING)

there is absolutely no question what you mean.

James Curran
  • 101,701
  • 37
  • 181
  • 258
0

We use NULL for pointers and NULLCHAR for characters, using

#define NULLCHAR '\0'
Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121