首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

cout输出有关问题!

2012-04-06 
高分求教cout输出问题!在线等!#includeiostreamusingnamespacestdintfoo(int&x){cout 第 x

高分求教cout输出问题!在线等!
#include   <iostream>
using   namespace   std;
int   foo(int   &x)
{
      cout   < <   "第 "   < <   x   < <   "次调用 "   < <   '\t ';
      return   ++x;
}

void   main()
{
      int   i   =   1;
      cout   < <   foo(i)   < <   '\t '   < <   foo(i)   < <   endl;
}


为什么会是如此输出:
        第1次调用               第2次调用               3               2

请高手指点一下!
不胜感激!


[解决办法]
cout < < 3 < < '\t ' < < 2 < < endl;
这句实际是调用了4次cout::operator < <,函数参数都预先已经压在栈里面了。

004020CB push offset @ILT+400(std::endl) (00401195)
004020D0 lea eax,[ebp-0A4h]
004020D6 push eax
004020D7 call @ILT+615(zoo) (0040126c)
004020DC add esp,4
004020DF push eax
004020E0 push 9
004020E2 lea ecx,[ebp-0A4h]
004020E8 push ecx
004020E9 call @ILT+685(foo) (004012b2)
004020EE add esp,4
004020F1 push eax
004020F2 mov ecx,offset std::cout (00485088)
004020F7 call @ILT+485(std::basic_ostream <char,std::char_traits <char> > ::operator < <) (004011ea)
004020FC push eax
004020FD call @ILT+780(std::operator < <) (00401311)
00402102 add esp,8
00402105 mov ecx,eax
00402107 call @ILT+485(std::basic_ostream <char,std::char_traits <char> > ::operator < <) (004011ea)
0040210C mov ecx,eax
0040210E call @ILT+855(std::basic_ostream <char,std::char_traits <char> > ::operator < <) (0040135c)


[解决办法]
1. C++标准中没有规定表达式的中子表达式的计算顺序(除了逗号表达式和逻辑运算表达式),所以到底怎样计算子表达式依赖具体编译器的实现。比如
int f();
int g();
int i;
i = f() + g();
该表达式中函数的优先级最高,应该先调用函数。
但计算顺序可以是先调用f(),然后调用g(),返回结果相加再赋给i,
也可以是先调用g(),然后调用f(),返回结果相加再赋给i。
具体是那种计算方式C++标准并没有规定,依赖编译器的实现。
所以上面的cout < < foo(i) < < "\t " < < zoo(i) < < endl;也是同样的道理。从汇编代码来看,VC,g++都是先调用zoo()再调用foo()的;而对上面加法表达式是先调用f(),再调用g()的。
这样的调用顺序在C++标准中是没有规定的,只是编译器的实现。

2. < <运算符是左结合的。也就是说
cout < < foo(i) < < "\t " < < zoo(i) < < endl;
在调用两个函数后,变成(这里假设函数调用顺序如1中所说)
cout < < 3 < < "\t " < < 2 < < endl;
然后,依次调用operator < < (ostream&, int), operator < <(ostream&, const char*), operator < <(ostream&, int)等等
[解决办法]
cout < < a(XXX) < < b(XXX) < < endl;

先计算b(XXX); 结果比如是“bbb”;

再计算a(XXX); 结果比如是 “aaa”;

在完成这两个函数运算之前,这个语句不会cout出任何东西
(函数a、b里的输出语句会直接输出,所以LZ代码先输出了两行有文字的)

这两个计算完了。上面的语句相当于

cout < < "aaa " < < "bbb " < < endl;

然后运行这个语句。与缓冲区没有关系,与堆栈也没有关系。虽然看起来像个堆栈的效果

至于为什么要先计算右面的函数。

C++的设计者BS说,C++标准没有规定应该先计算哪个。都可以。

但是从编译器设计的角度来说,先计算右面的会给设计带来方便。所以就先计算右面的了。

有兴趣的可以去找本编译原理书,看看“语法分析”部分。


热点排行