2015年1月28日 星期三

C++ Pointer 與 Array




指標(Pointer)其實是"箭頭",內容其實是位址(Address)


Pointer 和 Array 可以說是 “兄弟關係” ,  關係相當緊密。




Pointer 與 一維陣列 


例如:

 int a [] = { 1, 2, 3, 4, 5 };

 a[3] 可以represent為 *(a+3)
 a[0] 可以represent為 *(a+0) or *a <-- *a的起始值是a[0]


或者可以用一個pointer指住一個array,
e.g. int *p = a;   // 此方法只適用於一維陣列,多維陣列的宣告方法會於文章末端提及。



此時, 若a陣列記憶體位址分佈如下:

a[0] =  12000
           12001
           12002
           12003

a[1] =  12004
           12005
           12006
           12007

a[2] =  12008
           12009
           12010
           12011
......
......


p = 12000, *p = a[0] = 1;
p+1 = 12004, *(p+1) = a[1] = 2;
p+2 = 12008, *(p+2) = a[2] = 3;

註: *p+1 和 *(p+1) 的意思是不同,
      *p+1 會等於 2 , 意思是指先把*p的值
      拿出來,然後再+1。





Pointer 與 多維陣列


例如:

int a[2][4] = { {1,3,5,7} , {2,4,6,8} };

陣列表示法 連續記憶體表示法 陣列索引值轉換表示法
a[0][0] 1 **a *(*(a+0)+0)
a[0][1] 3 *(*a+1) *(*(a+0)+1)
a[1][0] 2 *(*a+4) *(*(a+1)+0)
a[1][3] 8 *(*a+7) *(*(a+1)+3)

註:Pointer會把一個多維陣列中每欄的element都編上
       一個次序,例如第一欄 {1,3,5,7} ,所得的次序就是
       0-3 , 接著第二欄 {2,4,6,8} ,所得次序就是4-7。
       例如 *( *a+7 ) 中,由於 *a 值是 0 , 所以*a+7 得出
       是7,然後 *7 即是指排在第7元素的值,即是第二欄
       的第4個element的值, 即是8。



- 在二維陣列的記憶體裡的位置是連續的儲存空間

- *( *(a+i) + j )  == a [ i ] [ j ] ;

- a[0][1][3] == *( *( *a+1)+3 ) ;
- a[1][2][3] == *( *( *(a+1) + 2 ) +3 );






Exercise: 


#include <iostream.h>
void main() {

       int a [3] [4] = { {1,3,5,7} , {2,4,6,8} , {10,20,30,40} };
 
       int *p = &a[0][0];
       int *pp = a[0][0];
       int *p0 = a[0];  // p0的起始點會是a[0][0]
       int *p1 = a[1];  // p1的起始點會是a[1][0]
       int *p2 = a[2];
 
       cout << *(p+4+1) << endl;
       cout << *pp << endl;
       cout << *(p0+2)  << endl;
       cout << *p1  <<endl;
       cout << *(p2-2) <<endl;
       cout << *p2[3] <<endl;
    
}



output:
4
1
5
2
6
40




* 常見問題!


知道一維宣告方法是

int *arr = new int[1];

但是換成了

int *arr = new int[1][1];

就出錯了,為什麼呢?



解答:

==============================

當宣告一維陣列時,可以

const int x=10;
int obj[x];

用指標宣告方法:

const int x=10;
int *obj = new int[x];

================================

但當宣告二維時,必須使用**,
以便逐一由內而外配置。

const int x=10, y=20;
int **obj;
obj = new int*[x];  // 第一次分配第一維

for(int i=0; i<x; ++i) {
       obj[i] = new int [y]; // 第二次分配第二維
}



=================================

三維陣列做法一樣

const int x=10, y=20, z=5;

int ***obj;

obj = new int**[x]; // 配置一次少一個星

for(int i=0; i<x; ++i) {

       obj[i] = new int*[y];  // 再配置一次,再少一個星

       for(int j=0; j<y; ++j) {
                 obj[i][j] = new int[z];  // 再配置一次,再少一個星
       }
}



1 則留言:

  1. 不好意思,exercise那邊的第一個cout,是否應該改成:cout << *(p+3)+0 << endl;

    請多多指教

    回覆刪除