Flujo de salida estándar en C

Jinku Hu 12 octubre 2023
  1. Utilice la función fflush para descargar el flujo de salida stdout en C
  2. Demuestre el comportamiento fflush utilizando la función printf en C
Flujo de salida estándar en C

Este artículo demostrará varios métodos sobre cómo vaciar el flujo de salida stdout en C.

Utilice la función fflush para descargar el flujo de salida stdout en C

La biblioteca estándar de C proporciona una biblioteca de E/S, stdio, que esencialmente representa una versión almacenada en búfer de las operaciones de E/S realizadas en el espacio de usuario, mejorando así el rendimiento para casos de uso comunes. Generalmente, el acceso a archivos y la realización de operaciones en ellos es proporcionado por los servicios del sistema operativo; por tanto, el usuario eventualmente necesita una llamada al sistema, para abrir un archivo. Una invocación frecuente de llamadas al sistema hace que el programa sea más lento, ya que implica acceder a las estructuras de datos del núcleo del sistema operativo y transferir el control de un lado a otro. Como resultado, hay búferes mantenidos por la biblioteca C para manejar las operaciones de entrada/salida cuando se usan las llamadas a la función stdio.

Si el usuario necesita forzar la escritura en los búferes del kernel, necesita vaciar el flujo proporcionado por la función fflush. fflush toma un único argumento del puntero FILE al flujo dado. Tenga en cuenta que fflush fuerza la función de escritura para los flujos de salida mientras descarta los datos almacenados en búfer para los flujos de entrada (con archivos buscables). Si el argumento es NULL, elimina todos los flujos de salida abiertos.

Sin embargo, tenga en cuenta que fflush no garantiza que los datos escritos se almacenen físicamente, ya que eso requiere que los búferes del kernel se descarguen (lo que se puede lograr usando la llamada fsync que se ve aquí).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  char *username;
  size_t len;
  int lnmax = 256;

  username = malloc(lnmax);
  if (username == NULL) perror("malloc");

  printf("Username: ");
  fflush(stdout);
  if (fgets(username, lnmax, stdin) == NULL) exit(EXIT_FAILURE);

  printf("Your username is set to - %s", username);

  exit(EXIT_SUCCESS);
}

Producción :

Username: tmp
Your username is set to - tmp

Demuestre el comportamiento fflush utilizando la función printf en C

Tenga en cuenta que algunas transmisiones (por ejemplo, stderr) no se almacenan en búfer. Por el contrario, la función printf que escribe implícitamente en el flujo stdout está almacenada en búfer, y si ejecutamos el bucle infinito imprimiendo un solo carácter en cada iteración debajo del capó, no enviará el contenido al flujo hasta que el búfer interno sea lleno. Por lo tanto, el siguiente ejemplo de código da como resultado la impresión en ráfaga de los caracteres de viñeta. Observe que llamamos a la función usleep cada iteración para ralentizar la ejecución del ojo humano para que sea claramente observable.

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

int main(int argc, char *argv[]) {
  while (1) {
    printf(".");
    usleep(1e3);
  }

  exit(EXIT_SUCCESS);
}

Alternativamente, si sustituimos la llamada printf con fprintf, que imprime en el flujo stderr, producirá el comportamiento de impresión iterativo char por char cada segundo. Una vez más, el retraso de 1 segundo en cada iteración se coloca solo para garantizar una buena demostración.

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

int main(int argc, char *argv[]) {
  while (1) {
    fprintf(stderr, ".");
    sleep(1);
  }

  exit(EXIT_SUCCESS);
}

Finalmente, si necesitáramos imitar el mismo comportamiento en la secuencia stdout como se ve en el código de ejemplo anterior, podemos agregar la llamada fflush después de la función printf. Esto obligará a que los búferes de la biblioteca C se escriban en búferes del kernel en cada iteración, lo que dará como resultado un comportamiento similar.

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

int main(int argc, char *argv[]) {
  while (1) {
    printf(".");
    fflush(stdout);
    sleep(1);
  }

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - C IO