C++ nil vs NULL

11

好的,我有一些C++代码在一个头文件中声明如下:

void StreamOut(FxStream *stream,const FxChar *name = nil);

我得到的错误信息是:

'nil' was not declared in this scope

nil是Pascal语言中的东西,对吗?

我应该使用NULL吗?

我以为它们都是一样的,或者至少是零,不是吗?


1
尽管它们两者都可以为零,但这并不意味着NULL = nil。它取决于许多因素,例如typedef的方式,声明/定义的方式等等。 - Ken White
7个回答

19

在C++中,你需要使用 NULL, 0 或者一些新编译器中的nullptr。在一些圈子中,使用 NULL 和 0 可能会引起一些争论,但在我看来,NULL 的使用比0更为普遍。


1
为了向其他人澄清,#DEFINE NULL 0null_ptr != NULLnull_ptr仅用于表示没有值的指针,0是一个有效的指针值,但除嵌入式系统外,它可能是无效的。 - joshperry
2
这是nullptr - Channel9上有一些很好的视频介绍它:http://channel9.msdn.com/shows/Going+Deep/Stephan-T-Lavavej-Everything-you-ever-wanted-to-know-about-nullptr/ - Johannes Schaub - litb
6
@joshperry,很抱歉你没有澄清问题,反而让它变得更加混乱了。0不是一个指针值,而是一个整数值,不受任何系统的限制。它可以被转换为指针值。请参见http://stackoverflow.com/questions/423823/whats-your-favorite-programmer-ignorance-pet-peeve/1331729#1331729。 - Johannes Schaub - litb
4
@Carl Norum,你使用了不同的“is”的定义。你说“A is B”当且仅当“A可以被转换成B”。当将参数传递给函数时,这个定义是有道理的。但对于大多数人来说(至少我会这样认为),如果把“is”从上下文中剥离出来,它表示“完全相同”。因此,这些人认为0既是整数又是指针,并且可能认为如果你执行ptr + 0(肯定是一个“指针上下文”),那么你可以把一个指针和一个空指针相加等等......最好清楚地说明“当需要时,将0转换为NULL指针”,以避免混淆。 - Johannes Schaub - litb
事实上,我相信正是这个“在某些情况下 0 是空指针”的说法让一些人认为在某些嵌入式系统中,“0”可能不可移植作为“空指针”。 如果改为“在某些情况下,0会转换为空指针”,就不会有这样的疑虑了。 - Johannes Schaub - litb
显示剩余4条评论

13

nil在标准C++中不存在。请使用NULL


6
是的。在C和C++中,它是NULL,在Objective-C中它是nil。
每种语言都有自己的无对象标识符。在C标准库中,NULL是((void *)0)的typedef。在C++标准库中,NULL是0或0L的typedef。
然而,在我看来,你永远不应该用0替代NULL,因为它有助于代码的可读性,就像在你的代码中使用常量变量一样:如果不使用NULL,则将值0用于空指针以及循环中的基础索引值以及空列表的计数/大小,这使得更难以知道哪一个是哪一个。此外,使用NULL更容易进行grep等操作。

1
IMO - 0 是一个整数值,NULL 表示一个指针。使用 0 让我怀疑程序员忘记了自己在做什么或者只是马虎大意。此外,sizeof(NULL) 应该与 sizeof(void)* 相同。 - NVRAM
2
@onebyone:在C++中,NULL是一个整数,但不一定特指'int'。可以将NULL定义为'OL',这意味着在这种情况下'sizeof(NULL) == sizeof(long)'。 - AnT stands with Russia
@AndreyT:虽然我同意并更喜欢在C++中使用0而不是NULL,在C中,null被定义为((void*)0),因此就C而言,sizeof(NULL)保证等于sizeof(void*) - David Rodríguez - dribeas
@AndreyT:哎呀,愚蠢的错误。你提醒了我,在标准的脚注中0L实际上是其中一个例子,是吗?感谢你的纠正。 - Steve Jessop
@dribeas:在 C 语言中,NULL 可以被定义为 (void *) 0,但不一定要这样定义。在 C 中,NULL 也可以被定义为普通的 0。实际上,在 C 中,NULL 甚至可以被定义为 '\0'。因此,在 C 语言中,sizeof(NULL)sizeof(void *) 不保证相同。 - AnT stands with Russia
显示剩余4条评论

