在c++的早期,当它被固定在C的顶部时,你不能使用NULL,因为它被定义为(void*)0。你不能将NULL赋值给除void*以外的任何指针,这使得它有点无用。在那些日子里,人们接受使用0(零)作为空指针。

直到今天,我仍然使用0作为空指针,但我周围的人坚持使用null。我个人认为给一个现有的值命名(NULL)没有任何好处-因为我也喜欢将指针作为真值测试:

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

那么使用0就更有意义了(就像如果你使用NULL,你不能在逻辑上使用p && !q -你需要显式地与NULL进行比较,除非你假设NULL为零,在这种情况下为什么要使用NULL)。

是否有任何客观的原因让人们更喜欢0而不是NULL(反之亦然),或者这只是个人偏好?

编辑:我应该补充(最初的意思是说),对于RAII和异常,我很少使用零/NULL指针,但有时你仍然需要它们。


当前回答

我曾经在一台机器上工作,其中0是一个有效地址,NULL被定义为一个特殊的八进制值。在该机器上(0 != NULL),因此代码如

char *p;

...

if (p) { ... }

不会如你所愿。你必须写

if (p != NULL) { ... }

虽然我相信现在大多数编译器都将NULL定义为0,但我仍然记得那些年前的教训:NULL不一定是0。

其他回答

主要是个人偏好,尽管有人可能会说,NULL使对象很明显是一个指针,目前不指向任何东西,例如。

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

IIRC,标准不要求NULL为0,所以使用<stddef.h>中定义的任何东西可能对你的编译器是最好的。

争论的另一个方面是是否应该使用逻辑比较(隐式转换为bool)或对NULL进行显式检查,但这也归结于可读性。

如果我回忆正确,NULL在我使用的头中定义不同。对于C,它被定义为(void*)0,而对于c++,它被定义为0。代码看起来像这样:

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

就我个人而言,我仍然使用NULL值来表示空指针,这表明你使用的是指针而不是某种整型。是的,在内部NULL值仍然是0,但它不是这样表示的。

此外,我不依赖于整数到布尔值的自动转换,而是显式地比较它们。

例如,更喜欢使用:

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

而不是:

if (pointer_value || !integer_value)

可以这么说,这在c++ 11中都得到了纠正,可以简单地使用nullptr而不是NULL,也可以使用nullptr的类型nullptr_t。

我曾经在一台机器上工作,其中0是一个有效地址,NULL被定义为一个特殊的八进制值。在该机器上(0 != NULL),因此代码如

char *p;

...

if (p) { ... }

不会如你所愿。你必须写

if (p != NULL) { ... }

虽然我相信现在大多数编译器都将NULL定义为0,但我仍然记得那些年前的教训:NULL不一定是0。

使用NULL。NULL表示你的意图。它是0是一个实现细节,应该无关紧要。

    cerr << sizeof(0) << endl;
    cerr << sizeof(NULL) << endl;
    cerr << sizeof(void*) << endl;

    ============
    On a 64-bit gcc RHEL platform you get:
    4
    8
    8
    ================

这个故事的寓意。在处理指针时应该使用NULL。

1)它声明了你的意图(不要让我搜索你所有的代码,试图找出一个变量是指针还是一些数字类型)。

2)在某些需要变量参数的API调用中,它们将使用null指针来指示参数列表的结束。在这种情况下,使用“0”而不是NULL可能会导致问题。在64位平台上,va_arg调用需要一个64位指针,但您将只传递一个32位整数。在我看来,你是在依靠其他32位来为你归零?我见过某些编译器(例如英特尔的icpc)不是那么友好——这导致了运行时错误。