【问题标题】:'\0' and printf() in C'\0' 和 printf() 在 C
【发布时间】:2020-05-23 14:52:02
【问题描述】:

在 C 的入门课程中,我了解到,在存储字符串时,在其末尾使用空字符 \0 存储。但是如果我想打印一个字符串,比如printf("hello"),虽然我发现它不是以\0 结尾的,但下面的语句

printf("%d", printf("hello"));

Output: 5

但这似乎是不一致的,据我所知,字符串之类的变量存储在主内存中,我猜在打印某些内容时它也可能存储在主内存中,那么为什么会有差异?

【问题讨论】:

  • 除了您的代码至少遗漏了);,您打算用该代码显示什么?你如何证明它不是以\0 结尾的?
  • 它存储的内存与它有什么关系?
  • 在 C 中,所有文字字符串都是真正的字符数组,其中包括空终止符。
  • @glglgl 我认为 printf() 返回它应该在屏幕上打印的字符数。
  • @AjayMishra 是的,它确实应该打印 5 个字符。终止的 0 字节不打印在屏幕上。

标签: c printf stdout c-strings


【解决方案1】:

空字节标记字符串的结尾。它不计入字符串的长度,并且在使用printf 打印字符串时不打印。基本上,空字节告诉执行字符串操作的函数何时停止。

如果您创建一个用字符串初始化的char 数组,您会看到不同之处。使用sizeof 运算符将反映数组的大小,包括空字节。例如:

char str[] = "hello";
printf("len=%zu\n", strlen(str));     // prints 5
printf("size=%zu\n", sizeof(str));    // prints 6

【讨论】:

  • 我认为printf() 的故事会有所不同。 TBH 我不知道printf() 是如何工作的。
【解决方案2】:

printf 返回打印的字符数。 '\0' 未打印 - 它只是表示此字符串中不再有字符。它也不计入字符串长度

int main()
{
    char string[] = "hello";

    printf("szieof(string) = %zu, strlen(string) = %zu\n", sizeof(string), strlen(string));
}

https://godbolt.org/z/wYn33e

sizeof(string) = 6, strlen(string) = 5

【讨论】:

    【解决方案3】:

    你的假设是错误的。您的字符串确实以 \0 结尾。

    它包含5个字符hello和0个字符。

    “内部”print() 调用输出的是打印的字符数,即 5。

    【讨论】:

      【解决方案4】:

      在 C 中,所有文字字符串实际上都是字符数组,其中包括空终止符。

      但是,空终止符 计入字符串的长度(无论是否为字面量),并且它不会被打印出来。当找到空终止符时,打印停止

      【讨论】:

      • 有没有在不将字符串存储在数组中的情况下验证这一点?
      • @AjayMishra 好吧,字符串已经 is 在数组中(如前所述)...但是如果没有空终止符,那么 printf 将超出范围字符串,并打印“随机”或“垃圾”字符,并返回一个与字符串长度不同的数字。如果您已经知道字符串的长度,您还可以检查该索引处的字符是否为'\0',如果数组的大小不包括终止符(如char arr[5] = "hello"; ,这不会将终止符添加到数组中)。
      • @AjayMishra 是的,例如,您可以执行 char * p = "Hello"; int i = 0; while (p[i] != '\0') { printf("%d: %c", i, p[i]); i++; } 并查看它是如何运行的:它显示带有索引的行和该行的内容。在索引 4 之后,它找到 0 字符并中断 while 循环。在那里你看到有一个 0 字符。
      【解决方案5】:

      所有答案都很好,但我想添加另一个示例来完成所有这些

      #include <stdio.h>
      
      int main()
      {
          char a_char_array[12] = "Hello world";
      
          printf("%s", a_char_array);
          printf("\n");
      
          a_char_array[4] = 0; //0 is ASCII for null terminator
      
          printf("%s", a_char_array);
          printf("\n");
      
          return 0;
      }
      

      对于那些不想在在线 gdb 上尝试的人,输出是:

      世界你好

      地狱

      https://linux.die.net/man/3/printf

      这有助于理解转义终止符的作用吗?它不是 char 数组或字符串的边界。这个角色会对解析-STOP,(打印)解析到这里的人说。

      PS:如果你将其解析并打印为 char 数组

      for(i=0; i<12; i++)
      {
          printf("%c", a_char_array[i]);
      }
      printf("\n");
      

      你得到:

      地狱世界

      其中,double l 之后的空格是空终止符,但是,解析 char 数组时,将只是每个字节的 char 值。如果您进行另一次解析并打印每个字节的 int 值 ("%d%,char_array[i]),您将看到(您得到 ASCII 码 int 表示)空白的值为 0。

      【讨论】:

        【解决方案6】:

        C函数中printf()返回打印的字符个数,\0是一个null终止符,在c语言中用于表示字符串的结束,没有内置string类型为c++,但是您的数组大小需要至少大于您要存储的 char 的数量。

        这里是参考:cpp ref printf()

        【讨论】:

          【解决方案7】:

          但是如果我想打印一个字符串,比如 printf("hello") 虽然 我通过以下语句发现它不以 \0 结尾

          printf("%d", printf("hello"));
          
          Output: 5
          

          你错了。此语句未确认字符串文字 "hello" 不以终止零字符 '\0' 结尾。此语句确认函数printf 输出字符串的元素,直到遇到终止零字符。

          当您在上面的语句中使用字符串文字时,编译器 创建一个包含字符串文字元素的静态存储持续时间的字符数组。

          所以其实这个表达式

          printf("hello")
          

          由编译器处理,如下所示

          static char string_literal_hello[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
          printf( string_literal_hello );
          

          函数printf在这个动作中你可以想象如下方式

          int printf( const char *string_literal )
          {
              int result = 0;
          
              for ( ; *string_literal != '\0'; ++string_literal )
              {    
                  putchar( *string_literal );
                  ++result;
              }
          
              return result;
          }
          

          要获取字符串文字“hello”中存储的字符数,可以运行以下程序

          #include <stdio.h>
          
          int main(void) 
          {
              char literal[] = "hello";
          
              printf( "The size of the literal \"%s\" is %zu\n", literal, sizeof( literal ) );
          
              return 0;
          }
          

          程序输出是

          The size of the literal "hello" is 6
          

          【讨论】:

            【解决方案8】:

            你必须先明确你的概念.. 当您处理数组时它将被清除,您正在使用的打印命令只是计算放在括号内的字符。它在数组字符串中必须以 \0

            结尾

            【讨论】:

              【解决方案9】:

              字符串是字符的向量。包含形成的字符序列 字符串,后跟特殊结束字符 字符串:'\0'

              示例: char str[10] = {'H', 'e', 'l', 'l', 'o', '\0'};

              示例:以下字符向量不是一个字符串,因为它不以'\ 0'结尾

              char str[2] = {'h', 'e'};

              【讨论】:

              • 我猜 C 中没有向量。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2023-03-04
              • 2014-01-17
              • 1970-01-01
              • 2015-05-24
              • 1970-01-01
              • 2013-08-18
              • 1970-01-01
              相关资源
              最近更新 更多