tags:

views:

4909

answers:

16

In the early days of C++ when it was bolted on top of C, you could not use NULL as it was defined as (void*)0. You could not assign NULL to any pointer other than void*, which made it kind of useless. Back in those days, it was accepted that you used 0 (zero) for null pointers.

To this day, I have continued to use zero as a null pointer but those around me insist on using NULL. I personally do not see any benefit to giving a name (NULL) to an existing value - and since I also like to test pointers as truth values:

if (p && !q)
  do_something();

then using zero makes more sense (as in if you use NULL, you cannot logically use p && !q - you need to explicitly compare against NULL, unless you assume NULL is zero, in which case why use NULL).

Is there any objective reason to prefer zero over NULL (or vice versa), or is all just personal preference?

Edit: I should add (and meant to originally say) that with RAII and exceptions, I rarely use zero/NULL pointers, but sometimes you do need them still.

+33  A: 

Here's Stroustrup's take on this: http://www.research.att.com/~bs/bs_faq2.html#null

That said, don't sweat the small stuff.

Martin Cote
Bjarne wrote this before C++ 0x started working on a new null type. It will be the case that NULL will be used for this type when it is available for a platform, and I think you'll see a C-change in the general consensus about this.
Richard Corden
I think you meant "sea-change", but it works as a pun nonetheless!
Tyler McHenry
+1 for "don't sweat the small stuff".
StackedCrooked
+6  A: 

I think the standard guarantees that NULL == 0, so you can do either. I prefer NULL because it documents your intent.

Mark Ransom
+1  A: 
mxg
You were not using a compliant compiler. The standard says NULL *is* 0 and that the compiler should convert 0 in a pointer context into a proper true NULL value for the arch.
Evan Teran
Yes, you are right. This was in mid-80s before ANSI produced a C standard. There was no such thing as compliance then and compiler writers were free to interpret the language as they saw fit. That's why a standard was necessary.
mxg
+8  A: 

If I recall correctly NULL is defined differently in the headers that I have used. For C it is defined as (void*)0, and for C++ it's defines as just 0. The code looked something like:

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

Personally I still use the NULL value to represent null pointers, it makes it explicit that you're using a pointer rather than some integral type. Yes internally the NULL value is still 0 but it isn't represented as such.

Additionally I don't rely on the automatic conversion of integers to boolean values but explicitly compare them.

For example prefer to use:

if (pointer_value != NULL || integer_value == 0)

rather than:

if (pointer_value || integer_value)
Daemin
+2  A: 

I'm with Stroustrup on this one :-) Since NULL is not part of the language, I prefer to use 0.

unforgiven3
+1  A: 

Mostly personal preference, though one could make the argument that NULL makes it quite obvious that the object is a pointer which currently doesn't point to anything, e.g.

void *ptr = &something;
/* lots o' code */
ptr = NULL; // more obvious that it's a pointer and not being used

IIRC, the standard does not require NULL to be 0, so using whatever is defined in <stddef.h> is probably best for your compiler.

Another facet to the argument is whether you should use logical comparisons (implicit cast to bool) or explicity check against NULL, but that comes down to readability as well.

Jimmy
+1  A: 

I always use 0. Not for any real thought out reason, just because when I was first learning C++ I read something that recommended using 0 and I've just always done it that way. In theory there could be a confusion issue in readability but in practice I have never once come across such an issue in thousands of man-hours and millions of lines of code. As Stroustrup says, it's really just a personal aesthetic issue until the standard becomes nullptr.

Gerald
+1  A: 

I prefer to use NULL as it makes clear that your intent is the value represents a pointer not an arithmetic value. The fact that it's a macro is unfortunate, but since it's so widely ingrained there's little danger (unless someone does something really boneheaded). I do wish it were a keyword from the beginning, but what can you do?

That said, I have no problem with using pointers as truth values in themselves. Just as with NULL, it's an ingrained idiom.

C++09 will add the the nullptr construct which I think is long overdue.

Michael Burr
+22  A: 

I stopped using NULL in favor of 0 long ago (as well as as most other macros). I did this not only because I wanted to avoid macros as much as possible, but also because NULL seems to have become over-used in C and C++ code. It seems to be used whenever a 0 value is needed, not just for pointers.

On new projects, I put this in a project header:

static const int nullptr = 0;

Now, when C++0x compliant compilers arrive, all I have to do is remove that line. A nice benefit of this is that Visual Studio already recognizes nullptr as a keyword and highlights it appropriately.

Ferruccio
Using NULL will be more portable long term. 'nullptr' will be available for some platforms and not for others. Your solution here requires that you use the preprocessor around your declaration to ensure that it's only present when required. NULL will do this automatically.
Richard Corden
I disagree. It will be less portable in the short term until compilers catch up. Long term, it will be just as portable and maybe a little more readable.
Ferruccio
Plus you can always #define nullptr NULL for your non-C++0x compiler.
Anteru
+16  A: 

