【问题标题】:'\0' evaluates false, "\0" evaluates true'\0' 评估为假,"\0" 评估为真
【发布时间】:2016-08-25 08:03:43
【问题描述】:

K&R 5.5 节中描述的程序的启发:

void strcpy(char *s, char *t)
{
    while(*s++ = *t++);
}

C 程序

if ('\0') { printf("\'\\0\' -> true \n"); }
else      { printf("\'\\0\' -> false\n"); }

if ("\0") { printf("\"\\0\" -> true \n"); }
else      { printf("\"\\0\" -> false\n"); }

打印

'\0' -> false
"\0" -> true

为什么 '\0'"\0" 在 C 中的计算方式不同?

clang 版本 3.8.0

【问题讨论】:

  • 第一个是nul-character,第二个是empty-string
  • 因为它们是不同的东西,为什么它们会评估相同?
  • 你为什么要将字符串/字符与布尔值进行比较?
  • @LightnessRacesinOrbit K&R 中描述的将 char[] 的内容复制到另一个的程序:while((dest[i++] = source[i++]));。记不太清了,明天查。
  • 出于同样的原因“假”为真。

标签: c arrays string null kernighan-and-ritchie


【解决方案1】:

回想一下字符串文字在 C 中是如何工作的 - "\0" 是一个包含两个零字节的字符数组(您要求的一个,最后是隐含的一个)。在为if 测试评估时,它衰减为指向其第一个字符的指针。该指针不为NULL,所以当作为条件使用时被认为是真的。

'\0' 是数字零,相当于 0。它是一个零整数,所以当它作为条件使用时被认为是假的。

【讨论】:

  • @M.M:这是一个字符串文字;)
  • 是的,字符串字面量是 char 数组
  • 这个“"\0" is a pointer to a character array”不适合 28++ 投票的答案,因为它在两个方面都是错误的。 "\0" 不是指针,而是数组,如果这个数组由于某种原因衰减为指针,它就不会指向数组而是指向它的第一个元素。
  • @MrLister 指向数组的指针和指向数组元素的指针是两种不同的野兽。
  • @MrLister char (*ptr)[] = &"test"; 将是指向字符串文字的指针,而char* ptr = "test"; 将是指向字符串文字"test" 的第一个字符的地址的指针。
【解决方案2】:

首先,你需要记住,在 C 中,

  • 零为假,非零为真。
  • 对于指针类型,NULL 为假,非NULL 为真。

'\0',正如其他人所说,与整数文字 0 相同,因此是错误的(请参阅上面的第一个要点以了解原因)。

"\0" 是一个包含两个\0 字符的字符串文字(一个是您显式添加的,另一个是隐式的,将由编译器添加)。字符串文字将存储在只读内存中的某个位置。 当您使用"\0" 时,它会转换为指向其第一个元素的指针。这通常称为“array decay”。 (这就是 char* str = "string"; 这样的东西起作用的原因)。

所以,您正在有效地检查字符串文字的第一个字符的地址。由于字符串文字的地址将始终为非NULL,因此 if 将始终为真(请参阅上面的第二个要点了解原因)。


:数组的这种“衰减”并不总是发生。见Exception to array not decaying into a pointer?

【讨论】:

  • 您当然是正确的,值 0 为假。但是,char 不一定与整数相同。除非您明确指定无符号,否则 int 始终是有符号的。 char 是否签名取决于实现!
  • '\0' 是一个int,IIRC,虽然它看起来像一个char
  • 另外,我不确定 unsignedsigned 与这里的相关性。我的意思是unsignedsignedcharint,都可以代表0。
  • 这显示了 0/NULL 的(恕我直言太常见)速记测试的问题。如果 OP 写了例如"if ("\0" == NULL),问题出在哪里就很明显了。
  • 请注意,'\0' 在 C++ 中是 char,尽管在 C 中是 int
【解决方案3】:

