社区
C++ 语言
帖子详情
高分求教cout输出问题!在线等!
zcphoenix
2007-08-11 03:48:10
#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
请高手指点一下!
不胜感激!
...全文
838
37
打赏
收藏
高分求教cout输出问题!在线等!
#include 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 请高手指点一下! 不胜感激!
复制链接
扫一扫
分享
转发到动态
举报
AI
作业
写回复
配置赞助广告
用AI写文章
37 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
sq901003
2012-03-31
打赏
举报
回复
顶34层说的,这个跟栈好像没有什么关系吧, cout输出中间只是一个缓冲区,把要输出的数据,插入到流中,进入缓冲区的
LKStudio
2008-08-21
打赏
举报
回复
受益匪浅啊。。。
donnychou
2007-08-12
打赏
举报
回复
got it
sbgeqh
2007-08-12
打赏
举报
回复
看了以上的,应该都明白了
gfxiang
2007-08-12
打赏
举报
回复
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)等等
SimerJoe
2007-08-12
打赏
举报
回复
首先cout那句是从右往左执行的,
第一次调用foo由foo里面的cout输出: 第1次调用 此时return ++x 相当于 return 2
第二次调用foo由foo里面的cout输出: 第2次调用 此时return ++x 相当于 return 3
最后由main函数里面的cout输出: 2 3
lgdgyd2
2007-08-12
打赏
举报
回复
mark,研究一下!
missilery
2007-08-12
打赏
举报
回复
同步
临界区
nankezhishi
2007-08-12
打赏
举报
回复
cout << a(XXX) << b(XXX) << endl;
先计算b(XXX); 结果比如是“bbb”;
再计算a(XXX); 结果比如是 “aaa”;
在完成这两个函数运算之前,这个语句不会cout出任何东西
(函数a、b里的输出语句会直接输出,所以LZ代码先输出了两行有文字的)
这两个计算完了。上面的语句相当于
cout << "aaa" << "bbb" << endl;
然后运行这个语句。与缓冲区没有关系,与堆栈也没有关系。虽然看起来像个堆栈的效果
至于为什么要先计算右面的函数。
C++的设计者BS说,C++标准没有规定应该先计算哪个。都可以。
但是从编译器设计的角度来说,先计算右面的会给设计带来方便。所以就先计算右面的了。
有兴趣的可以去找本编译原理书,看看“语法分析”部分。
shinyix
2007-08-12
打赏
举报
回复
gfxiang(afu) 的说法是正确的
zcphoenix
2007-08-12
打赏
举报
回复
我个人觉得‘gfxiang(afu)’的解释是正确的,但是我还想问一下:
cout << foo(i) << "\t" << zoo(i) << endl;
对于这样的语句,为什么编译器多是选择从右至左的函数执行顺序?而不是从左至右呢?
这样选择是不是对代码的优化有什么好处?还是会带来其它方面的好处呢?
谢谢!
onlinewan
2007-08-11
打赏
举报
回复
这个啊,就是函数的执行过程的问题,也就是栈操作问题.
要等子调用的函数都执行完了,才能继续执行自己.
loops
2007-08-11
打赏
举报
回复
takecareofmyself() 所说的那个缓冲区就是栈,我以为说的是cout内部的buffer。
loops
2007-08-11
打赏
举报
回复
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)
wyjkk
2007-08-11
打赏
举报
回复
我干脆总结一下吧:
原始输出语句: cout << foo(i) << '\t' << foo(i) << endl;
从又向左执行
1:执行<<endl,因为没有std::cout对象,无法执行,压栈
2:执行<<foo(i),执行foo(1),输出:第1次调用,得到返回值2,还是因为没有std::cout对象,无法马上输出,压栈
此时,代码变成cout << foo(i) << '\t' << 2 << endl;
3:执行<< '\t' ,没有std::cout对象,无法马上输出,压栈
此时,代码变成cout << foo(i) << '\t' << 2 << endl;
4:执行<<foo(i),执行foo(2),输出:第2次调用 得到返回值3,还是因为没有std::cout对象,无法马上输出,压栈
此时,代码变成cout << 3 << '\t' << 2 << endl;
输出上面的代码,OK,就是LZ看到的。
wyjkk
2007-08-11
打赏
举报
回复
我干脆总结一下吧:
原始输出语句: cout << foo(i) << '\t' << foo(i) << endl;
从又向左执行
1:执行<<endl,因为没有std::cout对象,无法执行,压栈
2:执行<<foo(i),执行foo(1),
输出:第1次调用
cnssccgg
2007-08-11
打赏
举报
回复
在执行这条语句cout << foo(i) << '\t' << foo(i) << endl;时,首先依次调用了两个foo(i),于是屏幕上出现了“第1次调用 第2次调用”,同时将两个返回值压入堆栈,这时,
cout << foo(i) << '\t' << foo(i) << endl语句,就变成了
cout <<‘3’<< '\t' <<‘2’ << endl;
wyjkk
2007-08-11
打赏
举报
回复
takecareofmyself() ( ) 信誉:100
正确
jayfer
2007-08-11
打赏
举报
回复
进程空间:
代码区----------------存放程序的执行代码
全局数据区------------存放全局数据,常量,文字量,静态全局量和静态局部量
堆区------------------存放动态内存,供程序随机申请使用
栈区------------------函数数据区(局部数据区)
(以上是运行中的内存布局)
函数调用的整个过程就是栈空间操作的过程。函数调用时,C++作以下工作:
(1)建立被调函数的栈空间,其大小由函数定义体中的数据量决定;
(2)保护调用函数的运行状态和返回地址;
(3)传递参数;
(4)将控制权转交给被调函数;
(5)函数运行完成后,复制返回植到函数局部数据块底部;
(6)恢复被调函数的运行状态;
(7)返回调用函数。
调用一个函数可以看作是一个栈中元素的压栈与退栈操作。
MPTD_Fire
2007-08-11
打赏
举报
回复
lz
我给你个解析
对于cout输出不压入堆栈,直接输出。而参数要压入堆栈,所以输出是3,2
不知道对不?
加载更多回复(17)
C/C++ C++ / 面向对象
对象与类 成员函数、全局函数和友元函数的差别? 写一个c++的类时,对于成员函数,私有变量的考虑好吗? 关于const 在const reference parameter中使用的大不解 C++中虚函数和纯虚函数的概念,差别和分别存在的原因 为何析构函数中的
cout
不起作用 请高手介绍一
什么?!双非BAT大厂技术offer,举报了哥(含职位名单)
一共就两面,一面HR了解意向,二面技术面试面试流程:自我介绍开局,问了问项目细节,校园活动组织。腾讯的面试官是真牛B呀,点名pcg,题目两道都撕出来了,其他的感觉答的不算差呀,结果反手给我挂了,你***是真恶心人呀,凭什么挂呀你啊啊,搁着浪费时间呢,我只能。泛微来学校开了宣讲会,结果宣讲会一结束就是笔试,接着就是面试(这个公司很缺人吗......)我抱着攒面试经验的心态去面了销售,结果HR对我表示怀疑,然后建议我去。面试流程:自我介绍开头,问了一部分测评中的
问题
,将简历当中的项目经历、校园经。
C/C++ C++ / 面向对象 FAQ
C/C++ C++ / 面向对象 对象与类 成员函数、全局函数和友元函数的差别? 写一个c++的类时,对于成员函数,私有变量的考虑好吗? 关于const 在const reference parameter中使用的大不解 C++中虚函数和纯虚函数的概念,差别和分别存在的原因 为何析构函数中的
cout
不起作用 请高
Oracle-QA模块概念培训.ppt
Oracle-QA模块概念培训.ppt
gen-colpali-similarity-maps(对于Colpali 的个人理解)
gen-colpali-similarity-maps(对于Colpali 的个人理解)
C++ 语言
65,186
社区成员
250,526
社区内容
发帖
与我相关
我的任务
C++ 语言
C++ 语言相关问题讨论,技术干货分享,前沿动态等
复制链接
扫一扫
分享
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++
技术论坛(原bbs)
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
请不要发布与C++技术无关的贴子
请不要发布与技术无关的招聘、广告的帖子
请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下
试试用AI创作助手写篇文章吧
+ 用AI写文章