#define MYNULL ((void*)0)
但是在以下语句中,这个定义并不起作用:
char *ch = MYNULL;
错误:无法将void*转换为char*
如何最好地定义NULL?
#define MYNULL NULL
这是最安全的方法,我认为没有必要这样做,但如果你真的想这样做,可以这样操作。 下面分别是 C 和 C++ 的方法:
#define NULL 0 //C++
#define NULL ((void*)0) //C
通常情况下,将0定义为NULL是一种不好的习惯,你实际上希望它成为语言的一部分。C++0x 解决了这个问题。
Bjarne Stroustrup 对此有以下看法:
我应该使用 NULL 还是 0?
在 C++ 中,NULL 的定义为 0,因此只有美学上的区别。我喜欢避免使用宏,所以我使用 0。另一个使用 NULL 的问题是,人们有时会错误地认为它与 0 不同和/或不是整数。在早期标准之前的代码中,NULL 有时被定义为某些不适当的内容,因此必须避免使用。但现在这种情况已经不太常见。
如果你必须给空指针命名,就叫它nullptr;这就是 C++11 中它的名称。然后,“nullptr” 将成为关键字。
#ifdef __cplusplus
#define MYNULL 0
#else
#define MYNULL ((void*)0)
#endif
它们两个都能起作用。
你从预期的地方获取 NULL 的问题究竟出在哪里?即,
#include <stddef.h>
或者 #include <cstddef>
正如@Johannes Rudolph的答案中所提到的,你所做的任何诡计都不太可能在面对像nullptr
等内容时具有很好的未来性。
编辑:虽然stdlib(和许多其他库)被要求包括NULL
,但是stddef是最经典的头文件[并且已经是几十年了]。
PS:通常情况下,涉及此类技巧都不是一个好主意,除非你有一个真正的好理由。你没有详细说明导致你感觉需要这样做的思路。如果你能添加一些细节,那么可能会得到更好的答案。其他回答问题的人也应该指出这点,但我猜FGITW最擅长的就是这个:D
编辑2:正如@Yossarian所指出的那样:唯一使用这种技巧的理由是如果在您的系统中没有以适当的语言无关形式定义NULL。裸编译器没有头文件和/或如果您正在从头开始编写自己的自定义标准库,则是这种情况的示例。 (在这种基本情况下,我会选择@lilburne的答案(尽量使用0
))
#define MYNULL 0
将会在C++中工作。
NULL
定义为0
是可以的,只是会稍微降低类型安全性。然而,在C语言中正确使用0
作为NULL
不会产生任何错误。如果你要反驳可变参数的哨兵值,建议即使使用NULL
也要转换为char*
类型。 - Evan Teranchar* ch = NULL
和
char* ch = 0;
是最小的。当涉及到表达式时,形式如下:
if (NULL == ch) {
}
if (0 == ch) {
}
if (nullptr == ch) {
}
没有更可读性高
if (!ch) {
}
0
和隐式强制转换为int而不是NULL
。(但是当它混淆这些问题时,我不会给它+1 :D) - Ruben Bartelink#define NULL 0 //for C
这是C语言中的完美定义
例如:
char *ch = NULL ;
*ch++ ;// will cause error
由于在执行增量语句时,指针ch指向空值,因此导致错误。编译器通过查看LOOK-UP表中指针的值为0来知道这一点。
如果你尝试更新该指针,则实际上是更改了从0物理地址开始的CODE区域的内容。因此,在代码区域开始之前,页表的第一个条目保持为空。
到底是从你应该得到NULL的地方出现了什么问题呢?
#include <stddef.h>
或者
#include <cstddef>
正如@Johannes Rudolph的回答中所提到的,你所做的任何诡计都不太可能在nullptr等因素面前具有未来可靠性。
编辑:虽然stdlib(和许多其他库)被强制包含NULL,但stddef是最经典的头文件[已经有几十年了]。
PS通常情况下,除非你有一个非常好的理由,否则千万不要涉及这种诡计。你没有详细说明导致你感觉需要这样做的思考过程。如果你能添加一些细节,那么很可能会得到更好的答案。其他回答问题的人也应该在他们的回答中指出这一点,但我猜FGITW最擅长做什么:D
编辑2:正如@Yossarian指出的那样:唯一的理由是如果在你的系统中没有以适当的语言无关形式定义NULL。裸编译器没有头文件和/或如果你正在从头开始编写自己的自定义标准库,则是这种情况的示例。(在这种基本的情况下,我会选择@lilburne的答案(尽可能使用0))
http://c-faq.com/null/null2.html
顺便说一句,comp.lang.c常见问题解答对于每个C程序员都是一个强烈推荐的阅读资料。例如在这里:
http://c-faq.com/null/null1.html
包含着那些几乎被遗忘的智慧珠玑,例如“如上所述,每种指针类型都有一个空指针,并且不同类型的空指针的内部值可能是不同的。” 这意味着calloc或memset不是指针的可移植初始化。
str
)?因为它很容易让读者混淆,他们可能会错误地认为你对NUL处理感兴趣。但我的真正问题是(就像@Neil Butterworth问的那样),为什么要这样做?(或者你能澄清一下你希望实现什么吗?你是想让一个单一的显式常量同时扮演指针和NUL字符的双重角色吗?) - Ruben Bartelink