2011年11月16日

C++: pointer (指標)

學C/C++,我想pointer(指標)是最大的門檻吧!
這也是大部分人學C/C++,最痛的東西吧!
這篇就稍微的講解pointer!

pointer是專門用來儲存某變數記憶體位置!
每宣告一個pointer時,就會配置一塊4 bytes的記憶體空間,
專門用來儲存某變數的記憶體位置。
下面用簡單的code來說明,
int iValue = 10;
int *iPointer = &iValue;

printf("iPointer的value=%d \r\n"            ,  *iPointer);      //取值要用* 
printf("iPointer儲存value的address=%X \r\n" ,  iPointer);       //沒有*就是印出本身儲存的記憶體位置   
printf("iPointer本身的address=%X \r\n"      ,  &iPointer);      //取得記憶體位置都是用& 
printf("iValue  本身的address=%X \r\n"      ,  &iValue);        //取得記憶體位置都是用& 
printf("iPointer的size=%d \r\n"             ,  sizeof(iPointer));  
printf("iValue的size=%d \r\n"               ,  sizeof(iValue));    





下面為執行結果以及說明,:
output    說明
   iPointer的value=10印出儲存的記憶體位置本身的value,前面說過pointer是用來儲存記憶體位置,
如果要取得該記憶體位置的value,就是利用*
   iPointer儲存value的address=28FF3C印出iPointer儲存的資訊(記憶體位置)
   iPointer本身的address=28FF38iPointer自己的記憶體起始位置在哪
   iValue  本身的address=28FF3C第四行就是印出iValue本身的記憶體起始位置,會發現跟第二行一樣,因為iPointer就是儲存這個資訊
   iPointer的size=4印出iPointer的大小,前面說過,每個pointer的大小都為4 bytes,不論型態為和
   iValue的size=4印出iValue本身的大小,因為是interger,所以為4 bytes


上面為基本用法。
pointer也很常用來做字串的處理。
原因是用指標處理字串較省記憶體空間,也比較彈性,
我們可以宣告一個字串指標指向一個字串常數,
下面是個簡單的範例:
char *pValue[2]     = {"Ken","Yang"};
char szValue[2][10] = {"Ken","Yang"};
printf("szValue的value=%s \r\n"   ,  szValue[0]);     
printf("pValue的value=%s \r\n"  ,  pValue[0]);    
printf("szValue的size=%d \r\n"   ,  sizeof(szValue));     
printf("pValue的size=%d \r\n"  ,  sizeof(pValue));    



下面為執行結果以及說明,顏色相同的為該對應的結果及說明:
output    說明
  szValue的value=Ken印出儲存在陣列0的value
  pValue的value=Ken印出儲存在指標陣列0的value
  szValue的size=20字元陣列的大小為20
  pValue的size=8指標陣列的大小為8

可以發現陣列以及指標陣列的第0項,都是ken阿,可是大小卻都不一樣!
陣列的大小為20,而指標陣列為8
這就是為什麼使用指標會較為省空間的原因,且也較為彈性
因為字串指標是可以更改值的,可是字元陣列是不行的。

指標還有個特性,就是可以用來做運算,
可以看下面簡單的範例,
char *pString = "Ken";
cout << pString << endl;
cout << *(pString+1) << endl;
cout << sizeof(pString) << endl;
cout << sizeof(*(pString+1)) << endl;
cout << &pString << endl;


上面的例子,第一行我們先宣告字串指標,然後指定一個字串常數給他,
第二行就是印出value來(會印出Ken)
第三行就是進行指標的運算(會印出e,如果我們改成+2,就變成n)
第四行是印出大小,會印出4,因為說過指標的長度都固定為4
第五行也是印出大小,差別是印出該位置的字元大小,那就一定是1了
第六行就是印出該記憶體位置了,會發現字串指標跟前面講的變數指標(int, double..之類的)存取value或者存取記憶體的方式都不太同。


最後要講的是指標函數,用個簡單的範例來說明,
void fnPointer(int *pValue){
     *pValue=*pValue+1;
     cout << pValue << endl;    //印出記憶體位置
}
main(){  
     int iValue = 2; 
     cout << &iValue << endl;
     fnPointer(&iValue);   //傳遞int變數的記憶體位置進去
     cout << iValue << endl;
}

我們先宣告一個函數,那個函數裡的參數是pointer型態,
那麼使用方式就是傳遞某變數的記憶體位置進去即可,
因為我們說過指標是用來存某變數的記憶體位置!!!
所以就是傳遞記憶體位置進去。
然後我們再函數fnPointer裡面對value進行+1的動作,
然後在印出傳遞進來pointer的記憶體位置,
而主程式則是先印出iValue的記憶體位置,
在印出iValue的值。
會發現,主程式跟函數印出來的記憶體位置都相同!!
且在函數裡面進行+1以後,最後在main印出的value會變成3。
如果有些人可能會認為還是印出2,代表對pointer的概念還是不太了解(囧),因為是pointer,還是存取到原本的變數啊!
所以也是對原本的變數做操作!!!
印出2的方式我們稱為call by value,
但印出3的方式我們稱為call by address!
還有一種是call by reference!
後面一篇會講道!


以上是pointer一些簡單的介紹!
下一篇會介紹c++才有的參考(reference)























0 意見:

張貼留言