在不同的计算机上打印'\0'会得到不同的结果吗?

3

以下代码在我的电脑上,字符\0始终会被打印为一个空格(使用cout命令)。然而,在我朋友的电脑上,字符\0始终会被打印为字符a。代码和截图如下:

#include <iostream>
using namespace std;

// Function main
int main()
{
    cout << "xxx" << '\0' << "yyy" << endl;
    return 0;
}

enter image description here enter image description here

左侧: 我的电脑。 右侧: 我朋友的电脑。

这里发生了什么?为什么不同的电脑上结果不同?

PS:

  1. 即使我们共享相同的可执行文件exe(即在我的电脑上编译并在两台电脑上运行),结果仍然会有所不同。

  2. 我们都使用visual studio 2010,并具有相同的项目字符集。

  3. 这里可能存在一些缓冲区溢出问题,但请注意,我将始终得到一个空格,而我的朋友将始终得到字符“a”。

  4. 如果我们都执行cout<<ends,则结果也将相同。


2
请发布代码。您不应该得到一个字符。 - MoonBun
2
我认为你应该提到不同的编译器,而不是不同的电脑。 - Digital_Reality
1
这似乎难以置信。你可以发布完整的代码,并附上在你朋友的电脑上运行时输出的截图吗? - David Grayson
1
@herohuyongtao dbasic 问你是否在运行相同的可执行文件,即在单个环境中编译一次,然后在两个不同的环境中运行,而不是在两个环境中编译相同的代码。 - JBentley
1
在我看来,字体大小似乎不同 - 可能实际上也是不同的字体?我认为,特定(可打印或不可打印)的“外观”取决于所使用的实际字体。 - Mats Petersson
显示剩余13条评论
5个回答

6
字符\0,或ASCII码0,不是可打印字符,没有标准的输出方式。
可打印的ASCII字符范围从0x200x7E,参见维基百科: ASCII

那么打印它就是未定义行为? - Suvarna Pattayil
但是为什么我总是会得到一个空格呢? - herohuyongtao
3
我认为这不是未定义行为,而是实现定义的行为。 - Yu Hao
1
@herohuyongtao https://dev59.com/63E95IYBdhLWcg3wPbZ7 - Suvarna Pattayil
2
@YuHao:不,实现定义行为 意味着每个实现都需要记录它所做的事情。没有要求记录打印空字符的效果。 - Keith Thompson
显示剩余5条评论

2
对于“不可打印字符”(对于ASCII码表而言,指范围在0x20-0x7e之外的字符),其输出实际上是未定义的,其视觉输出将取决于以下几个因素:
  1. 实际输出设备——如果您在Windows命令行提示符中查看此类字符,则其外观可能与Linux下的终端窗口不同,并且在使用真正的(30多年历史的)VT100终端时,其外观很可能会再次有所不同。事实上,当我第一次为使用串行输入的终端编写代码时,我们会使用NUL字符来“填充”某些控制序列,因为当转义序列变得“复杂”时,终端会丢失一些字符,例如清除屏幕,它可能无法接收下一个5-6个字符,因此我们会额外添加10个NUL字符,以便我们会丢失NUL而不是部分重要文本。
  2. 如果适用,则选择用于显示文本的字体也可能很重要(这似乎适用于这种特殊情况,但不要依赖它)。当然,这也适用于可打印字符,但除了一些“特殊”字体(Zapf Dingbats、Symbols等明显的例子)外,“可打印范围”与我们期望的匹配。而“不可打印”的范围则没有那么明确。
  3. 实际打印方法——例如,使用coutprintf将产生与在PC上“(文本模式下)将字符写入帧缓冲区存储器”的结果不同。
为了得到一致的非打印字符输出结果,您需要将其处理成定义为可打印的内容。
[*] 许多系统支持扩展范围,例如原始IBM / PC的范围为0x20-0xff,现代系统使用多个字节来表示在UTF-8编码中被定义为“非打印”的字符,例如常用字符[欧洲语言中]使用单字节编码,而不常用字符则使用两个、三个或四个字节编码。即使在此处,实际输出也取决于所选择的确切字体。

1
如上所述,它是实现定义的。在我的终端上,我得到了一个^@NULL终止符用于打印字符串,但在这种情况下,您正在尝试输出字符本身(它将具有不同的表示形式,从随机字符到无)。

好的,但请解释为什么在给定的电脑上它总是相同的? - herohuyongtao
@herohuyongtao 为什么输出结果会有差异? - user1508519
我的意思是,既然它是随机的,为什么在给定的电脑上总是相同的呢? - herohuyongtao
1
@herohuyongtao 这并不是随机的,而是由实现定义的。我的意思是它会以不同的方式呈现。 - user1508519
1
@herohuyongtao 在特定实现中,随机意味着它可能是任何东西,不是随机生成在每个输出上的那种随机。 - JBentley

0

'\0' 是一个终止字符,用于确定字符串的结束位置,因此例如这个会打印出 ab

#include <iostream>

int main(int argc, char* argv[])
{
    char str[]= { 'a', 'b', '\0' };
    std::cout <<str<< std::endl;
    return 0;
}

如果你只打印最后一个字符,它不应该打印任何东西,而是立即终止而不打印任何内容。

你所说的空格可能是由于 std::endl 引起的。

这里没有未定义的行为,未定义的行为通常是在相反的情况下引起的,即没有终止字符('\0'),然后你打印超出你分配块的内存,你打印的内容就是未定义的。

编辑:

这真的很奇怪,你所说的话毫无意义,请发布全部的代码。


不,这不是因为 endl。即使使用 cout << '\0',我也会得到一个空格。 - herohuyongtao
OP 打印的是 NUL 字符,而不是字符串...你的代码和讨论都不相关。 - Jim Balter

0
#include < iostream >
using namespace std;
int main()
{
    cout << "xxx" << '\0' << "yyy" << endl;
    return 0;
}

我不知道为什么你得到了不同的输出结果。 用g++再检查一遍。我用g++得到了这个输出结果。

enter image description here


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