Pourquoi printf
n'est-il pas vide après l'appel, sauf si un retour à la ligne est dans la chaîne de format? Est-ce un comportement POSIX? Comment pourrais-je avoir printf immédiatement à chaque fois?
Réponses
Trop de publicités?L' stdout
flux est mis en mémoire tampon, de sorte affichera uniquement ce qui est dans le buffer après avoir atteint un saut de ligne (ou quand c'est dit). Vous avez un peu d'options pour imprimer immédiatement:
Imprimer vers stderr l'aide d' fprintf
:
fprintf(stderr, "I will be printed immediately");
Flush stdout chaque fois que vous en avez besoin à l'aide d' fflush
:
printf("Buffered, will be flushed");
fflush(stdout); // Will now print everything in the stdout buffer
Edit: De Andy Ross commentaire ci-dessous, vous pouvez également désactiver la mise en mémoire tampon sur la sortie standard en utilisant setbuf
:
setbuf(stdout, NULL);
Non, il n'est pas POSIX comportement, c'est de l'ISO comportement (bon, c' est POSIX comportement, mais seulement dans la mesure où ils sont conformes à la norme ISO).
La sortie Standard est la ligne de tampon si elle peut être détectée à se référer à un dispositif interactif, sinon il est entièrement mis en mémoire tampon. Il y a des situations où l' printf
ne pas rincer, même s'il fait un retour à la ligne pour envoyer, tels que:
myprog >myfile.txt
Cela a un sens pour l'efficacité car, si vous êtes en interaction avec un utilisateur, ils veulent probablement pour voir chaque ligne. Si vous êtes à envoyer la sortie vers un fichier, il est plus que probable qu'il n'y a pas un utilisateur à l'autre bout (mais pas impossible, ils pourraient être de résidus de la file). Maintenant, vous pourriez argumenter que l'utilisateur veut les voir chaque personnage, mais il y a deux problèmes avec ça.
La première est qu'il n'est pas très efficace. La deuxième est que le C ANSI mandat avait pour principal objet de codifier existant comportement, plutôt que d'inventer de nouveaux comportements, et ceux de la conception des décisions ont été prises bien avant ANSI a commencé le processus. Même ISO de nos jours de marches très attentivement lors de la modification des règles existantes dans les normes.
Quant à la façon de traiter avec cela, si vous fflush (stdout)
après chaque sortie que vous souhaitez voir immédiatement, qui permettra de résoudre le problème.
Alternativement, vous pouvez utiliser setvbuf
avant d'opérer sur stdout
, pour le mettre en mémoire sans tampon et vous ne devez pas vous inquiéter au sujet de l'ajout de tous ces fflush
des lignes de code:
setvbuf (stdout, NULL, _IONBF, BUFSIZ);
Il suffit de garder à l'esprit que peut affecter les performances tout à fait un peu si vous êtes d'envoyer la sortie vers un fichier. Aussi garder à l'esprit que le soutien à cette mise en œuvre est définie, non garantie par la norme.
La norme ISO C99 section 7.19.3/3
est le:
Lorsqu'un flux est sans tampon, les personnages sont destinés à apparaître à partir de la source ou de la destination dès que possible. Sinon, les caractères peuvent être accumulés et transmis vers ou à partir de l'hôte de l'environnement comme un bloc.
Lorsqu'un flux est entièrement mis en mémoire tampon, les personnages sont destinés à être transmis vers ou à partir de l'hôte de l'environnement comme un bloc lorsqu'un tampon est rempli.
Lorsqu'un flux est de la ligne de tampon, les personnages sont destinés à être transmis vers ou à partir de l'hôte de l'environnement comme un bloc lorsqu'un caractère de nouvelle ligne est rencontré.
En outre, les personnages sont destinés à être transmis comme un bloc à l'environnement d'accueil lorsqu'un tampon est rempli, lorsque la saisie est demandée sur un tampon de flux, ou lorsque la saisie est demandée sur une ligne de tampon de flux qui nécessite la transmission de caractères à partir de l'environnement d'accueil.
Le Support de ces caractéristiques est la mise en œuvre définies, et peut être affectée par l'
setbuf
etsetvbuf
fonctions.
C'est probablement comme ça à cause de l'efficacité et parce que si vous avez plusieurs programmes qui écrivent sur un seul TTY, vous n'obtenez pas de caractères sur une ligne entrelacée. Donc, si les programmes A et B sortent, vous aurez généralement:
program A output
program B output
program B output
program A output
program B output
Cela pue, mais c'est mieux que
proprogrgraam m AB ououtputputt
prproogrgram amB A ououtputtput
program B output
Notez qu'il n'est même pas garanti d'effectuer un vidage sur un retour à la ligne, vous devez donc vidanger explicitement si le rinçage est important pour vous.