¿Por qué printf() no imprime nada antes de sleep()?

4 minutos de lectura

Estoy aprendiendo C con el libro de Kernighan y Ritchie; Estoy en los conceptos básicos del cuarto capítulo (“Funciones y estructura del programa”). El otro día me entró curiosidad por el sleep() función, así que traté de usarlo así:

#include <stdio.h>
#include <unistd.h>

int main(void)
{
  printf(" I like cows.");
  sleep(5);
  return 0;
}

El problema es la salida del programa, parece que hace lo sleep() primero y luego el printf(), en otras palabras, espera cinco segundos y luego imprime la cadena. Así que pensé, tal vez el programa llega a sleep() tan rápido que no deja printf() hacer su trabajo como quiero, es decir, imprimir la cadena y luego dormir.

¿Cómo puedo mostrar la cadena y luego poner el programa a dormir? El compilador es GCC 3.3.5 (propolice) en OpenBSD 4.3.

avatar de usuario
roberto apuesta

printf() escribe a stdout (el flujo de salida predeterminado) que generalmente tiene un búfer de línea. El búfer no se descarga en el momento sleep se llama para que no se muestre nada, cuando el programa sale, todas las secuencias se vacían automáticamente, por lo que se imprime justo antes de salir. Imprimir una nueva línea generalmente hará que la secuencia se vacíe, alternativamente, puede usar el fflush función:

int main(void)
{
  printf(" I like cows.\n");
  sleep(5);
  return 0;
}

o:

int main(void)
{
  printf(" I like cows.");
  fflush(stdout);
  sleep(5);
  return 0;
}

Si está imprimiendo en una secuencia que no tiene un búfer de línea, como puede ser el caso si stdout es redirigido o está escribiendo en un archivo, simplemente imprimir una nueva línea probablemente no funcione. En tales casos, debe utilizar fflush si desea que los datos se escriban inmediatamente.

  • La razón por la que agregar \n a la cadena funciona es que printf en la consola tiene un búfer de línea. Sin embargo, si lo redirige a un archivo, puede que no sea suficiente porque utiliza un esquema de almacenamiento en búfer diferente.

    –Paul Tomblin

    3 de diciembre de 2008 a las 18:48

  • Entonces, una pregunta interesante es, ¿cómo puede saber qué modo de almacenamiento en búfer está usando su puntero de archivo actual?

    -Vinko Vrsalovic

    3 de diciembre de 2008 a las 18:54

  • @Paul, correcto, por eso dije que lo hará generalmente hacer que la corriente se enjuague, pero seguiré adelante y lo aclararé.

    – Roberto Gamble

    3 de diciembre de 2008 a las 18:55

  • @Vinko, no hay una función estándar que le diga cuál es el modo de almacenamiento en búfer para una transmisión, pero muchas implementaciones tienen sus propias funciones (glibc tiene __flbf y __fbufsize, por ejemplo).

    – Roberto Gamble

    3 de diciembre de 2008 a las 19:14

  • @RobertGamble, bueno, había aprendido eso fflush (stdout) es comportamiento indefinido.

    –Ashish Ahuja

    9 de febrero de 2016 a las 14:32

avatar de usuario
pablo tomblin

Su problema es que printf (y cualquier otra cosa que use la biblioteca stdio para escribir en stdout (salida estándar)) se almacena en el búfer: la línea se almacena en el búfer si va a la consola y el tamaño se almacena en el búfer si va a un archivo. si haces un fflush(stdout); después de la printf, hará lo que quieras. Puede intentar simplemente agregar una nueva línea (‘\ n’) a su cadena, y eso haría lo correcto siempre que no redirija la salida estándar a un archivo.

No estoy 100% seguro, pero creo stderr no está almacenado en el búfer, lo que puede causar confusión porque es posible que vea el resultado que realizó en stderr antes de la salida que hizo previamente a stdout.

  • printf no está almacenado en búfer, la secuencia en la que está escribiendo sí lo está.

    – Roberto Gamble

    3 de diciembre de 2008 a las 18:47

  • stderr generalmente no tiene búfer (aunque puede tener búfer de línea).

    – Roberto Gamble

    3 de diciembre de 2008 a las 19:04

  • ¿Por qué la nueva línea (‘\ n’) hace el trabajo?

    – gonidelis

    9 de abril de 2019 a las 22:24

  • @johngonidelis porque, como dije antes, tiene un búfer de línea. Cuando ve el final de una línea, vacía el búfer.

    –Paul Tomblin

    10 de abril de 2019 a las 12:50

avatar de usuario
Vinko Vrsalovic

El almacenamiento en búfer significa que toda la salida se almacena en un lugar (llamado búfer) y se emite después de que una cierta cantidad de datos está presente en él. Esto se hace por razones de eficiencia.

Algunas implementaciones (¿la mayoría?) limpian el búfer después de una nueva línea al escribir en la consola, por lo que también puede intentar

printf(" I like cows.\n");

en lugar de la llamada a fflush()

Implementé el encuentro de tiempo de la siguiente manera;

for (int i = 1; i <= 60; i++) {
    printf("%02d", i);
    fflush(stdout);
    sleep(1);
    printf("\b\b");
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad