#define NULL NULL

9
#ifndef NULL
#define NULL NULL
#endif

这段代码在gcc中编译时没有警告/错误。请问有人能解释一下这里的预处理器是做什么的吗?

1
在C/C++中,NULL并不意味着未定义... - Artelius
3
这可能比使用#define SIXTY_NINE 69更好。http://bugpwr.blogspot.com/2007/07/magic-numbers-in-code.html - Pavel Radzivilovsky
尝试执行以下操作: #ifndef NULL #define NULL 0 #endif - TripleS
@TripleS - 我永远不会在生产代码中这样做。我只是在某个地方看到它,觉得很有趣,值得思考。 - J. Polfer
1
其实我也在某个地方看到过这个...但我不会把它作为最终解决方案。据说在C++的开头,NULL被定义为零。 - TripleS
7个回答

20

无论在哪里编译器看到文本“NULL”,它都会用文本“NULL”替换它。这就像在代码中执行搜索和替换“NULL”为“NULL”。这不是非法的,只是有点奇怪 :)


6
我认为值得注意的是,除非未定义NULL,否则几乎肯定不会执行此操作。NULL通常已定义,因此此代码块可能不起作用。 - Adam

16
唯一可能这样做的原因是在包含自己执行类似操作的头文件之前执行。
#ifndef NULL
#define NULL (void *)0
#endif

这样就可以防止NULL被定义成那样了。


8
先生,我很喜欢你的头像。我很久没有想起过《旋转木马》这个游戏了。 - J. Polfer
这难道不会引起更加神秘的问题吗?为什么你想要阻止在其他头文件中定义NULL? - Aaronaught
3
这个问题也被标记为C++,在Stroustrup的书的§5.1.1中,他推荐以下定义:const int NULL = 0; - Greg Bacon

5

这是正常现象:

#ifndef JON_SKEET
#define JON_SKEET JON_SKEET
#endif

这也可以编译通过。这是因为预处理器只是进行无意义的替换。它替换的内容和替换成的内容不需要是有效的标识符。
可以这样理解:打开编辑器的“查找和替换”窗口,在“替换”和“替换为”字段中都输入“NULL”。它不会给出任何错误或警告,虽然实际上它什么也没做。预处理器也是这样做的。
显然当你尝试使用它时:
'JON_SKEET'未声明(在此函数中第一次使用) (每个未声明的标识符仅报告一次 对于它出现的每个函数。)

是的,但是像那样的块通常意味着符号被定义的事实才是重要的。这对于NULL来说非常奇怪。 - Aaronaught
不是必须的,没有这个要求。 - Andreas Bonini

3

我曾经看到过这样的代码,它将一个值从编译器命名空间(一般来说,并不是C++中的namespace)带到了预处理器命名空间中,例如:

// In the compiler namespace, not in the preprocessor namespace
static int const FOO = 1234;

// Bring the constant into the preprocessor namespace as well
#ifndef FOO       // <---- FOO really is undefined here.
#define FOO FOO
#endif

真的很丑陋。

个人而言,我还没有找到这种东西的用途,但它仍然存在。


编辑:虽然我见过这个,但我不知道为什么它会有用,除了检查代码中是否定义了"FOO"作为预处理器符号;也许在处理一些遗留代码时。 任何人都可以解释吗?


哦,我原本以为我可以用那个,但后来意识到那是错误的。如果 FOO 已经被定义过了,在 static int const FOO = 1234; 这一行中它将被替换。我不知道为什么你会愿意在这些情况下继续进行。#define FOO FOO 可能有意义,正如你所说的,如果你要用常量替换宏,但又不想更改一些检查其是否被定义的旧代码。但是在定义常量 FOO 时让 FOO 被定义为其他东西,对我来说听起来像是麻烦事。 - Steve Jessop

2

显然,这不是作为宏使用,而是作为编译标志使用。您是否在代码的其他地方看到过 #ifdef NULL#ifndef NULL

将“NULL”作为这样的标志使用非常奇怪,但我见过更奇怪的用法 (#define TRUE FALSE)...


1

回答关于预处理器的问题:

除非有先前的代码取消了 NULL 的定义,否则它会完全跳过 #define NULL NULL。NULL 几乎肯定已经被定义了。在 C++ 中,由于 C++ 更严格的类型检查,使用 0 是首选。如果必须使用 NULL,则最好声明 const int NULL = 0;(请参见 Stroustrup 的第 5.1.1 节)。


0

这不是简单地将NULL定义为字符序列"NULL"吗?


1
不。应该是 #define NULL "NULL" - Andreas Bonini
2
当你说字符序列并使用引号时要小心,因为它可能看起来像是在引用一个C字符串字符数组"NULL" - catchmeifyoutry

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