4

我读过这篇文章。但是当我尝试时:

  printf("before null %c after null\n", 0);  // (ASCII=0) != '\0' ??

而不是得到:

before null 

我有:

before null   after null

所以我的问题是:ASCII 值 0 实际上等于 '\0' 吗?

4

3 回答 3

5

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取决于您的终端模拟器......它可能根本没有显示,它可能显示为一个空格,或者它可能有一个有趣的框符号...

需要注意的重要一点是,这发生在运行时 - 而不是编译时。

于 2018-06-09T07:03:39.830 回答
3

原因是它实际上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'。他们是同一个角色。

于 2018-06-09T06:44:48.650 回答
1

printf当给定值或时,不会在格式说明符的该字符位置终止 printf 格式%c 字符串。相反,终端输出通常是占位符(例如 a等)0'\0'nulspace

但是,您可以将 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 '
于 2018-06-09T06:57:33.883 回答