【发布时间】:2015-12-12 16:04:23
【问题描述】:
当我在规范模式下使用这段代码时:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
static struct termios newt;
static struct termios oldt;
static void kb_fini(void)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
}
void kb_init(void)
{
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= (tcflag_t)~(ICANON | ECHO | ISIG);
newt.c_cc[VMIN] = 1;
newt.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
atexit(kb_fini);
}
int main(void)
{
int c;
kb_init();
printf("Press q ");
c = getchar();
if (c == 'q') {
printf("q was pressed\n");
}
return 0;
}
在按下q之前,我可以在控制台中阅读“Press q”
切换到read:
int main(void)
{
char c;
kb_init();
printf("Press q ");
read(STDIN_FILENO, &c, 1);
if (c == 'q') {
printf("q was pressed\n");
}
return 0;
}
在按下q 之前不显示“Press q”。
这是为什么?
【问题讨论】:
-
标准 I/O 包知道发生了什么并协调事情,以便在调用读取操作之前刷新标准输出的挂起输出。
read()系统调用不知道也不关心 STDOUT_FILENO 发生了什么。如果您要混合使用这两种模式,请确保在使用read()之前先fflush(stdout);或fflush(0);。 -
我敢打赌,标准输出默认是行缓冲的。在
printf()之后尝试fflush(stdout) -
@JonathanLeffler,有道理,谢谢!,混合这两种模式是否有明确定义的行为?
-
@vlp,谢谢,是的,我知道
fflush解决了这个问题,我的问题是为什么read和getchar之间的行为不同 -
"混合这两种模式是否有明确定义的行为?"我不会打赌。即使是这样,它也是糟糕的设计风格和维护问题,例如如果您稍后阅读代码并尝试了解发生了什么。真的有充分的理由不坚持一个吗?