2009-03-18 7 views
1

Je sais que cout et printf ont un tampon aujourd'hui, et il est dit que le tampon est comme une pile et obtient la sortie de cout et printf de droite à gauche, puis les éteindre (à la console ou au fichier) de haut en bas. Comme cela,le tampon et la séquence de sortie de cout et printf

a = 1; b = 2; c = 3; 
cout<<a<<b<<c<<endl; 
buffer:|3|2|1|<- (take “<-” as a poniter) 

output:|3|2|<-  (output 1) 
     |3|<-  (output 2) 
     |<-   (output 3) 

J'écrire un code ci-dessous,

#include <iostream> 
using namespace std; 
int c = 6; 
int f() 
{ 
    c+=1; 
    return c; 
} 

int main() 
{ 
    int i = 0; 
    cout <<"i="<<i<<" i++="<<i++<<" i--="<<i--<<endl; 
    i = 0; 
    printf("i=%d i++=%d i--=%d\n" , i , i++ ,i--); 

    cout<<f()<<" "<<f()<<" "<<f()<<endl; 
    c = 6; 
    printf("%d %d %d\n" , f() , f() ,f()); 
    system("pause"); 
    return 0; 
} 

Sous VS2005, la sortie est

i=0 i++=-1 i--=0 
i=0 i++=-1 i--=0 
9 8 7 
9 8 7 

Sous g ++ ((GCC) 3.4.2 (MinGW-spéciale)), la sortie est,

i=0 i++=0 i--=1 
i=0 i++=-1 i--=0 
9 8 7 
9 8 7 

Il semble que le b uffer est comme une pile. Cependant, j'ai lu C++ Primer Plus aujourd'hui, et il est dit que le cout fonctionne de gauche à droite, chaque fois retourner un objet (cout), donc "C'est la fonctionnalité qui vous permet de concaténer la sortie en utilisant l'insertion". Mais la façon de gauche à droite ne peut pas expliquer cout < sortie 9 8 7 Maintenant, je suis confus au sujet du fonctionnement du tampon de cout, quelqu'un peut-il m'aider?

Répondre

3

Ce n'est pas un bogue et cela n'a rien à voir avec la mise en mémoire tampon de sortie.

L'ordre d'exécution des opérations i-- et i++ n'est pas défini lorsqu'elles sont appelées plusieurs fois en tant que paramètres du même appel de fonction.

Elaborer (et peut-être correct) la mention de Iraimbilanja de « points de séquence », la version cout équivaut à:

(((cout << a) << b) << c) 

En effet, il est en fait trois appels de fonction séparés, chacun dont les paramètres sont évalués afin , même si c'est écrit comme une seule déclaration.

L'opérateur << est vraiment ostream& operator<<(ostream& os, int), donc une autre façon d'écrire c'est:

operator<< (operator<< (operator<< (cout, a), b), c) 

Depuis le extérieur appellent ce n'est pas (AFAIK) défini quel ordre les deux paramètres sont évalués, il est parfaitement possible pour le le paramètre "c" de la main droite (ou dans votre cas "i--") avant d'évaluer le paramètre de la main gauche.

+0

Salut, Alnitak, J'ai une question que je pense que le tampon de Cout obtenir la sortie de droite à gauche, puis les sortir de droite à gauche, aussi. Mais je pense que dans votre code, le tampon cout obtient la sortie de gauche à droite, est-ce vrai? Merci ~ – lucas

+0

Et dans le g ++, le cout << "i =" << i << "i ++ =" << i ++ << "i - =" << i - << endl; sortie i = 0 i ++ = 0 i - = 1 mais dans le VS2005, il sort i = 0 i ++ = - 1 i - = 0 Pouvez-vous expliquer cela? – lucas

+0

Je ne peux pas expliquer la différence, mais je suis confiant sur l'imbrication gauche-droite que j'ai montrée. La fonction est ostream & operator << (ostream &, ) donc il doit s'emboîter de cette façon. – Alnitak

6

La sortie de:

printf("i=%d i++=%d i--=%d\n" , i , i++ ,i--); 

est non spécifiée. C'est un piège courant de C++: l'ordre d'évaluation des arguments n'est pas spécifié. Il n'en est pas de même avec le cas de la coutume: il utilise des appels chaînés (points de séquence), et non des arguments pour une seule fonction, de sorte que l'ordre d'évaluation est bien défini de gauche à droite.

Edit: David Thornley souligne que le comportement du code ci-dessus est en fait undefined.

+0

C'est pire que non spécifié; c'est indéfini. Il n'y a aucune garantie que le résultat correspondra à n'importe quel ordre d'évaluation, bien que ce soit habituellement ce qui se passe compte tenu de la mise en œuvre évidente. Cependant, +1 pour l'explication du cas de cout. –

0

si possible, essayez de mettre à jour à gcc> = 4. Je viens de lancer ceci sur 4.0.1 et il exécute juste dandy.

+0

Alors que gcc 3.x est très très ancien et la mise à jour peut être une bonne idée en général, dans ce cas le fait est qu'aucun des résultats n'est "correct". C'est juste non spécifié, et s'appuyer sur un comportement non spécifié peut changer d'une version du compilateur à l'autre. – janneb

+2

Étant donné que ce comportement n'est pas défini, (a) tout comportement est juste dandy selon la norme, et (b) vous ne savez pas s'il donnera le comportement que vous attendez d'une autre version, d'autres options du compilateur, ou autre code environnant. –

Questions connexes