C語言的二維陣列

複習一維陣列

介紹陣列與指標相關的文章實在太多了,我們簡單帶過一維陣列: #include <stdio.h> int main() { const int length = 3; int arr[length]; int i; printf(" arr = %p\n", arr); printf("&arr = %p\n", &arr); printf("size of array: %lu = %lu * %d\n", sizeof(arr), sizeof(int), length); printf("length of array: %ld\n", sizeof(arr) / sizeof(arr[0])); for (i = 0; i < length; i++) arr[i] = i; // Show. for (i = 0; i < length; i++) printf("address %p: value = %d (size = %lu)\n", &arr[i], arr[i], sizeof(arr[i])); return 0; } 輸出如下: arr = 0x7ffdcf290ce0 &arr = 0x7ffdcf290ce0 size of array: 12 = 4 * 3 length of array: 3 address 0x7ffdcf290ce0: value = 0 (size = 4) address 0x7ffdcf290ce4: value = 1 (size = 4) address 0x7ffdcf290ce8: value = 2 (size = 4) 「&arr」與陣列變數「arr」是等價的。

有時遇到長度不固定,可以在長度確定後,再用malloc()配置指標,記得養成好習慣,使用後用free()釋出記憶體,不然在程式結束之前,會一直佔用malloc的記憶體區域。 #include <stdio.h> #include <stdlib.h> int main() { int length; int *ptr; int i; length = 3; ptr = (int*)malloc(sizeof(int) * length); printf("ptr = %p\n", ptr); printf("&ptr = %p\n", &ptr); // Wrong //printf("size of array: %lu = %lu * %d\n", sizeof(ptr), sizeof(int), length); //printf("length of array: %lu\n", sizeof(ptr) / sizeof(ptr[0])); printf("size of array: %lu * %d\n", sizeof(int), length); printf("size of pointer: %lu\n", sizeof(ptr)); for (i = 0; i < length; i++) ptr[i] = i; // Show 1: as an array. printf("--- Show 1 ---\n"); for (i = 0; i < length; i++) printf("address %p: value = %d (size = %lu)\n", &ptr[i], ptr[i], sizeof(ptr[i])); // Show 2: as a pointer. printf("--- Show 2 ---\n"); for (i = 0; i < length; i++) printf("address %p: value = %d (size = %lu)\n", ptr + i, *(ptr + i), sizeof(*(ptr + i))); free(ptr); return 0; } 輸出如下: ptr = 0x55cd601b02a0 &ptr = 0x7ffd42666ec0 size of array: 4 * 3 size of pointer: 8 --- Show 1 --- address 0x55cd601b02a0: value = 0 (size = 4) address 0x55cd601b02a4: value = 1 (size = 4) address 0x55cd601b02a8: value = 2 (size = 4) --- Show 2 --- address 0x55cd601b02a0: value = 0 (size = 4) address 0x55cd601b02a4: value = 1 (size = 4) address 0x55cd601b02a8: value = 2 (size = 4) sizeof()輸入一個指標變數,得到的大小,是儲存一個位址所需要的大小,在64位元的作業系統中,是8-Byte,也就是64-bit。

二維陣列

先來看3×5的二維陣列範例。
Column 0 Column 1 Column 2 Column 3 Column 4
Row 0 0 1 2 3 4
Row 1 10 11 12 13 14
Row 2 20 21 22 23 24

#include <stdio.h> int main() { const int row = 3, column = 5; int arr[row][column]; int i, j; for (i = 0; i < row; i++) { for (j = 0; j < column; j++) { arr[i][j] = (10 * i) + j; } } // Show. printf("arr: address = %p, address = %p\n", arr, &arr); for (i = 0; i < row; i++) { printf("Row %d: address: %p, address = %p\n", i, arr[i], &arr[i]); for (j = 0; j < column; j++) { printf("(Row %d, Column %d): value = %d, address = %p\n", i, j, arr[i][j], &arr[i][j]); } } return 0; } 輸出如下: arr: address = 0x7fffac0e4490, address = 0x7fffac0e4490 Row 0: address: 0x7fffac0e4490, address = 0x7fffac0e4490 (Row 0, Column 0): value = 0, address = 0x7fffac0e4490 (Row 0, Column 1): value = 1, address = 0x7fffac0e4494 (Row 0, Column 2): value = 2, address = 0x7fffac0e4498 (Row 0, Column 3): value = 3, address = 0x7fffac0e449c (Row 0, Column 4): value = 4, address = 0x7fffac0e44a0 Row 1: address: 0x7fffac0e44a4, address = 0x7fffac0e44a4 (Row 1, Column 0): value = 10, address = 0x7fffac0e44a4 (Row 1, Column 1): value = 11, address = 0x7fffac0e44a8 (Row 1, Column 2): value = 12, address = 0x7fffac0e44ac (Row 1, Column 3): value = 13, address = 0x7fffac0e44b0 (Row 1, Column 4): value = 14, address = 0x7fffac0e44b4 Row 2: address: 0x7fffac0e44b8, address = 0x7fffac0e44b8 (Row 2, Column 0): value = 20, address = 0x7fffac0e44b8 (Row 2, Column 1): value = 21, address = 0x7fffac0e44bc (Row 2, Column 2): value = 22, address = 0x7fffac0e44c0 (Row 2, Column 3): value = 23, address = 0x7fffac0e44c4 (Row 2, Column 4): value = 24, address = 0x7fffac0e44c8 「arr」與「arr[]」分別是二維和一維陣列變數,「&arr」等價於「arr」,「&arr[]」等價於「arr[]」。

二級指標

