Posted on 2010-10-08 00:06
李熙建 閱讀(405)
評論(0) 編輯 收藏 引用 所屬分類:
C++
某公司的筆試題本意是想考察學生對于指針問題的理解和應用,在做測試的時候發現使用連<<輸出符號一些有趣的問題,在參數是表達式的情況下,分析一下編譯器是如何處理連<<問題的
#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;
}
輸出結果為:abc,ef,ghi 這個沒問題,要注意一點的是++運算符優先級高于 “*”解引用運算符。
下面我們把這三個cout寫成一條語句,先分析一下結果會是怎么樣呢?
#include <iostream>
using namespace std;
int main()


{

char* a[] =
{"abc","def","ghi","jkl"};
char **p = 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 **p = a;
cout<<++*p<<","
<<*p++<<","
<<p[1]<<endl;;
return 0;
}
//程序運行結果:ef,abc,ghi