'\0' 是一个数字:0,因此它被评估为假(0 = 假,!0 = 真)。

但是"\0" 是一个指向存储实际字符串的只读部分的指针,该指针不是NULL,所以这是真的。

【讨论】:

  • "\0" 不是指针。它是一个字符串字面量,它的值是一个数组(在大多数但不是所有上下文中都隐式转换为指针)。
【解决方案4】:

首先看两个条件,'\0'是整数类型的常量,表示空字符C,与0相同。 "\0" 是一个字符串文字,它包含 2 个字节,一个指定的字节和一个隐式添加的空终止符字节。作为字符串文字,指针不能是NULL

其次,在 C 中,对于 if 语句的条件,所有非零都被评估为 true,而零被评估为 false

根据这条规则,很明显'\0'false,而"\0" 被评估为true

【讨论】:

  • 您的回答没有解释为什么"\0" 会被视为true
  • @alk "\0" 将是 true,而不是 false
  • 我说的是字符串文字,不能是NULL,所以是true
  • 我知道这一点。但从你的回答中并不明显。对于那些 not 知道“字符串”在某些条件下会衰减为指向其第一个元素的指针的人来说并不明显,因为 OP 可能不知道。
  • "作为字符串文字,指针不能是 NULL" -- 解释一下您所指的指针会很有帮助(尽管其他答案已经覆盖)。
【解决方案5】:

首先请注意,False 的十六进制值是0x00,True 是 0x00 以外的任何值。

"\0" 是一个字符串,末尾有一个字符和空终止符'\0'。所以它是一个字符指针,指向一个2字节的数组:['\0', '\0']。在这个数组中,第一个是字符,另一个是空终止符。

编译后(没有优化),这个字符指针被临时分配给内存中的一个地址,指向这两个字节的第一个字节。例如,此地址可能是十六进制的0x18A6。所以编译器(大多数)实际上将这两个值写入内存。因为字符串实际上是该字符串的第一个字节的地址,所以我们的表达式被解释为 0x18A6 != false 。所以,很明显0x18A6 != 0x00 是真的。

'\0' 只是十六进制的0x000x00 != 0x00 是假的。

此答案是针对具有 16 位寻址的 8 位数据架构编写的。我希望这会有所帮助。

