2010-09-24 24 views
0

E/S Voici mon programme:Comment fonctionne ce programme simple, lié

#include <stdio.h> 
int main(int argc, char* argv[]) { 
    char buf[1024] = {0}; 
    setvbuf(stdout, buf, _IOFBF, 1024); 
    printf("error\n"); 
    printf("%s\n", buf); 
} 

Et voici la sortie:

error 
error 

Exited: ExitFailure 7 

Pourquoi les deux lignes 3 et ligne 4 lignes vides? Le caractère '\n' ne purge-t-il pas le tampon de sortie et est rejeté plus tard?

+1

À l'avenir, veuillez simplement copier et coller votre code dans votre question plutôt que de capturer votre éditeur à l'écran. De cette façon, si quelqu'un veut essayer de compiler votre programme, il n'aura pas à retaper tout votre code. – meagar

+0

Vous avez raison, je promets de ne pas le faire – Tracy

Répondre

3

Vous invoquez certainement un comportement indéfini (ou au moins non spécifié). Vous déclarez un tampon, puis transmettez-le via setvbuf à stdout. À partir de ce moment-là, le tampon est détenu par stdout et non plus vous. Cela signifie que vous ne pouvez plus y accéder. Mais c'est exactement ce que vous faites.

Je ne peux pas le prouver à partir du libellé de la norme, mais il y a certainement une combinaison de paragraphes qui mène à ma conclusion.

Mise à jour: ISO C99 dit dans 7.19.5.6p2 sur la fonction setvbuf: Le contenu du tableau à tout moment sont indéterminées. Donc, ce que vous voyez est juste une coïncidence. Vous pouvez également voir autre chose, il n'y a aucune garantie de l'ISO C99 seul.

Mise à jour 2: Étant donné que le contenu du tableau est indéterminé, ils peuvent également tous être des caractères non nuls. Et dans ce cas, buf ne contient plus une chaîne plus. Par conséquent, vous appelez clairement undefined behavior.

1

Votre code de sortie me dit que printf a imprimé 7 caractères - je suppose 5 en "erreur" et deux autres "\ n" s. La ligne 4 pourrait-elle être ajoutée par votre système d'exploitation - par les impressions "Exited"?

3

L'appel:

printf("error\n"); 

copies "erreur \ n" dans le tampon de sortie standard, qui est maintenant buf, puis débusque que l'écran.

L'appel:

printf("%s\n", buf); 

ensuite des copies buf, que l'appel printf précédent avait réglé sur "erreur \ n" à BUF encore et ajoute un autre \ n à, donc buf est maintenant « erreur \ n \ n ", c'est de là que viennent vos 2 lignes vides.

Ensuite, puisque vous n'avez pas return 0 à la fin de main la valeur de retour du dernier appel printf a été interprétée comme la valeur de retour de principal. Comme "errno \ n \ n" est long de 7 caractères, printf aurait retourné 7, et puisque ce n'est pas 0, cela a été interprété comme un échec par celui qui a exécuté le programme.

1

Le problème avec votre code est que vous utilisez un tampon pour des tâches complètement distinctes - en l'utilisant comme tampon de sortie intermédiaire et en utilisant son contenu pour l'imprimer en sortie.

Qu'est-ce que votre programme fait:

  1. Alloue un `buf` tampon et` écrit '\ `0'` à buf [0]` ce qui en fait une chaîne vide
  2. Définit le tampon d'E/S `buf`
  3. Ecrit" erreur \ n "sur la sortie standard - cela signifie d'abord` buf`, puis probablement à l'écran.
  4. `buf` contient maintenant la chaîne" error \ n "
  5. Vous imprimez le contenu de` buf` - ce qui signifie que `buf` est copié sur lui-même, ce qui pourrait causer l'échec de sortie bizarre plus tard. Cela imprimera la deuxième ligne contenant l'erreur.

Les caractères supplémentaires sont probablement ajoutés par le système. Méfiez-vous que \ n ne vide pas le tampon de sortie, vous devez appeler la fonction de rinçage pour vous assurer qu'un vidage a eu lieu.

+0

Salut, que voulez-vous dire par cela \ n ne vider le tampon de sortie? Voulez-vous dire que le contenu de buf reste inchangé ou ne sont pas vidés à l'écran. Merci – Tracy

+0

En fait, c'est les deux - \ n ne force pas le texte à apparaître sur l'écran. Ne remplissez que le tampon entier ou le flush d'appel le fait apparaître sur l'écran. Le contenu de buf dépend de l'implémentation, mais la plupart du temps, buf n'est pas mis à zéro quand I/O est vidé, l'écriture suivante après un flush commencera simplement à écrire depuis le début de buf. –

+0

merci, alors qu'est-ce que j'utilise cout << endl? Est-ce garanti de vider à l'écran? – Tracy