Это потому, что printf
к стандартному выводу поток буферизован, но write
к стандартному выводу дескриптор файла нет.
Это означает поведениеможет меняться в зависимости от типа буферизации.В C стандартным выходом является строка в буфере, если его можно определить как подключенное к интерактивному устройству.В противном случае он полностью буферизирован (см. здесь для трактата о том, почему это так).
Строковая буферизация означает, что она будет сброшена в дескриптор файла, когда увидит новую строку,Полностью буферизованный означает, что он будет сбрасываться только при заполнении буфера (например, данных 4K), или когда поток закрыт (или когда вы fflush
).
Когда вы запускаете его в интерактивном режиме, сброспроисходит до write
, потому что printf
встречается с \n
и автоматически сбрасывается.
Однако, когда вы запускаете его иначе (например, перенаправляя вывод в файл или в онлайн-компилятор / исполнитель, где онвероятно, сделал бы то же самое, чтобы захватить данные для представления), сброс происходит после write
(потому что printf
не сбрасывает после каждой строки).
На самом деле,вам не нужны все эти каналы, чтобы увидеть это в действии, согласно следующей программе:
#include <stdio.h>
#include <unistd.h>
int main (void) {
printf ("Hello\n");
write (1, "Goodbye\n", 8);
return 0;
}
Когда я выполняю myprog ; echo === ; myprog >myprog.out ; cat myprog.out
, я получаю:
Hello
Goodbye
===
Goodbye
Hello
и вы можете увидеть разницу между разными типами буферизации.
Если вы хотите буферизацию строки независимо от перенаправления, вы можете попробовать:
setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
на ранней стадии вашей программы - этореализация деоштрафовано, поддерживает ли реализация это, так что это может не иметь никакого эффекта, но я не видел многих, где это не работает.