【讨论】:

    【解决方案6】:

    '\0' 是一个 null 字符,其值为 0。它用于终止一串字符。所以它被认为是错误的。

    "\0"nullempty 字符串。字符串中唯一的字符是终止字符串的空字符。所以它被认为是真的。

    【讨论】:

    • 这不仅仅是“被认为是真实的”。 C 中的字符串文字只是指向其第一个元素的指针,这就是被评估为 true 的内容。
    • @lemondrop 字符串文字不是指针。在某些上下文(例如 OP 的代码)中,字符串文字可能会转换为指针
    • "字符串中唯一的字符是终止字符串的空字符"这并不完全正确。这个“字符串”("\0") 包含 两个 '\0' 个字符。
    • "所以它被认为是真的。" 而这个 "So" 从中提取任何证据,为什么文字 "\0" 会评估为 " true" 从您的回答中并不明显。
    • @cat sizeof "" 不等于 sizeof "\0"
    【解决方案7】:

    '\0' 是一个等于数字零的字符。 "\0" 是一个字符串,我们通常在字符串末尾添加 '\0'。不要在条件语句中使用 '\0' 或 "\0",因为这很容易混淆。

    建议如下用法:

    if (array[0] != 0)
    {
    
    }
    
    if (p != 0)
    {
    
    }
    
    if (p != NULL)
    {
    
    }
    

    【讨论】:

    • 我总是希望看到'\0' 在条件句中使用,因为它表明您将“事物”作为字符串处理,而不是数字数组。
    【解决方案8】:

    通过示例查看此内容..

    #include <stdio.h> 
    
    int main() 
    { 
    printf( "string value\n" ); 
    
    //the integer zero 
    printf( "0.........%d\n" , 0 ); 
    
    //the char zero, but chars are very small ints, so it is also an int 
    //it just has some special syntax and conventions to allow it to seem 
    //like a character, it's actual value is 48, this is based on the 
    //ASCII standard, which you can look up on Wikipedia 
    printf( "'0'.......%d\n" , '0' ); 
    
    //because it is an integer, you can add it together, 
    //'0'+'0' is the same as 48+48 , so it's value is 96 
    printf( "'0'+'0'...%d\n" , '0'+'0' ); 
    
    //the null terminator, this indicates that it is the end of the string 
    //this is one of the conventions strings use, as a string is just an array 
    //of characters (in C, at least), it uses this value to know where the array 
    //ends, that way you don't have to lug around another variable to track 
    //how long your string is. The actual integer value of '\0' is zero. 
    printf( "'\\0'......%d\n" , '\0' ); 
    
    //as stated, a string is just an array of characters, and arrays are tracked 
    //by the memory location of their first index. This means that a string is 
    //actually a pointer to the memory address that stores the first element of 
    //the string. We should get some large number, a memory address 
    printf( "\"0\".......%d\n" , "0" ); 
    
    //a string is just an array of characters, so lets access the character 
    //in position zero of the array. it should be the character zero, which 
    //has an integer value of 48 
    printf( "\"0\"[0]....%d\n" , "0"[0] ); 
    
    //and the same thing for the empty string 
    printf( "\"\\0\"[0]...%d\n" , "\0"[0] ); //equal to '\0' 
    
    //we also said a string is just a pointer, so we should be able to access 
    //the value it is pointing to (the first index of the array of characters) 
    //by using pointers 
    printf( "*\"0\"......%d\n" , *"0" ); 
    
    return 0; 
    }
    

    【讨论】:

      【解决方案9】:

      简单的事情是 ATLEAST 0 (int) 和 0.0 (float or double) 在 C 中具有 FALSE 值。

      '\0' 是整数 0。

      "\0" 是一个字符数组。数组内部有多少个字符或这些字符是什么并不重要。

      因此,'\0' 的计算结果为 0,就像 77-77 的计算结果为 0。 0 为假。

      int x; x = '\0'; printf("X has a value : %d"); 输出:


      x 有一个值:0

      还有代码:

      if(0){printf("true");}
      
      else{printf("false");}
      

      输出:


      【讨论】:

        【解决方案10】:

        我们可以用两个不同的C概念来解决上述问题

        1. if(condition) 在 C 中的工作
        2. C 中字符和字符串文字的区别

        1.在 C 中 if( 条件 ) 的工作 如果(条件)

        在 C 语言中,如果条件适用于 0(零)和非零基数。

        如果给定条件的结果为零,则 C 认为给定条件为假。

        如果给定条件的结果为非零,则 C 认为给定条件为真。

        2. C中字符和字符串文字的区别

        在C语言中,字符串文字是用双引号(“”)括起来的文字,而字符文字是用单引号('')括起来的文字,最小长度是一个字符,最大长度是两个字符。

        另一个重要的一点是,在 C 中,如果我们将 '\0' (null) 转换为 int (Integer),那么我们将得到 0(Zero),而我们不能将 "\0" 隐式或显式转换为 int。因为 "\0" 是字符串,而 '\0' 是字符。

        并且根据字符串IF条件的工作逻辑,如果条件返回0或假,则表示条件为假;如果条件返回非零,则表示条件为真。

        所以,根据第 1 点和第 2 点,我们最终可以得出结论

        if ('\0') printf("\'\0\' != false\n"); //条件变为假

        if ("\0") printf("\"\0\" != false\n"); //条件变为真

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-01
          • 2018-07-01
          • 1970-01-01
          • 2019-05-24
          • 1970-01-01
          • 1970-01-01
          • 2012-09-11
          • 1970-01-01
          相关资源
          最近更新 更多