從一道筆試題來看指針的使用

原文地址:http://blog.csdn.net/demon__hunter/archive/2009/04/30/4140603.aspx

 

從一道筆試題來看指針的使用

不運行程序,問下面代碼的輸出是什麼?

 

1#include<iostream>
2 using namespace std;
3 int main()
4 {
5     char *str[]={"welcome","to","Fortemedia","Nanjing"};
6     char**p=str+1;
7     str[0]=(*p++)+2;
8     str[1]=*(p+1);

9     str[2]=p[1]+3;
10   str[3]=p[0]+(str[2]-str[1]);
11   cout<<str[0]<<endl;
12   cout<<str[1]<<endl;
13   cout<<str[2]<<endl;
14   cout<<str[3]<<endl;

15   system("pause");

16}

 

如果您分析的結果和程序運行的結果都一致,那麼下面的內容您可以忽略了,...o(∩_∩)o...

如果對上面的程序一頭霧水的話,個人建議那最好看一下下面的內容了。.......o(∩_∩)o...

指針是c/c++語言中一個重要的語言特性,但對於c/c++的初學者來說,卻不是那麼好理解。總起來說指針一個特殊的變量,這個變量能合法的使用*操作符對指針的變量內容進行提領(dereference)和成員訪問。對於指針變量在它四個字節(32位平臺)的內存裏存儲的數據是一個內存的地址值,也就是我們平時說的指向一個地址,而指針變量的類型則決定着對指針變量的所指向的地址裏的數據的訪問方式和從指向的地址開始往下所涵蓋的範圍。舉例來說:

 

#include<iostream>
using namespace std;

int main()
{
    int i[2]={1073741824,-1073741824};
    int *p1=&i[0];
    char *p2=(char*)&i[0];
    float *p3=(float*)&i[0];
    printf("%d->%d/n",p1,*p1);
    printf("%d->%d/n",p2,*p2);
    printf("%d->%f/n",p3,*p3);
    p1++;
    p2++;
    p3++;
    printf("%d->%d/n",p1,*p1);
    printf("%d->%d/n",p2,*p2);
    printf("%d->%f/n",p3,*p3);

    system("pause");

}

 

上述代碼中指針變量p1,p2,p3指向相同的地址值,都是i[0]所標識的內存的地址值,但由於指針的類型不同,導致用*運算符進行提領時,*p1,*p2,*p3的值不一樣。當p1用*提領p1所指向的內存裏的數據時,由於p1是int*型的,所以會從地址值爲&i[0]開始,往下涵蓋四個字節(sizeof(int))的內存,然後把裏面的數據安照int變量的存儲方式解析成一個int型數值。1073741824在內存&i[0]~&i[0]+3中存儲是0x00,0x00,0x00,0x40,(小段機 補碼存儲),所以*p1的值是1073741824。而p2是char*型的,所以僅從地址值爲&i[0](sizeof(char))的內存把裏面的數據按照char變量的存儲方式解析成一個char型數值,由於地址值爲&[i]的內存裏是0x00,所以*p2爲0.同樣由於p3是float*型的,所以會從地址值爲&i[0]開始,往下涵蓋四個字節(sizeof(float))的內存,然後把裏面的數據安照float變量的存儲方式解析成一個float型數值。由於float型變量的存儲方式不同於整型,c/c++浮點數存儲遵循ieee標準,按照標準*p3的值爲2.0(具體請參見本博客裏一篇關於float內存佈局的博文,不再贅述)。另外從上述代碼我們可以看到,指針變量的類型還影響着指針變量算術運算時的跨度,即指針變量+1時,指針變量的值會增加sizeof(指針所指向變量的類型)。

 

弄明白上面所分析的是掌握指針的關鍵(個人是這麼看的),基於剛纔的分析來看開始的筆試題:

 

首先在line 5聲明一個指針數組,而str的值就是數組的起始地址值,str的值被默認解析成char **變量的值。

 

line6聲明瞭一個2級指針,char**p=str+1;由於str是char**型,即str指向的類型是char *型的,所以p的值是(int)str+sizeof(char*),顯然p指向了str的第二個元素即str[1]的地址。

 

line7 :(*p++)+2;,由於後置運算符++優先級比*高,所以先進行++運算,p的值變爲(int)p+sizeof(char*),,顯然此時p指向了str[2]的地址,再進行*運算,由於後置是++返回未變化的p的值,取到了str[1]的值,即指向字符串"to"的指針的值,由於*p類型是char*的所以](*p++)+2;最終str[0]指向了“to”結尾的'/0'所以輸出str[0]時爲空。

 

line8:str[1]=*(p+1);,顯然str[1]指向了字符串"Nanjing"的首地址。cout<<str[1]<<endl;輸出字符串Nanjing

 

line9:很顯然cout<<str[2]<<endl;輸出jing

 

line10:由於在line7分析到p指向了str[2]的地址,由於line9中,把&str[2]~&str[2]+3裏的數據修改成了字符創"jing"的首地址。所以最終cout<<str[3]<<endl; 輸出g。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章