是技术,更是艺术

一心编程,就没有解决不了的问题
posts - 9, comments - 11, trackbacks - 0, articles - 0

cout问题

Posted on 2010-10-08 00:06 李熙建 阅读(393) 评论(0)  编辑 收藏 引用 所属分类: C++

某公司的笔试题本意是想考察学生对于指针问题的理解和应用,在做测试的时候发现使用连<<输出符号一些有趣的问题,在参数是表达式的情况下,分析一下编译器是如何处理连<<问题的

#include <iostream>
using namespace std;
int main()
{
    
char* a[] = {"abc","def","ghi","jkl"};
    
char **= a;
    cout
<<*p++<<",";
    cout
<<++*p<<",";
    cout
<<p[1]<<endl;
    
return 0;
}
输出结果为:abc,ef,ghi
这个没问题,要注意一点的是++运算符优先级高于 “*”解引用运算符。

下面我们把这三个cout写成一条语句,先分析一下结果会是怎么样呢?
#include <iostream>
using namespace std;
int main()
{
    
char* a[] = {"abc","def","ghi","jkl"};
    
char **= a;
    cout
<<*p++<<","
        
<<++*p<<","
        
<<p[1]<<endl;;
    
return 0;
}
还会是上面的输出结果吗?
输出结果为:bc,def,ghi
分析:
通过查看汇编代码我们发现,编译器先首先检查,如果<<参数为表达式,先会计算每个参数的值,并且计算的顺序是从右到左的
1.由于p[1]已经可以直接读取了,不需要计算,
 首先计算 ++*p ,*p指向abc中a的地址,经过自加操作后指向b的地址
2.其次,计算*p++ ,编译器会把*p的值保存到栈的一个位置,当前*p就是上一步计算得到的值,然后将p++,这个时候p就指向了 串"def"的首地址
3.参数入栈,p[1]入栈,p[1]指向串"ghi"的首地址,所以p[1]的值为"ghi"
4.++*p的值入栈,当前p指向串"def"的首地址 所以++*p的值为"def"
5.*p++的值入栈,是当时保存的p++之前的*p的值 "bc" 所以*p++的值为"bc"
6.从左向右call三次<<输出重载操作符函数,每次调用形式为basic_ostream&<<(basic_ostream& cout,char*)

建议:从上面的分析可以看出,在使用cout输出的时候,最好不要使用连<<,如果要使用的话,尽量保证每个输出对象是单个的值,而不是表达式,表达式可能输出的结果和我们的期望相差很大。

比如,我们把上面的两个参数交换一下,感兴趣的朋友可以试着分析一下:
#include <iostream>
using namespace std;
int main()
{
    
char* a[] = {"abc","def","ghi","jkl"};
    
char **= a;
    cout
<<++*p<<","
        
<<*p++<<","
        
<<p[1]<<endl;;
    
return 0;
}

//程序运行结果:ef,abc,ghi

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理