为什么printf函数会忽略后者\ 0?

时间:2019-06-30 13:13:40

标签: c

我坚持使用\ 0的某些功能。

我知道\ 0是一个空字符,它是一个表示形式是字符串的术语。

a2

当我尝试打印“ abcdef \ 0abcdefg \ 0”时,C只打印字符串“ abcdef”和“ 6”,而不是总计“ 13”的“ abcdef”和“ abcdefg”。为什么发生这种情况?

3 个答案:

答案 0 :(得分:0)

这里

j = printf("abcdef\0abcdefg\0"); /* printf stops printing once \0 encounters hence it prints abcdef */

printf() 从字符串常量"abcdef\0abcdefg\0"的基地址开始打印,即从a开始打印,直到遇到第一个\0字符。因此它打印abcdef

 -----------------------------------------------------------------
| a | b | c | d | e | f | \0 | a | b | c | d | e | f | f | g | \0 |
 -----------------------------------------------------------------
0x100 0x101 ...............|                                0x100 - assume this as base address of the string literal      
  |                        |
starts printing      when printf sees
from 0x100 memory    first \0
location             it stops the printing & returns.

然后printf()返回可打印字符数,即6

printf("%d", j); /* prints 6 */

printf的手册页中

  

返回值

     

成功返回后,这些函数将返回   打印的字符(不包括空字节,用于结束输出   至          字符串)。

答案 1 :(得分:0)

C中的字符串是一个字符序列,后跟NUL字符'\0'。没有单独的“长度”字段。

当字符串以文字形式显示时,例如"hello",实际上存储在内存中的是:

'h', 'e', 'l', 'l', 'o', '\0'

因此,您可以看到,如果字符串本身包含'\0',那么就任何C标准库函数而言,它就是字符串的结尾。

一旦printf看到字符串中的第一个'\0',它将停止打印并返回,因为那是格式字符串的结尾。 printf无法知道'\0'之后还有另一个字符串。在那之后,也许有-或者也许在内存中只是随机的其他程序数据。无法分辨出差异。

如果要实际打印'\0'字符,则需要采用其他方法来跟踪字符串的“实际”长度,并使用接受该长度作为参数的函数。另外,您可以在格式化过程中通过在格式字符串中指定'\0'并传递%c作为字符值来添加0字符。

答案 2 :(得分:0)

"abcdef\0abcdefg\0"(字符串文字)实际上是staticconst(出于各种目的)char数组,因此它具有与编译器相关的大小维护:

#include <stdio.h>
#define S "abcdef\0abcdefg\0" 
//^string literals implicitly add a(nother) hidden \0 at the end
int main()
{
    printf("%zu\n", sizeof(S)); //prints 16
}

但是数组在C中被特殊对待,并将它们作为参数传递给函数,或者几乎所有运算符都将其转换为指向其第一个元素的指针。

指针没有关联的大小。

当您将char const*传递给函数(例如printf)时,该函数仅接收一个数字-第一个元素的地址。

C中的printf和大多数字符串函数获取大小的方法是对字符进行计数,直到第一个'\0'

如果您将指针传递到char数组的第一个元素中,该数组的第一个元素具有显式嵌入的零,则对于直到第一个'\0'为止一直计数的函数,字符串实际上在第一个结尾'\0'