我写了下面的程序。
void main()
{
int *piarrNumber1 = (int *) calloc(1, sizeof(int));
int iUserInput = 0;
scanf("%d", &iUserInput);
piarrNumber1[(sizeof piarrNumber1 / sizeof(int)) - 1] = iUserInput;
printf("\n%d\n", piarrNumber1[0]);
}
Run Code Online (Sandbox Code Playgroud)
我从键盘输入“3”,然后输入 TAB。什么都没发生。然后,我按 Enter 键。我打印出“3”,程序结束。
如果“TAB”[水平制表符]和“Enter”[换行符]都是空白字符,为什么它们的行为不同?
详细信息是特定于操作系统的(因为标准 C99 不了解终端)。
我假设你使用的是Linux。
首先,stdio(3)正在缓冲标准输入流和大多数其他FILE*
流。您可以尝试使用setvbuf(3)更改它,但这只会影响输出缓冲。
更重要的是,当stdin(实际上是它使用的文件描述符,即STDIN_FILENO
通常是 的值fileno(stdin)
)是终端时(请参阅isatty(3)进行测试),Linux 内核通常对终端进行行缓冲(所谓的熟) mode ) - 至少要处理backspace密钥。您可以通过将 tty 切换到原始模式来更改它(就像每个编辑器喜欢emacs
或vim
或nano
会做的那样)。看到这个问题。但您应该在程序退出之前重置煮熟模式。
因此,在正常情况下,会发生两个级别的缓冲:在内核中用于终端的线路规则,以及在libc
用于缓冲stdin
在实践中,如果您想要复杂的终端输入,请使用一些库,例如ncurses或readline(不要只使用 termios)
另请参见stty(1) & termios(3) & tty_ioctl(4);了解ANSI 转义码信息。
请注意,此行在两个级别(libc
和内核)进行缓冲是特定于 ttys 的。什么时候stdin
是管道(7)(如echo foo | yourprogram
)或文件(如yourprogram < yourinputfile.txt
)时,情况有所不同。
简而言之,tty 很难理解,因为它们模仿 20 世纪 50 年代至 1970 年代复杂而神秘的硬件设备。