空字符终止符(\0)和 `^@` 之间的区别

4

我的代码如下:

#include <iostream>
using std::cout;
using std::endl;

int main(int argc, char *argv[])
{
    cout << (int)('\0') << endl;
    cout << (char)(0) << endl;
    return 0;
}

我期望在终端上看到像这样的内容:
$ test-program
0

$ 

然而,我看到的是这样的:
$ test-program
0
^@
$

我感到困惑的是,我认为'\0'可以转换为0,而0也可以强制转换为'\0'。我期望看到一个空字符紧随着endl,但结果却像'^@'这样奇怪。

有人对此有什么想法吗?


1
我在Windows上(使用MinGW gcc编译)得到了预期的结果。 - nhahtdh
使用 | hexdump -C 命令可以查看十六进制输出。这样你就可以确保 你的程序 执行的是你期望的操作,而不是终端表现出了你意料之外的行为。 - leemes
这是C++,所以类型很重要。在第一种情况下,需要显示一个整数0,然后将0转换为字符串"0"。在第二种情况下,它是一个真正的字符0,它确实是一个字符0。test-programm > result。使用带有--hexl-mode的emacs,它将确认这一点。第二点是终端显示字符0可能会有所不同,在您的情况下,字符0(通常不应该显示,因为在C中它结束了一个字符串)将显示为^@。 - philippe lhardy
4个回答

12

^@ 是终端仿真器呈现 '\0' 的方式。


7

^@ 通常表示 null 字符。同样的,^A 表示基数值为1的字符,^G 表示基数值为7的字符(bell),^M 表示基数值为13的字符(回车符)。

cout << (char)0

只是打印字符表示,而不是整数表示


1
如果你在查看终端的输出,你不知道是你的程序表现不如预期还是你的终端模拟器出了问题。
在类Unix系统上,使用./myProgram | hexdump -C来查看十六进制输出。这样你就可以确定你的程序是否按照你的预期运行,这样就可以确认是终端的问题而不是你的程序的问题:
00000000  30 0a 00 0a                                       |0...|
00000004

如果你看到的输出和我看到的一样,那么实际上你正在打印一个零 '0',一个换行符 '\n',一个空字符 '\0',还有一个换行符 '\n'。所以在这种情况下,你的程序表现得像你预期的那样。
你可能需要尝试不同的终端仿真器或设置。

0
如果你将 0 转换成 char,它并不会生成 '0',而是会生成 '\0'。请记住,从整数类型到 char 的转换会创建一个具有该 ASCII 码的 char
因此,基本上第二行输出了一个 null 字符(ASCII 0)。
如果你想输出一个 '0' 字符,你需要做的是像 (char)48 这样的事情,因为 48 恰好是字符 0 的 ASCII 值。

1
OP知道他正在打印空字符,或者至少从他提问的方式来看我认为他知道。 - nhahtdh
第一行是错误的,因为在这种情况下它显示的是零整数,而不是零字符。 - philippe lhardy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接