#c #printf
#c #printf
Вопрос:
#include<stdio.h>
#include <unistd.h>
int main(){
while(1)
{
fprintf(stdout,"hello-out");
fprintf(stderr,"hello-err");
sleep(1);
}
return 0;
}
При компиляции этой программы в gcc и при ее выполнении выводится только hello-err, а не hello-out.Почему это так?Может кто-нибудь, пожалуйста, объяснить причину этого?
Комментарии:
1. Где вы смотрели свой печатный текст? Первая
printf
выполняет печать вstdout
, а вторая вstderr
. В вашем случае это может относиться к разным потокам вывода2. @JimBuck-Я работаю над Fedora Linux.
3. @Nekto-Я думаю, что оба вывода stdout и stderr направляются на терминал. Потому что я могу видеть hello-err в терминале.
Ответ №1:
Если вы добавите 'n'
в свое сообщение, это будет (или должно быть), т.е. "hello-outn"
.
Причина в том, что stdout
она буферизуется для большей эффективности, тогда как stderr
не буферизует свои выходные данные и больше подходит для сообщений об ошибках и всего, что необходимо напечатать немедленно.
stdout
обычно будет сброшен, когда:
- Необходимо напечатать новую строку (
n
) - Вы читаете из
stdin
fflush()
Вызывается в ней
РЕДАКТИРОВАТЬ: Еще одна вещь, которую я хотел добавить до того, как мой компьютер разбился … дважды…было ли это также можно использовать setbuf(stdout, NULL);
для отключения буферизации stdout
. Я делал это раньше, когда мне приходилось использовать write()
(Unix) и я не хотел, чтобы мой вывод был буферизован.
Комментарии:
1. @bornfree: не беспокойтесь, надеюсь, я все хорошо объяснил.
Ответ №2:
Она не всегда выводит выходные данные в стандартный вывод, потому что по дизайну стандартный вывод является буферизованным, а стандартный вывод небуферизован. В общем случае для буферизованного выходного потока поток не сбрасывается до тех пор, пока система не станет «свободной» для этого. Таким образом, данные могут продолжать буферизоваться в течение длительного времени, прежде чем они будут сброшены. Если вы хотите принудительно очистить буфер, вы можете сделать это вручную, используя fflush
#include<stdio.h>
#include <unistd.h>
int main(){
while(1)
{
fprintf(stdout,"hello-out");
fflush(stdout); /* force flush */
fprintf(stderr,"hello-err");
sleep(1);
}
return 0;
}
Обновление: стандартный вывод буферизуется при подключении к терминалу и просто буферизуется в противном случае (например, перенаправление или канал)
Ответ №3:
Вы забыли новые строки (отмечено n
) в ваших строках. Или вам нужно вызвать fflush(NULL);
или, по крайней мере, fflush(stdout);
перед sleep(1);
И fprintf(stdout, ...)
совпадает с printf(...)
Вам нужно вывести новые строки или вызвать fflush
, потому что (по крайней мере, в Linux) stdout
буфер файла буферизован по строкам. Это означает, что библиотека C буферизует данные и действительно выведет их (используя системный вызов write
Linux), когда буфер будет достаточно заполнен, или когда вы очистите его либо новой строкой, либо вызовом fflush
. Буферизация необходима, потому что системные вызовы являются дорогостоящими (вызов write
для каждого выводимого байта действительно слишком медленный). Прочитайте также справочную страницу setbuf
Комментарии:
1. Не могли бы вы пояснить, пожалуйста, почему это требуется? Я хочу понять причину, стоящую за этим.
2. Ответ AusCBloke объясняет это.
3. как уже отвечали другие, потому что она буферизована для сокращения операций ввода-вывода. вызов fflush() принудительно очистит буфер.