#c #glibc #stdio
#c #glibc #стандартный формат
Вопрос:
Кажется, что когда я запускаю следующий код:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv)
{
int i=0;
setvbuf(stdout, NULL, _IOLBF,0);
while (1)
printf("%d ",i );
return 0;
}
он печатает порциями по 1024 символа, независимо от размера, который я определяю для setvbuf().
Вопрос в том, влияет ли как-то в этом случае размер и откуда берется определение для 1024 символов.
Ответ №1:
Я не знаю, как вы определили, 1024
но это, вероятно BUFSIZ
. BUFSIZ
определяется в stdio.h
.
Если buf равно нулю, то библиотека stdio автоматически выделяет буфер для использования с потоком (если мы не выбираем небуферизованный ввод-вывод).
Редактировать
Вот что glibc
говорит:
Макрос: int BUFSIZ Значение этого макроса является целочисленным постоянным выражением, которое удобно использовать в качестве аргумента размера для setvbuf. Это значение гарантированно должно быть не менее 256.
Значение BUFSIZ выбирается в каждой системе таким образом, чтобы сделать потоковый ввод-вывод эффективным. Поэтому хорошей идеей будет использовать BUFSIZ в качестве размера буфера при вызове setvbuf.
ПРАВКА 2
@larsmans прав. Я посмотрел, как setvbuf
это реализовано, и он игнорирует вызов при запросе буферизации строки и представлении буфера с НУЛЕВЫМ значением. Теперь stdout
это не обычный файл, он прикреплен к терминалу. Итак, переходим к pixelbeat
- Размер буфера напрямую влияет только на режим буферизации
- Размер по умолчанию, как и в ядре, основан на размере страницы (4096 байт в моей системе)
- если stdin / stdout подключены к терминалу, то размер по умолчанию = 1024;
в противном случае размер = 4096
Комментарии:
1. Маловероятно; в моей системе Linux / glibc
BUFSIZ == 8192
.2. @larsmans У меня тоже; но я только что запустил его в VS 2008 и там
BUFSIZ == 512
. Кроме того, я все еще не знаю, так ли это на самом деле1024
.
Ответ №2:
В соответствии с (черновиком) Стандарт C,
Если
buf
указатель не равен нулю, массив, на который он указывает, может использоваться вместо буфера, выделенногоsetvbuf
функцией, а аргументsize
указывает размер массива; в противном случае,size
может определять размер буфера, выделенногоsetvbuf
функцией. [Выделено мной.]
Итак, предполагая, что вы измерили правильно, похоже, что Glibc может делать все, что ему заблагорассудится, когда buf
равно нулю, и это дает вам буфер размером 1 КБ. Поскольку вы никогда не вводите новую строку, буферизация строк не влияет, и поведение аналогично полной буферизации.
Ответ №3:
Размер, вероятно, не оказывает большого влияния на указатель буфера с нулевым значением.
Однако вы по-прежнему запрашиваете буферизованный вывод с помощью _IOLBF
Try _IONBF
вместо этого.