C++中cout语句背后的堆栈知识
C++中的cout是最常见的,假如cout后面有多个输出的话,他们的输出顺序是什么呢?决定他们输出顺序背后的原理是什么呢?先看下面的代码(1):
1 #include<iostream> 2 using namespace std; 3 int abs(int a); 4 int main() 5 { int a=-5; 6 cout<<a<<endl<<abs(a)<<endl; 7 } 8 int abs(int a) 9 { cout<<"int a"<<endl; 10 return (a>=0?a:-a); 11 }
大家看一眼第6行的输出结果:很多人认为是-5
int a
5
可实际的结果是这样吗?看下图
图(1)
是不是与我们期望的不一样?
最后的输出结果与cout背后的汇编中堆栈有很大联系,我们知道汇编中堆栈是“后入先出”的存储区,执行第6行语句,从右向左依次把要输出的值压入堆栈,最后从上到下依次输出,第6行的汇编伪代码如下(以下代码不是严格意义上的汇编代码,为容易理解而写成):
push endl;//把换行符压入
push abs(a);//压入函数返回值,函数返回值压入堆栈需要两步:首先先执行cout<<"int a"<<endl;这行语句,故屏幕先显示出int a,然后计算a的绝对值并压入堆栈
push endl;
push a;输出a的值
到此所有的值都压入堆栈,并且此过程中执行其他语句(第9行)的输出结果在屏幕上已经显示出来,然后堆栈中的值依次出栈,在屏幕上先显示-5,再显示5;
假如还有点迷糊的话,再看一个例子(代码2):
1 #include<iostream> 2 using namespace std; 3 int abs(int a); 4 float abs(float b); 5 int main() 6 { int a=-5; 7 float c=-2.4f; 8 cout<<"a="<<abs(a)<<endl<<"c="<<abs(c)<<endl; 9 return 0; 10 } 11 int abs(int a) 12 { cout<<"int abs"<<endl; 13 return(a>=0?a:-a); 14 } 15 float abs(float b) 16 { cout<<"float abs"<<endl; 17 return(b>=0?b:-b); 18 }
假如还按照原来的感觉,那么输出顺序应该是a=int abs
5
c=float abs
2.4
运行结果如下图:
图(2)
还是按照上面提到的汇编的方法分析下,压入堆栈的汇编伪代码如下:
push endl;
push abs(c);//需要强调的是这一步中 float abs立刻在屏幕中显示出来,无需等到所有的值压入堆栈完毕
push c=;
push endl;
push abs(a);//这一步也立刻把int abs显示出来,显示在float abs下面
push a=;
等上面所有的步骤执行完后,然后堆栈中的值依次出栈,最后的输出结果如图(2),代码(2)用到了重载函数,也是很有趣的知识。顺便提一句,在重载函数中,任意两个函数的参数表中函数的个数,各参数的数据类型和顺序不能完全一样,如int func(int a,char b,float c)和double func(int d,char e,float f)。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。