【问题标题】:Why are stdin and stdout seemingly interchangeable?为什么 stdin 和 stdout 看起来可以互换?
【发布时间】:2025-12-09 23:20:03
【问题描述】:

我知道标准输入和标准输出(至少在 UNIX 用语中)是流缓冲区,标准输出用于从程序输出到控制台(或然后由外壳等通过管道传输),标准输入是用于程序的标准输入..

那么为什么至少在 macOS 上它们可以互换使用(stdout 作为标准输入,反之亦然?

例子:

  1. 如果你运行cat /dev/stdin 然后输入一些东西,它会回显。以cat /dev/stdout 的身份运行命令执行相同的操作。

  2. 同样,echo "Hey There" > /dev/stdoutecho "Hey There" > /dev/stdin 都将“Hey There”输出回终端。

  3. 它也适用于 C++:

示例:

#include <iostream>
#include <string>
#include <fstream>

int main(int argc, const char * argv[]) {
    std::string echoString;
    std::fstream stdoutFile;
    stdoutFile.open("/dev/stdout");
    stdoutFile << "Hey look! I'm using stdout properly!\nNow You trying using it wrongly: " << std::endl;
    stdoutFile >> echoString;
    stdoutFile << "You Typed: " << echoString << std::endl;
}

出现提示时,键入一个单词,然后按 EOF (Ctrl+D) 即可正常工作。

【问题讨论】:

  • 请注意,/dev/stdin/dev/stdout 可以互换这一事实意味着 stdinstdout 可以互换。特别是,如果您使用&gt; /dev/stdin 启动进程,则无法从进程的标准输出流中读取。
  • @Brian 你是什么意思?这似乎有效:pastebin.com/Su3yuJax
  • 这和我说的不一样。 std::fstream 默认以读/写模式打开。如果您在终端上执行&gt; foo,它将以只写模式打开foo,并且文件描述符将无法用于读取。
  • @Brian 对,我现在明白了。谢谢!

标签: c++ macos shell unix stdout


【解决方案1】:

正如您所说,它们只是流缓冲区。它们并没有强制执行特定的使用模式 - 只是约定。流缓冲区 stdin、stdout 和 stderr 都是为了方便编程而提供的。

【讨论】:

    【解决方案2】:

    因为,通常情况下,当从交互式终端调用程序时,在没有重定向的情况下,标准输入和标准输出都连接到同一个终端设备,例如/dev/tty(实际设备名称因操作而异)系统)。

    终端设备是一个读/写设备。从终端设备读取读取终端输入。写入终端设备会在终端上生成输出。

    您仍然有离散的文件描述符,0 和 1,但它们连接到同一个设备。

    将其视为单个双向管道,即duped 到文件描述符 0 和 1。

    Linux 的行为方式相同(您可以echo Foo &gt;/dev/stdin 并查看输出):

    $ ls -al /proc/self/fd/[01]
    lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/0 -> /dev/pts/1
    lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/1 -> /dev/pts/1
    

    因此,对于这个进程,文件描述符 0 和 1 连接到同一伪终端设备 /dev/pts/1。无论您是从文件描述符 0 还是文件描述符 1 读取,最终都会从相同的底层 /dev 设备读取,因此使用哪个实际文件描述符没有区别。

    当然,这取决于操作系统。其他基于 POSIX 的操作系统可能以其他方式实现其标准输入和输出,您实际上无法写入标准输入并从标准输出中读取。

    【讨论】:

      最近更新 更多