我读过这篇文章。但是当我尝试时:
printf("before null %c after null\n", 0); // (ASCII=0) != '\0' ??
而不是得到:
before null
我有:
before null after null
所以我的问题是:ASCII 值 0 实际上等于 '\0' 吗?
我读过这篇文章。但是当我尝试时:
printf("before null %c after null\n", 0); // (ASCII=0) != '\0' ??
而不是得到:
before null
我有:
before null after null
所以我的问题是:ASCII 值 0 实际上等于 '\0' 吗?
ASCII 值 0 实际上等于
\0
吗?
是的
字符串在内存中存储方式和由类似函数处理的方式的差异printf()
很重要。
"before null %c after null\n"
"before null \0 after null\n"
两者都存储在内存\0
中,末尾有一个隐式终止符。\0
第二个在中间有一个明确的字符这一事实改变了事情。
printf()
将扫描字符串直到“结束”,打印组件......在C中“结束”通常意味着直到第一个\0
/ nul字符。
使用第一个变体,printf()
将字符复制到输出,直到它到达%c
指令,此时它会查看给函数的参数......它可能会发现你给了'\0'
,或者它可能发现你给了'+'
- 无论哪种方式,它将其复制到输出。然后它将继续将字符复制到输出,寻找字符串的“结尾”。
使用第二个变体,printf()
将开始将字符复制到输出,将找到“结尾”(由 表示\0
),然后停止。
如果您要使用snprintf()
,则结果/输出将包含以下内容:(同样,隐式\0
终止)
"before null \0 after null\n"
"before null "
如果您随后打印这两个,它们看起来相同,但内存内容会不同。
但是,输出printf()
是终端(或文件)......会发生什么\0
取决于您的终端模拟器......它可能根本没有显示,它可能显示为一个空格,或者它可能有一个有趣的框符号...
需要注意的重要一点是,这发生在运行时 - 而不是编译时。
原因是它实际上printf
并没有替换"Hello %s", "World"
为"Hello World"
then 打印它们。相反"Hello "
,它会"World"
在一行中单独打印每个字符,按顺序
如果您曾经尝试使用 打印单个null
字符putchar()
,您会注意到它会打印一个空格,这就是为什么printf
也基于它打印一个空格。
请注意,它不会在其他系统(例如 Linux)上打印任何内容。
printf 如何实际工作的示例代码。
const char * x;
// while the current char != '\0'
while (*format)
{
// if the current char == '%'
if (*format == '%')
{
// increment the pointer so we can point to the next char and skip printing '%'
switch (*(++format)) // then switch that next char (specifier).
{
case 'c':
putchar(va_arg(args, char)); // if the argument is null, then it's putchar(0);
break;
case 's':
// regular operation of printing a string argument.
x = va_arg(args, const char*);
while (*x) putchar(*x++);
break;
}
// skips the format specifier so we don't print it (e.g 's', 'c'..)
*format++;
}
// else: isn't a format specfier.
else
// print the current char (pointer) of the original string
putchar(*format++); // increments it for the next operation.
}
va_end(args);
所以回到你的问题,它会打印每个字符,当涉及到null0
的参数时,会根据你的系统放置一个空格或什么都没有。putchar()
您可以说printf
参数与终止它的原始字符串实际上没有任何关系,它们彼此不认识。
就像你一样printf("Hello %s, from SO!", "World");
, "World"
实际上以 结尾\0
,但它只会终止它自己,而不是另一个, from SO!
。
是的,0
是'\0'
。他们是同一个角色。
printf
当给定值或时,不会在格式说明符的该字符位置终止 printf 格式%c
字符串。相反,终端输出通常是占位符(例如 a等)0
'\0'
nul
space
但是,您可以将 anul
插入字符串,然后使用%s
格式说明符输出字符串,并看到实际上十进制0 实际上是等效 ASCII字符 的 ASCII 值,并将在nul 字符'\0'
处终止字符串(参见: www.ASCIItable.com ),例如
#include <stdio.h>
#define FMT "before null %c after null\n"
int main (void) {
char buf[sizeof FMT * 2];
puts (FMT);
sprintf (buf, FMT, 0);
printf ("using 0 : '%s'", buf);
putchar ('\n');
sprintf (buf, FMT, '\0');
printf ("using \\0: '%s'", buf);
putchar ('\n');
return 0;
}
示例使用/输出
$ ./bin/str_printf_null
before null %c after null
using 0 : 'before null '
using \0: 'before null '