почему эта программа на c не печатает первую инструкцию printf?

#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() принудительно очистит буфер.