1

我知道今天 cout 和 printf 有缓冲区,据说缓冲区有点像堆栈,从右到左获取 cout 和 printf 的输出,然后从上到下将它们输出(到控制台或文件)。像这样,

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

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

然后我在下面写一个代码,

#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; 
} 

VS2005下,输出为

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

在 g++( (GCC) 3.4.2 (mingw-special)) 下,输出为,

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

看起来缓冲区就像一个堆栈。但是,我今天阅读了C++ Primer Plus,据说 cout 从左到右工作,每次返回一个对象(cout),所以“这就是让您通过插入连接输出的功能”。但是从左到右的方式无法解释 cout< 输出 9 8 7 现在我对 cout 的缓冲区如何工作感到困惑,有人可以帮助我吗?

4

3 回答 3

6

输出:

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

未指定。这是 C++ 的一个常见缺陷:未指定参数评估顺序。

cout 情况并非如此:它使用链式调用(序列点),而不是单个函数的参数,因此评估顺序从左到右定义良好。

编辑: David Thornley 指出上述代码的行为实际上是undefined

于 2009-03-18T17:21:30.887 回答
3

这不是错误,也与输出缓冲无关。

i--当andi++操作作为同一个函数调用的参数被多次调用时,并没有定义它们的执行顺序。

为了详细说明(并且可能是正确的)Iraimbilanja 提到的“序列点”,该cout版本相当于:

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

实际上,它实际上是三个独立的函数调用,每个函数的参数都按顺序计算,即使它写得像一条语句。

<<运算符是真的,ostream& operator<<(ostream& os, int)所以另一种写法是:

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

由于对于外部调用,它没有(AFAIK)定义评估两个参数的顺序,因此右侧“c”参数(或在您的情况下为“ i--”)完全有可能在评估左侧参数之前发生。

于 2009-03-18T17:20:39.313 回答
0

如果可能,请尝试更新到 gcc >= 4。我刚刚在 4.0.1 上运行它,它执行得很好。

于 2009-03-18T17:31:59.397 回答