Posted on 2010-10-08 00:06
李熙建 閱讀(405)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
C++
某公司的筆試題本意是想考察學(xué)生對(duì)于指針問(wèn)題的理解和應(yīng)用,在做測(cè)試的時(shí)候發(fā)現(xiàn)使用連<<輸出符號(hào)一些有趣的問(wèn)題,在參數(shù)是表達(dá)式的情況下,分析一下編譯器是如何處理連<<問(wèn)題的
#include <iostream>
using namespace std;
int main()


{

char* a[] =
{"abc","def","ghi","jkl"};
char **p = a;
cout<<*p++<<",";
cout<<++*p<<",";
cout<<p[1]<<endl;
return 0;
}
輸出結(jié)果為:abc,ef,ghi 這個(gè)沒(méi)問(wèn)題,要注意一點(diǎn)的是++運(yùn)算符優(yōu)先級(jí)高于 “*”解引用運(yùn)算符。
下面我們把這三個(gè)cout寫成一條語(yǔ)句,先分析一下結(jié)果會(huì)是怎么樣呢?
#include <iostream>
using namespace std;
int main()


{

char* a[] =
{"abc","def","ghi","jkl"};
char **p = a;
cout<<*p++<<","
<<++*p<<","
<<p[1]<<endl;;
return 0;
}
還會(huì)是上面的輸出結(jié)果嗎?
輸出結(jié)果為:bc,def,ghi分析:
通過(guò)查看匯編代碼我們發(fā)現(xiàn),編譯器先首先檢查,如果<<參數(shù)為表達(dá)式,先會(huì)計(jì)算每個(gè)參數(shù)的值,并且計(jì)算的順序是從右到左的
1.由于p[1]已經(jīng)可以直接讀取了,不需要計(jì)算,
首先計(jì)算 ++*p ,*p指向abc中a的地址,經(jīng)過(guò)自加操作后指向b的地址
2.其次,計(jì)算*p++ ,編譯器會(huì)把*p的值保存到棧的一個(gè)位置,當(dāng)前*p就是上一步計(jì)算得到的值,然后將p++,這個(gè)時(shí)候p就指向了 串"def"的首地址
3.參數(shù)入棧,p[1]入棧,p[1]指向串"ghi"的首地址,所以p[1]的值為"ghi"
4.++*p的值入棧,當(dāng)前p指向串"def"的首地址 所以++*p的值為"def"
5.*p++的值入棧,是當(dāng)時(shí)保存的p++之前的*p的值 "bc" 所以*p++的值為"bc"
6.從左向右call三次<<輸出重載操作符函數(shù),每次調(diào)用形式為basic_ostream&<<(basic_ostream& cout,char*)
建議:從上面的分析可以看出,在使用cout輸出的時(shí)候,最好不要使用連<<,如果要使用的話,盡量保證每個(gè)輸出對(duì)象是單個(gè)的值,而不是表達(dá)式,表達(dá)式可能輸出的結(jié)果和我們的期望相差很大。
比如,我們把上面的兩個(gè)參數(shù)交換一下,感興趣的朋友可以試著分析一下:
#include <iostream>
using namespace std;
int main()


{

char* a[] =
{"abc","def","ghi","jkl"};
char **p = a;
cout<<++*p<<","
<<*p++<<","
<<p[1]<<endl;;
return 0;
}
//程序運(yùn)行結(jié)果:ef,abc,ghi