stdout c99 buffered

¿La línea stdout está en búfer, no en búfer o indeterminada por defecto?



c99 buffered (1)

La sección 7.9.13/7 de c99 establece que:

Al inicio del programa, tres flujos de texto están predefinidos y no es necesario que se abran explícitamente: entrada estándar (para leer entrada convencional), salida estándar (para escribir salida convencional) y error estándar (para escribir salida de diagnóstico).

Como se abrió inicialmente, el flujo de error estándar no está completamente almacenado en búfer; la entrada estándar y las secuencias de salida estándar están completamente almacenadas en búfer si, y solo si se puede determinar que la secuencia no se refiere a un dispositivo interactivo.

Así que eso tiene sentido. Si está empujando su salida estándar a un archivo, quiere que esté completamente almacenado para la eficiencia.

Pero no puedo encontrar ninguna mención en el estándar en cuanto a si la salida tiene búfer de línea o no está en búfer cuando no se puede determinar que el dispositivo no sea interactivo (es decir, la salida normal a un terminal).

La razón por la que pregunto fue un comentario a mi respuesta here que debería insertar un fflush(stdout); entre las dos afirmaciones:

printf ("Enter number> "); // fflush (stdout); needed ? if (fgets (buff, sizeof(buff), stdin) == NULL) { ... }

porque no estaba terminando el printf con una nueva linea. ¿Alguien puede aclarar esto?


El estándar C99 no especifica si los tres flujos estándar están sin almacenamiento o con búfer de línea: depende de la implementación. Todas las implementaciones de UNIX que conozco tienen un stdin búfer de línea. En Linux, stdout en línea con búfer y stderr sin búfer.

Que yo sepa, POSIX no impone restricciones adicionales. La página fflush de POSIX no se nota en la sección EJEMPLOS:

[...] La función fflush () se usa porque la salida estándar suele estar en búfer y es posible que la solicitud no se imprima inmediatamente en la salida o el terminal.

Así que la observación de que agrega fflush(stdout); es correcto.

Una alternativa podría ser hacer stdout sin búfer:

setbuf(stdout, NULL); /* or */ setvbuf(stdout, NULL, _IONBF, 0);

Pero como R. señala, solo puede hacer esto una vez, y debe ser antes de escribir en la salida estándar o realizar cualquier otra operación en él. (C99 7.19.5.5 2)

Acabo de leer un hilo reciente en comp.lang.c sobre la misma cosa. Una de las observaciones:

La convención de Unix es que stdin y stdout tienen stdout línea cuando están asociados con un terminal, y de otro modo están completamente en búfer (también conocido como bloque de búfer). stderr siempre está sin búfer.