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

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

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

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

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

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

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

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

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

C,IMNSHO中的最佳实践是对空字符使用'\0' ,对于空指针使用 0不为 NULL

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

 #define NULL ((char *)0) 

 #define NULL ((void *)0) 

 #define NULL 0L 

 #define NULL 0 

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

 if (h1 == 0) 

或者更简单:

 if (!h1) 

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

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

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

或者更简单:

 while (buf[i]) 

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

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

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

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