指標指向2維陣列
Prerequisites:
觀念
所謂的2維陣列,事實上是指向一維「指標陣列」,一維指標陣列的「元素」,再指向一維「整數陣列」。
宣告方式:
圓括號包住(* 指標名)代表指標指向大小為3 *4byte = 12 byte的「一維陣列」。
int (* 指標名)[大小] = 陣列名;
int (* ptr)[3] = arr;
指標
指標有自己的記憶體位址,存放的記憶體位址是指向arr[0]的一維陣列。
1
2
3
4
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
cout << "ptr addr = " << &ptr << endl;
cout << "ptr value = " << ptr << endl;
ptr addr = 0x1000
ptr value = 0x2000
指標的移動
指標指向大小為3 *4byte = 12 byte的「一維陣列」。
所以指標的每一次移動是+12byte,而不是+4byte,它的移動單位是一維陣列大小12byte。
1
2
3
4
5
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
cout << "ptr+0 addr=" << * (ptr + 0) << endl;
cout << "ptr+1 addr=" << * (ptr + 1) << endl;
cout << "ptr+2 addr=" << * (ptr + 2) << endl;
ptr+0 addr=0x2000
ptr+1 addr=0x200C
ptr+2 addr=0x2018
取值運算子*
對指標陣列的元素使用「*取值運算子」,可以取到指向一維陣列中的「記憶體位址」。
下圖中,對*(ptr + 2)
使用取值運算子,黃色區塊就是取到的位址。
1
2
3
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
cout << "ptr+2 addr=" << * (ptr + 2) << endl;
ptr+2 addr=0x2018
再對記憶體位址,使用*取值運算子,會得到存放的內容。
1
2
3
4
5
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
cout << "ptr+2 addr=" << * (ptr + 2) << endl;
// 取出內容
cout << "ptr+2 value=" << * ( * (ptr + 2)) << endl;
ptr+2 addr=0x2018
ptr+2 value=70
取值運算子*與移動指標
先把位址使用取值運算子*取出來,此時取出來的位址是int*
整數指標類型,移動的單位是4byte,而不是12byte。
再把取出的位址+1就會移動4byte到下一格的記憶體位址。
1
2
3
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
cout << "addr=" << * (ptr + 2) + 1 << endl;
addr=0x201C
再對記憶體位址,使用*取值運算子,會得到存放的內容。
1
2
3
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
cout << "value=" << * ( * (ptr + 2) + 1 ) << endl;
value=80
指標遍歷2維陣列
使用指標來遍歷2維陣列。
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {
int arr[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} };
int (* ptr)[3] = arr;
int rowsize = sizeof(arr) / sizeof(arr[0]);
int colsize = sizeof(arr[0]) / sizeof(int);
for (int i=0; i < rowsize;i++) {
for(int j=0; j < colsize;j++) {
cout << * ( * (ptr + i) + j) << " ";
}
cout << endl;
}
return 0;
}
10 20 30
40 50 60
70 80 90
另一種簡便的遍歷方式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
int arr[3][3] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
int row = sizeof(arr) / sizeof(arr[0]);
int column = sizeof(arr[0]) / sizeof(int);
// 宣告指標,指向二維陣列
// 注意!有括號包住指標(* ptr),有圓括號包住代表指向二維陣列的指標
int (* ptr)[3] = arr;
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
// 用法跟2維陣列用法相同,但變數名改為ptr
cout << ptr[i][j] << " ";
}
cout << endl;
}
return 0;
}
10 20 30
40 50 60
70 80 90
以下為舊的文章內容。
指標指向二維陣列
指標指向二維陣列,英文是pointer to array。
二維陣列可以解釋為,一維陣列,裡面每一個元素又指向一維陣列。
宣告方式
資料類型 (*指標變數)[二維陣列每個元素所指向的一維陣列大小] = 二維陣列變數名;
使用二維陣列指標一定要把*指標變數用括號()包起來,因為有運算子優先順序的問題。
1
2
3
4
5
6
7
int main() {
//[3]代表二維陣列每個元素是大小為3的一維陣列。
int arr[2][3] = { {1,2,3},{4,5,6} };
//[3]代表二維陣列每個元素是大小為3的一維陣列。
int (* p)[3] = arr;
return 0;
}
二維陣列傳函式
方法有二種
- 指標方式 void func(int (*p)[3], int len);
- 陣列方式 void func(int p[][3], int len);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
void func(int (* p)[3], int len) {
for (int i = 0; i < len; i++) {
for (int j = 0; j < 3; j++) {
cout << "p[" << i << "][" << i << "] = " << p[i][j] << "\t";
}
cout << endl;
}
}
int main() {
//[3]代表每個元素是大小為3的一維陣列。
int arr[2][3] = { {1,2,3},{4,5,6} };
func(arr, 2);
return 0;
}
p[0][0] = 1 p[0][0] = 2 p[0][0] = 3
p[1][1] = 4 p[1][1] = 5 p[1][1] = 6
指標轉型
以下程式碼原本指向一維陣列的指標,指向二維陣列會編譯錯誤。
//二維陣列
int arr[2][3] = {0};
//原本指向一維陣列的指標,直接指向二維陣列會編譯錯誤
int* p = arr;
Cannot initialize a variable of type ‘int *’ with an lvalue of type ‘int[2][3]’
二維陣列先轉成一維陣列,使用(int*)
,再讓指標指向轉型成一維的陣列。
int arr[2][3] = {0};
int* p = (int*)arr;
二維陣列轉成一維陣列
- 2維陣列記憶體位址是連續
- 把陣列名指派給指標,是把陣列[0][0]的記憶體位址指派給指標
- 使用指標把連續的記憶體位址中的值印出來。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
using namespace std;
int main() {
//宣告陣列長度,初始化陣列全部元素為整數0
int arr[2][3] = {0};
//指派值到二維陣列
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;
//印出值
cout << "arr[0][0] = " << arr[0][0] << endl;
cout << "arr[0][1] = " << arr[0][1] << endl;
cout << "arr[0][2] = " << arr[0][2] << endl;
cout << "arr[1][0] = " << arr[1][0] << endl;
cout << "arr[1][1] = " << arr[1][1] << endl;
cout << "arr[1][2] = " << arr[1][2] << endl;
//記憶體位址是連續
cout << "arr[0][0]位址 = " << (long long)&arr[0][0] << endl;
cout << "arr[0][1]位址 = " << (long long)&arr[0][1] << endl;
cout << "arr[0][2]位址 = " << (long long)&arr[0][2] << endl;
cout << "arr[1][0]位址 = " << (long long)&arr[1][0] << endl;
cout << "arr[1][1]位址 = " << (long long)&arr[1][1] << endl;
cout << "arr[1][2]位址 = " << (long long)&arr[1][2] << endl;
//因為記憶體位址都是連續的,把二維陣列[0][0]記憶體位址指派給指標p
int* p = (int*)arr;
//取得arr變數記憶體大小
int size = sizeof(arr) / sizeof(int);
for (int i = 0; i < size; i++) {
//使用指標運算印出每個元素的值
cout << "*(p + " << i << ") = " << *(p+i) << ",";
//使用索引方式印出值
cout << " [" << i << "] = " << p[i] << endl;
}
return 0;
}
arr[0][0] = 1
arr[0][1] = 2
arr[0][2] = 3
arr[1][0] = 4
arr[1][1] = 5
arr[1][2] = 6
arr[0][0]位址 = 140702053823568
arr[0][1]位址 = 140702053823572
arr[0][2]位址 = 140702053823576
arr[1][0]位址 = 140702053823580
arr[1][1]位址 = 140702053823584
arr[1][2]位址 = 140702053823588
*(p + 0) = 1, [0] = 1
*(p + 1) = 2, [1] = 2
*(p + 2) = 3, [2] = 3
*(p + 3) = 4, [3] = 4
*(p + 4) = 5, [4] = 5
*(p + 5) = 6, [5] = 6
從以上結果可以發現,記憶體位址的差距為4byte,而且是連續的。
可以使用指標把二維陣列轉成一維指標陣列,印出值。
指標指向三維陣列
宣告方式
資料類型 (*指標變數)[陣列個數][元素個數] = 三維陣列變數名;
三維陣列傳函式的方法有二種
- 指標方式
void func(int (*p)[2][3], int len);
- 陣列方式
void func(int p[][2][3], int len);
印出陣列元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
void func(int (* p)[2][3], int len) {
for (int i = 0; i < len; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 3; k++) {
cout << "p[" << i << "][" << j << "][" << k << "] = " << p[i][j][k] << "\t";
}
cout << endl;
}
cout << endl;
}
}
int main() {
int arr[2][2][3] =
{
{ {1,2,3}, {4,5,6} },
{ {7,8,9}, {10,11,12} }
};
func(arr, 2);
return 0;
}
p[0][0][0] = 1 p[0][0][1] = 2 p[0][0][2] = 3
p[0][1][0] = 4 p[0][1][1] = 5 p[0][1][2] = 6
p[1][0][0] = 7 p[1][0][1] = 8 p[1][0][2] = 9
p[1][1][0] = 10 p[1][1][1] = 11 p[1][1][2] = 12
修改陣列元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;
const int firstMax = 2;
const int secondMax = 2;
const int thirdMax = 3;
void modifyArr(int p[][secondMax][thirdMax], int len) {
for (int i = 0; i < len; i++) {
for (int j = 0; j < secondMax; j++) {
for (int k = 0; k < thirdMax; k++) {
//修改指標記憶體位址的值
p[i][j][k] += 10;
}
}// end of j
}// end of i
}
void printArr(int (*p)[secondMax][thirdMax], int len) {
for (int i = 0; i < len; i++) {
for (int j = 0; j < secondMax; j++) {
for (int k = 0; k < thirdMax; k++) {
cout << "p[" << i << "][" << j << "][" << k << "] = " << p[i][j][k] << "\t";
}
cout << endl;
}// end of j
cout << endl;
}//end of i
}
int main() {
int arr[firstMax][secondMax][thirdMax] =
{
{ {1,2,3}, {4,5,6} },
{ {7,8,9}, {10,11,12} }
};
modifyArr(arr, firstMax);
printArr(arr, firstMax);
return 0;
}
p[0][0][0] = 11 p[0][0][1] = 12 p[0][0][2] = 13
p[0][1][0] = 14 p[0][1][1] = 15 p[0][1][2] = 16
p[1][0][0] = 17 p[1][0][1] = 18 p[1][0][2] = 19
p[1][1][0] = 20 p[1][1][1] = 21 p[1][1][2] = 22