Cygwin 上令人困惑的代码流顺序

Confusing sequence of Code flow on Cygwin

在 C 中有这个非常简单的程序(在 Cygwin 上用 gcc 构建)::

// This program is a tutorial to Stack-based overflow, that's why "gets"
    #include <stdio.h>

    void test()
    {
        char buff[4];
        printf("Some input: ");
        gets(buff);
        puts(buff);
    }

    int main(int argc, char** argv)
    {
        test();
        return 0;
    }

现在当我 运行 在 Windows 控制台上执行此操作时,printf 首先执行并等待输入::

但是当我在 Cygwin 终端下 运行 相同的 exe 时,它​​等待输入然后 printf 执行::

为什么会这样?

EDIT:: \n 附加到 printf 语句中的字符串,行为保持不变::

因此,经过一些阅读和研究,我得出了针对此行为的最终理论。

简答:: stdout 被缓冲,所以做

void test()
{
    char buff[4];
    setvbuf(stdout, NULL, _IONBF, 0); // <--- setting stdout to _IONBF
    printf("Some input: ");
    gets(buff);
    puts(buff);
}

在向控制台打印任何内容之前,或者,

void test()
    {
        char buff[4];
        printf("Some input: ");
        fflush(stdout); // <--- force the stdout to flush
        gets(buff);
        puts(buff);
    }

printf语句后问题解决。

长答案::

当我 运行 与 Bash.exe 相同的 exe 时,stdout 没有被缓冲::

mintty.exe 相同的 exe,stdout 被缓冲::

现在的问题是,

  • 为什么 stdout 在一个中没有缓冲而在另一个中缓冲?

As you can see the tty output on both, bash shows as console session /dev/cons0, whereas the mintty shows as pseudo-terminal session /dev/pty0.

所以,

  • 它如何回答无缓冲和缓冲标准输出的问题?

My browsing re-re-and-re searches landed me here, stating, If I type tty in the respective Cygwin windows, I see that mintty and xterm are both pseudo-terminals whereas bash is a console session - I believe procServ uses forkpty(). So I think it boils down to Windows treating a Cygwin pty as non-interactive and thus buffering both stdout and stderr.

我不确定,这有多精确,但是是的,这似乎是对这种行为的实用且最好的解释。

根据 Section 7.9.13/7 of c99 指出:

At program start-up, three text streams are predefined and need not be opened explicitly - standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output).

As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

*粗体强调是我的