首页 文章

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

提问于
浏览
4

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

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

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

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

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

3 回答

  • 7

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

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

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

    C,IMNSHO中的最佳实践是使用 '\0' 作为空字符,而 0 - 不是 NULL - 作为空指针 .

  • 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)
    

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

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

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

    或者更简单:

    while (buf[i])
    
  • 1

    NULL 有效地用作链表或指针数组的空终止符 . '\0' 用作字符串的空终止符(即char数组)

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

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

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

相关问题