若是用malloc()配置指標,可選用二級指標實現二維陣列。 #include <stdio.h> #include <stdlib.h> int main() { const int row = 3, column = 5; int **pptr = (int**)malloc(sizeof(int*) * row); int i, j; for (i = 0; i < row; i++) { pptr[i] = (int*)malloc(sizeof(int) * column); for (j = 0; j < column; j++) { pptr[i][j] = (10 * i) + j; } } // Show. printf("pptr: value = %p, address = %p\n", pptr, &pptr); for (i = 0; i < row; i++) { printf("Row %d: value: %p, address = %p\n", i, pptr[i], &pptr[i]); for (j = 0; j < column; j++) { printf("(Row %d, Column %d): value = %d, address = %p\n", i, j, pptr[i][j], &pptr[i][j]); } } //// Show as a pointer. //for (i = 0; i < row; i++) { // printf("Row %d: value: %p, address = %p\n", i, *(pptr + i), pptr + i); // for (j = 0; j < column; j++) { // printf("(Row %d, Column %d): value = %d, address = %p\n", i, j, *(*(pptr + i) + j), *(pptr + i) + j); // } //} return 0; } 輸出如下: pptr: value = 0x55640558c2a0, address = 0x7fffd8e91810 Row 0: value: 0x55640558c2c0, address = 0x55640558c2a0 (Row 0, Column 0): value = 0, address = 0x55640558c2c0 (Row 0, Column 1): value = 1, address = 0x55640558c2c4 (Row 0, Column 2): value = 2, address = 0x55640558c2c8 (Row 0, Column 3): value = 3, address = 0x55640558c2cc (Row 0, Column 4): value = 4, address = 0x55640558c2d0 Row 1: value: 0x55640558c2e0, address = 0x55640558c2a8 (Row 1, Column 0): value = 10, address = 0x55640558c2e0 (Row 1, Column 1): value = 11, address = 0x55640558c2e4 (Row 1, Column 2): value = 12, address = 0x55640558c2e8 (Row 1, Column 3): value = 13, address = 0x55640558c2ec (Row 1, Column 4): value = 14, address = 0x55640558c2f0 Row 2: value: 0x55640558c300, address = 0x55640558c2b0 (Row 2, Column 0): value = 20, address = 0x55640558c300 (Row 2, Column 1): value = 21, address = 0x55640558c304 (Row 2, Column 2): value = 22, address = 0x55640558c308 (Row 2, Column 3): value = 23, address = 0x55640558c30c (Row 2, Column 4): value = 24, address = 0x55640558c310 可觀察出,5個數的一維陣列,被分為3組,3組的位址是分開的,且比起直接使用arr[][]宣告陣列,多了3個位址(&pptr[0]、&pptr[1]、&pptr[2])分別去記錄每組的起始位址。

指向一維陣列的指標做二維陣列

宣告陣列arr[][]若要用指標形式實現,可使用指標指向int[]。 #include <stdio.h> #include <stdlib.h> int main() { const int row = 3, column = 5; int (*parr)[column] = (int(*)[column])malloc(sizeof(int) * column * row); int i, j; for (i = 0; i < row; i++) { parr[i] = (int*)malloc(sizeof(int) * column); for (j = 0; j < column; j++) { parr[i][j] = (10 * i) + j; } } // Show. printf("parr: value = %p, address = %p\n", parr, &parr); for (i = 0; i < row; i++) { printf("Row %d: value: %p, address = %p\n", i, parr[i], &parr[i]); for (j = 0; j < column; j++) { printf("(Row %d, Column %d): value = %d, address = %p\n", i, j, parr[i][j], &parr[i][j]); } } //// As a pointer to an array. //for (i = 0; i < row; i++) { // printf("Row %d: value: %p, address = %p\n", i, *(parr + i), parr + i); // for (j = 0; j < column; j++) { // printf("(Row %d, Column %d): value = %d, address = %p\n", i, j, *(parr[i] + j), parr[i] + j); // } //} return 0; } 輸出如下: parr: value = 0x555d6a0e92a0, address = 0x7ffc637cd9e0 Row 0: value: 0x555d6a0e92a0, address = 0x555d6a0e92a0 (Row 0, Column 0): value = 0, address = 0x555d6a0e92a0 (Row 0, Column 1): value = 1, address = 0x555d6a0e92a4 (Row 0, Column 2): value = 2, address = 0x555d6a0e92a8 (Row 0, Column 3): value = 3, address = 0x555d6a0e92ac (Row 0, Column 4): value = 4, address = 0x555d6a0e92b0 Row 1: value: 0x555d6a0e92b4, address = 0x555d6a0e92b4 (Row 1, Column 0): value = 10, address = 0x555d6a0e92b4 (Row 1, Column 1): value = 11, address = 0x555d6a0e92b8 (Row 1, Column 2): value = 12, address = 0x555d6a0e92bc (Row 1, Column 3): value = 13, address = 0x555d6a0e92c0 (Row 1, Column 4): value = 14, address = 0x555d6a0e92c4 Row 2: value: 0x555d6a0e92c8, address = 0x555d6a0e92c8 (Row 2, Column 0): value = 20, address = 0x555d6a0e92c8 (Row 2, Column 1): value = 21, address = 0x555d6a0e92cc (Row 2, Column 2): value = 22, address = 0x555d6a0e92d0 (Row 2, Column 3): value = 23, address = 0x555d6a0e92d4 (Row 2, Column 4): value = 24, address = 0x555d6a0e92d8 parr的作用,是一個指向arr[][],也可以這樣宣告。 const int row = 3, column = 5; int arr[row][column]; int (*parr)[column] = arr;

留言

這個網誌中的熱門文章

Python的10進制與16進制轉換

設定CPU的Cache模式:MTRR

ls -l 顯示出現亂碼