为什么命令提示符和 PowerShell 给出的输出结果与终端不同?

为什么命令提示符和 PowerShell 给出的输出结果与终端不同?

我有一本书中的以下示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  printf("Hello World (pid:%d)\n", (int) getpid());
  int rc = fork();

  if (rc < 0)
  {
    //fork failed
    fprintf(stderr, "fork failed\n");
    exit(1);
  }

  else if (rc == 0)
  {
    //child (new process)
    printf("Hello I am child (pid:%d)\n", (int) getpid());
  }

  else
  {
    //parent goes down this path (main)
    printf("Hello, I am parent of %d (pid:%d)\n",
            rc, (int) getpid());
  }

  return 0;
}

在 Windows(powershell 和命令提示符)中,我得到以下信息:

Hello World (pid:1283)
Hello, I am parent of 1284 (pid:1283)Hello I am child (pid:1284)

在 Linux (终端) 中我得到:

Hello World (pid:1923)
Hello, I am parent of 1924 (pid:1923)
Hello I am child (pid:1924)

如下图所示。

为什么相同的代码在不同的程序中显示不同?Windows 是否只是根据其读取代码的方式错误地显示输出?还是它的编译器出了问题?我在 Linux 上使用附带的 gcc。我在 Windows 上使用 cygwin gcc。

Windows 上的 PowerShell

powershell-windows

Linux 上的终端

终端Linux

Windows 上的命令提示符

cmd窗口

同时运行此代码:

#include <stdio.h>

int main()
{
    printf("Name\n");
    printf("Address Line 1\n");
    printf("Address Line 2");
}

在 Windows 上的 PowerShell 中正确打印代码。

在此处输入图片描述

答案1

对于 Cygwin 来说,有一个显然是一种竞争条件它输出构成行主体的字符,然后输出行尾(CRLF),另一个进程能够介入,这样您实际上就得到了body1 body2 CRLF CRLF(为清楚起见添加了间距)。

标准 C 禁止将标准输出完全缓冲到“交互式设备”(即多于一行),但允许缓冲较少的内容,而且无论如何,操作系统(C 正式称之为“主机环境”)如何处理来自多个进程的输出一旦“传输”给它就完全超出了 C 的范围 — — 如果我没记错的话,在这种情况下甚至超出了 POSIX 的范围 — — 无论如何,Cygwin 都不能完全满足 POSIX。

答案2

您却在 Windows 上使用 Unix 换行符 ( \n),而它应该是\r\n

差异很好这里解释

有三种不同类型的换行符,它们最初都是各大操作系统所独有的:Windows/DOS、Macintosh 和 Unix。使用 Mac 换行符的文档在 Windows 系统上看起来很糟糕,而使用 Windows 换行符的文档在 Unix 上也无法正确解释。造成这种情况的原因在于换行符的实际创建方式。默认情况下,Mac 使用单个回车符 ( <CR>),表示为\r。而 Unix 使用单个换行符 ( <LF>),\n。Windows 更进一步,同时使用两者,创建 () 组合,\r\n

要亲自测试,只需更改以下几行:

printf("Hello World (pid:%d)\n", (int) getpid());
fprintf(stderr, "fork failed\n");
printf("Hello I am child (pid:%d)\n", (int) getpid());
printf("Hello, I am parent of %d (pid:%d)\n",
            rc, (int) getpid());

对此:

printf("Hello World (pid:%d)\r\n", (int) getpid());
fprintf(stderr, "fork failed\r\n");
printf("Hello I am child (pid:%d)\r\n", (int) getpid());
printf("Hello, I am parent of %d (pid:%d)\r\n",
            rc, (int) getpid());

如果希望换行符在跨平台上保持一致,我建议只需根据 OS/shell 版本在代码中应用一个常量即可,该常量将分配正确的换行符,然后将其分配给\n代码中的所有位置。

相关内容