Use NULL. NULL shows your intent. That it is 0 is an implementation detail that should not matter.

Andy Lester
0 is not an implementation detail. The standard defines 0 to be whatever bit pattern represents a null pointer.
Ferruccio
As if ..!! Dude, C++ is a low level language! Use 0, it's a well known idiom.
hasen j
+5  A: 

I always use:

NULL for pointers
'\0' for chars
0.0 for floats and doubles

where 0 would do fine. It is a matter of signaling intent. That said, I am not anal about it.

Andrew Stein
ya probably should use 0.0F for floats, to avoid the implicit typecast
EvilTeach
+20  A: 

There are a few arguments (one of which is relatively recent) which I believe contradict Bjarne's position on this.

1) Documentation of intent:

Using 'NULL' allows for searches on it's use and it also highlights that the developer "wanted" to use a NULL pointer, irrespective of whether it is being interpreted by the compiler as NULL or not.

2) Overload of pointer and 'int' is relatively rare

The example that everybody quotes is:

void foo(int*);
void foo (int);

void bar() {
  foo (NULL);  // Calls 'foo(int)'
}

However, at least in my opinion, the problem with the above is not that we're using NULL for the null pointer constant, it's that we have overloads of 'foo' which take very different kinds of arguments. The parameter must be an int too, as any other type will result in an ambiguous call and so generate a helpful compiler warning.

3) Analysis tools can help TODAY!

Even in the absence of C++ 0x, there are tools available today that verify that NULL is being used for pointers, and that 0 is being used for integral types.

4) C++ 0x will have a new 'std::nullptr_t' type.

This is the newest argument to the table. The problem of 0 and NULL is being actively addressed for C++ 0x, and you can guarantee that for every implementation that provides NULL, the very first thing that they will do is:

#define NULL  nullptr

For those who use NULL rather than 0, the change will be an improvement in type-safety with little or no effort - if anything it may also catch a few bugs where they've used NULL for 0. For anybody using '0' today....erm...well hopefully they have a good knowledge of regular expressions...

Richard Corden
Those are some rather good points, I must admit. I am glad that C++ 0x will have a null type, I think that will make a lot of stuff cleaner.
unforgiven3
Nice summary. A small nitpick - the new null will be the keyword 'nullptr' and/or the new type 'std::nullptr_t'
Michael Burr
@Mike, Was too lazy to check - thanks for doing so.
Richard Corden
@Richard, why not do the opposite? You can use Meyers nullptr_t then when 0x gets avaliable you remove the `#include` and keep in the safe side all the way.
fnieto
@fnieto: Good point. That approach has a safety advantage for C++ '98/'03 too.
Richard Corden
+6  A: 

I usually use 0. I don't like macros, and there's no guarantee that some third party header you're using doesn't redefine NULL to be something odd.

You could use a nullptr object as proposed by Scott Meyers and others until C++ gets a nullptr keyword:

const // It is a const object...
class nullptr_t 
{
public:
    template<class T>
    operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template<class C, class T>
    operator T C::*() const   // or any type of null member pointer...
    { return 0; }

private:
    void operator&() const;  // Can't take address of nullptr

} nullptr = {};

Google "nullptr" for more info.

jon

jon hanson
Any third-party library that defines NULL to anything other than 0 (or `(void*)0` if being compiled as C code) is just asking for trouble and should not be used.
Adam Rosenfield
+1  A: 

I try to avoid the whole question by using C++ references where possible. Rather than

void foo(const Bar* pBar) { ... }

you might often be able to write

void foo(const Bar& bar) { ... }

Of course, this doesn't always work; but null pointers can be overused.

Dan
+1  A: 

Someone told me once... I am going to redefine NULL to 69 and fuck all of you. Since then I don't use it :P

It makes your code quite vulnerable.

Edit:

Not everything in the standard is perfect. The macro NULL is an implementation-defined C++ null pointer constant not fully compatible with C NULL macro, what besides the type hiding implicit convert it in a useless and prone to errors tool.

NULL does not behaves as a null pointer but as a O/OL literal.

Tell me next example is not confusing:

void foo(char *); 
void foo(int); 
foo(NULL); // calls int version instead of pointer version!

Is because of all that, in the new standard appears std::nullptr_t

If you don't want to wait for the new standard and want to use a nullptr, use at least a decent one like the proposed by Meyers (see jon.h comment).

fnieto
`NULL` is a well defined part of the C++ standard. Letting people who like to redefine standard macros edit code in your project makes your code 'vulnerable'; using `NULL` doesn't.
Charles Bailey
I edit the post to answer
fnieto
A: 

Strange, nobody, including Stroustroup mentioned that. While talking a lot about standards and aesthetics nobody noticed that it is dangerous to use 0 in NULL's stead, for instance, in variable argument list on the architecture where sizeof(int) != sizeof(void*). Like Stroustroup, I prefer 0 for aesthetic reasons, but one has to be careful not to use it where its type might be ambiguous.

Michael Krelin - hacker