何时使用NULL以及何时使用' \ 0'在C的链表中?

时间:2015-09-20 19:43:18

标签: c pointers linked-list

我在C:null char == '\0' == NULL中学到了这一点,我在下面写了一个循环来读取C中char []的开头到结尾。

// case #1
char buf[32];
while (buf[i] != NULL){
    //do something...
}  

然而,我的gcc编译器给了我一个警告:指针和整数之间的比较。有人提到我混淆了两个不同的概念:NULL用于指针,而' \ 0'是为了人物。所以为了摆脱警告,我应该使用' \ 0'因为我的循环测试了一个char。

现在我正在编写一个链表,并测试一个头指针是否指向一个节点。由于它的结构,使用if (h1 == NULL)是合理的,但显然当我使用if (h1 == '\0')时编译器也会编译,即使节点是结构但不是char。有人可以给出一些帮助,为什么这两个' \ 0'在这种情况下可以使用NULL和NULL,而它们不能同时用于第一种情况吗?

// case #2
struct ListNode {
    int val;
    struct ListNode *next;
};

3 个答案:

答案 0 :(得分:8)

这是一个非常普遍的混乱。 A" null字符" (由于历史原因,通常拼写为NUL,只有一个L)是字符,它等于零。 A"空指针"是指针,它比较等于零。差异只是类型 - 但这是一个重要的区别。允许编译器(但不是必需)反对程序,因为您正在将字符值与null 指针常量进行比较。

C有一个相当松散的类型系统,特别是当涉及整数常量时,所以你可以在很多时候使用具有正式错误类型的常量。当它达到零时尤其如此:整数文字0可以在任何可以安全使用宏NULL或字符文字'\0'的地方使用。实际上,特别允许在C标准的所有版本中使用#define NULL 0。因此,有一小部分上下文,其中一个绝对必须使用(T*)0来表示某个具体类型T,而不是0NULL,例如,当将空指针传递给一个带有可变数量参数的函数时(例如execl)。

作为混淆蛋糕的进一步锦上添花,C字符文字的类型为int,而不是char,而'\0'是合法的空指针常量。 (在C ++中,这些都不是真的。)

C,IMNSHO的最佳做法是使用'\0'作为null 字符0 - NULL - 对于null 指针

答案 1 :(得分:3)

根据编译器的不同,可能会以不同的方式定义NULL

#define NULL ((char *)0)

#define NULL ((void *)0)

#define NULL 0L

#define NULL 0

NULL用于指针比较。但是,整数0是允许进行指针比较的特殊情况,这就是为什么您可以直接将ListNode*指针与0进行比较的原因(否则上面的NULL定义了不存在指针类型转换不起作用):

if (h1 == 0)

或更简单:

if (!h1)

{C}中'\0'字符文字是int,可隐式转换为C ++中的int。所以'\0'也可用于指针比较。

您应该使用'\0'(或仅0)进行字符比较,不要使用NULL

while (buf[i] != '\0') // or 0

或更简单:

while (buf[i])

答案 2 :(得分:1)

NULL实际上用作链表或指针数组的空终止符。 '\0'用作字符串的空终止符(即字符数组)

如果你有一个结构数组,你可能想要遍历它们直到你到达结尾:

MyStruct** things = ...
for(int i = 0; things[i] != NULL; i++) {
    // Do something with things[i]
}

当指向最后一个结构的指针为NULL时,此循环将结束。