Я начну с некоторых определений, а затем перейду к ответам на ваши вопросы.
Файл: это упорядоченная последовательность байтов. Это может быть файл на диске, поток байтов, сгенерированный программой (например, конвейером), сокет TCP/IP, поток байтов, полученных или отправленных на периферийное устройство (например, клавиатуру или дисплей) и т. д. Последние два являются интерактивными файлами. Файлы обычно являются основным средством, с помощью которого программа взаимодействует со своим окружением.
Поток: представление потока данных из одного места в другое, например, с диска в память, из памяти на диск, одной программы. к другому и т. д. Поток — это источник данных, в который данные можно вводить (записывать) или извлекать данные (читать). Таким образом, это интерфейс для записи данных или чтения данных из файла, который может быть любого типа, как указано выше. Прежде чем вы сможете выполнить какую-либо операцию с файлом, файл должен быть открыт. Открытие файла связывает его с потоком. Потоки представлены типом данных FILE
, определенным в заголовке stdio.h
. Объект FILE
(это структура) содержит всю внутреннюю информацию о состоянии подключения к связанному файлу, включая такие вещи, как индикатор позиции файла и информацию о буферизации. Объекты FILE
выделяются и управляются внутри функциями библиотеки ввода/вывода, и вам не следует пытаться создавать свои собственные объекты типа FILE
, библиотека делает это за нас. Программы должны иметь дело только с указателями на эти объекты (FILE *
), а не с самими объектами.
Буфер. Буфер — это блок памяти, который принадлежит потоку и используется для временного хранения данных потока. Когда над файлом происходит первая операция ввода/вывода, вызывается malloc
и получается буфер. Символы, которые записываются в поток, обычно накапливаются в буфере (перед передачей в файл фрагментами), а не появляются сразу после вывода прикладной программой. Точно так же потоки извлекают входные данные из хост-среды блоками, а не посимвольно. Это сделано для повышения эффективности, так как файловый и консольный ввод-вывод медленнее по сравнению с операциями с памятью.
Библиотека C
предоставляет три предопределенных текстовых потока (FILE *
), открытых и доступных для использования при запуске программы. Это stdin
(стандартный поток ввода, который является обычным источником ввода для программы), stdout
(стандартный поток вывода, который используется для нормального вывода программы) и stderr
(стандартный поток ошибок, который используется для сообщений об ошибках и диагностики, выдаваемой программой). Будут ли эти потоки буферизированы или небуферизованы, определяется реализацией и не требуется стандартом.
GCC
обеспечивает три типа буферизации: небуферизованная, блочная буферизация и буферизация строк. Небуферизованный означает, что символы появляются в целевом файле, как только они записываются (для выходного потока), или входные данные считываются из файла посимвольно, а не блоками (для входных потоков). Блочная буферизация означает, что символы сохраняются в буфере и записываются или считываются как блок. Буферизация строк означает, что символы сохраняются только до тех пор, пока новая строка не будет записана в буфер или прочитана из него.
stdin
и stdout
буферизуются блоками тогда и только тогда, когда можно определить, что они не относятся к интерактивному устройству, в противном случае они буферизуются строками (это верно для любого потока). stderr
по умолчанию всегда не буферизируется.
Стандартная библиотека предоставляет функции для изменения поведения потоков по умолчанию. Вы можете использовать fflush
, чтобы принудительно вывести данные из буфера выходного потока (fflush
не определено для входных потоков). Вы можете сделать поток небуферизованным, используя функцию setbuf
.
Теперь давайте перейдем к вашим вопросам.
Вопрос без пометки: Да, потому что stdout
обычно относится к терминалу с дисплеем, если у вас нет перенаправления вывода с использованием оператора >
.
Q1: Он ждет, потому что stdout
буферизуется новой строкой, когда он ссылается на терминал.
Q2: Символы буферизуются, ну, в буфере, выделенном для потока stdout
.
Q3: Поток печати: память --> stdout
буфер --> терминал дисплея. Существуют буферы ядра, которые также контролируются ОС, через которые данные проходят перед тем, как появиться на терминале.
Q4: stdout
относится к стандартному выходному потоку, который обычно является терминалом.
Наконец, вот пример кода для экспериментов, прежде чем я закончу свой ответ.
#include <stdio.h>
#include <limits.h>
int main(void) {
// setbuf(stdout, NULL); // make stdout unbuffered
printf("Hello, World!"); // no newline
// printf("Hello, World!"); // with a newline
// only for demonstrating that stdout is line buffered
for(size_t i = 0; i < UINT_MAX; i++)
; // null statement
printf("\n"); // flush the buffer
return 0;
}
person
ajay
schedule
27.02.2014
fflush(stdout)
приводит к сбросу. - person Nathan S.   schedule 27.02.2014