1
如果你在glibc中进行搜索,你会找到这行代码:
#define NULL 0

这只是一种标记空指针的标准方式(不确定是否已经发布)。变量值为0仍然是一个值。指向0(0x0000...(它是十进制零))的指针实际上指向无处。这只是为了可读性。

int *var1, var2;
var1 = 0;
var2 = 0;

尽管这两个赋值看起来相同,但它们并不相同。


1

在C++中,0是被推荐和常用的样式。


3
Stroustrup并不是“推荐”这个做法,他更像是“个人倾向”这么做。 - AnT stands with Russia
1
我甚至不会说使用0是常见的。我看过一些有它的代码,但是把它称为常见的可能有点牵强。NULL倒是很常见的。 - Martin York
1
“如果你必须给空指针命名,就称其为nullptr” 对我来说听起来像是建议不要使用NULL(尽管空指针和空指针常量根本不是同一回事,但我认为他所说的是应该使用哪个字面值来生成空指针)。实际上这是一道直接的命令,但考虑到他并不是我的老板,我选择将其解释为建议;-) - Steve Jessop
1
+1 Guido。我更喜欢0。如果程序员不理解他们正在评估的参数或NULL代表什么(这是变化的),那么他们会遇到更大的问题。这是一个指针比较,不需要被包装或复杂化。如果我想要一个带标签(明确)的类型,我会为其创建一个描述性常量。 - justin

0

只需在开头添加

#define null '\0'

或者你可以选择其他的代替 null,并坚持你喜欢的。在 C++ 中,null 的概念只是指向空指针 (0x0)。

请注意,每个编译器可能都有自己的 null、nil、NULL 等定义,但最终它仍然是 0。

可能在你查看的源代码中有一个

#define nil '\0'

在头文件的某个地方...


1
你定义了一个 char 常量,用于处理以 null 结尾的字符串。操作码期望 nil 是一个指针。 - NVRAM
实际上我总是在我的 "common.h" 头文件中使用它,编译器从未抱怨,执行也没有问题。但也许加上 -Wall 编译选项会有所表示。 - Jack
1
实际上,在C和C++中将NULL定义为\0是完全有效的。我会很惊讶地看到这样的实现,但是\0仍然是定义NULL的有效方式。 - AnT stands with Russia
C++中2.13.2/4的证明表明:"转义符\ooo... [被] 用于指定所需字符的值"。因此,\0的值为零,是NULL的有效值。但我对C++中的false不确定:它的值是false而不是零,要变成零,需要升级为int或转换为另一个整数类型。但这需要整数和指针转换 - 因此将变得非法。但尽管如此,我尝试了各种实现,它们都接受false - Johannes Schaub - litb

0

我看到了一些有关为什么不使用0的评论。通常人们不喜欢魔术数字,或者有意义的数字。给它们起一个名字。在代码中,我宁愿看到 ANSWER_TO_THE_ULTIMATE_QUESTION 而不是 42。

至于 nil,在 Obj-C 中也使用 nil。我会很讨厌想到有人违反了非常流行的惯例(或者至少是我记得的),即使用 NULL,我认为这个应该在标准库头文件中。不过我已经有一段时间没有做 C++ 了。


1
个人认为,0是如此神奇,以至于假装你的意思是某种特殊类型的0是毫无意义的。当然,你可以说INTEGER_THAT_CONVERTS_TO_NULL_POINTER(这就是NULL的含义),或者你可以说DEFAULT_INITIAL_VALUE_OF_A_GLOBAL_INT_VARIABLE,或者INDEX_OF_FIRST_OBJECT_IN_AN_ARRAY。但是每个人都知道你的意思是0,并且在他们的头脑中将其翻译为0。我曾经小心地使用NULL,我不反对它,但我倾向于坚持使用0。对于'\0'也是一样,尽管我认为ASCII_NUL宏至少与NULL一样有用。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接