今天分析了C語言二維數組和指針的基本理解,感受有點懵。。。代碼記錄一下,若是有大神臨幸發現哪裏有誤,歡迎指正~~~數組
#include <stdio.h> #include <stdlib.h> #include <string.h> //void func(int p[][]) //這樣寫等同於void func(int **p) p++移動了四個字節,(*p)++移動了四個字節,不符合二維數組規律 //{ //} //列優先輸出的函數(即豎着輸出) void func(int p[][4], int a, int b) //這樣寫是正確的,這樣寫等同於void func(int (*p)[4]) p++移動16個字節,(*p)++移動了4個字節,a和b是爲了保持維度,a表示列,b表示行 { for (int i = 0; i < a; i++) { for (int j = 0; j < b; j++) { printf("%d\n", *(*(p + j) + i)); } } } int main() { int array[3][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } }; //printf("%d\n", sizeof(array[0])); // 結果爲16,媽的,array[0]居然不是指針,而是一個數組的名稱, //printf("%d\n", sizeof(array)); //結果48 func(array,sizeof(array[0]) / sizeof(int), sizeof(array) / sizeof(array[0]));//
第二個參數是列數,第三個參數爲行數 //array[0]並非一個變量,是二維數組中第0行的首地址
//和下面的: *(p + 0) + 1; 表明int *向後位移了一個位置 道理上應該是相同的。 //在二維數組中*array表明的也是數組的首地址,而一維數組中*array表明的是第一個元素的值 //printf("%d %d %d %d\n", array, *array, &array, &array[0][0], array[0]); //printf("%d\n", array + 1); //
printf("%d\n", array[0] + 1); //結果爲array + 1 移動了16個字節 // array[0] + 1 移動了4個字節 //能夠這樣理解,array + 1當作連長,array[0] + 1當作排長,連長每次走一行(即走4個數,14個字節),排長每次走一列(即走一個數,4個字節) //int *p = array; //指向一維數組的指針//int (*p)[4];
是一個變相的二級指針 //p = array; //*(p + 0) + 1; 表明int *向後位移了一個位置 //for (int i = 0; i < 4; i++) //{ // for (int j = 0; j < 3; j++) // { // printf("%d\n", *(*(p + j) + i)); // } //} //*(p + 0) 表明的是指向第一行的指針。因此*(p + 0) + 1 是指向第一行第二個元素的位置 //printf("---------------\n"); //----------- //p + 1; //表明的是排長,每次走一行 //p[0][0] = *(*(p + 0) + 0); //表明的是連長,每次走一個數 //printf("%d\n", *(*(p+1))); //第一行第0個元素 system("pause"); return 0; }
分析以下:函數
黃色代碼部分:輸出的地址徹底相同,因此二維數組和一維數組的一點區別是: 在二維數組中*array表明的也是數組的首地址,而一維數組中*array表明的是第一個元素的值 測試
紅色代碼部分: 相對於黃色代碼部分,紅色代碼結果爲: array + 1 移動了16個字節 , array[0] + 1 移動了4個字節;spa
由於array是數組的首地址,並且是一個二維數組,因此array+1 應該是移動一行,即4個數字,array[0]是二維數組的「第一行數組」的首地址,因此+1應該是在第一行數組裏面移動指針;指針
( 若是 int *p = &i; 那麼p+1的結果就會移動4個字節,若是 char *p = &i; 那麼p+1的結果就會移動1個字節, 這裏其實也是相同的道理,只是很差理解。。。)code
也可使用排長和連長的例子來理解,把array當作連長,把array[0]當作排長,連長每次審閱,會一行一行的走,排長審閱,則會一排一排的走,因此array(連長)每次走16個字節,array[0]每次走4個字節。blog
橘黃色代碼部分: 定義二級指針的時候,通常會這樣定義,int (*p)[4]; get
這裏有一個「指針數組」和「數組指針」的概念,圖示和代碼以下:string
指針數組: 數組指針it
int *p[5]; int (*P)[10];
#include <stdio.h> #include <stdlib.h> int main() { //指針數組 char *s[10]; //是一個數組,該數組中有10個char *指針,每一個指針指向一個字符 printf( "%d\n" ,sizeof (s[0])); //4 //數組指針 char (*s1)[10]; //是一個指針變量,該指針變量指向一個char[10];不能指向其餘任何char[n]數組 printf( "%d\n" , sizeof (s1)); //4 system( "pause" ); return 0; }
因此:int (*p)[4]; 是一個數組指針,指向一個4個元素的數組,
p = array; 也就是把二維數組的首地址賦給p,array也是一個地址(至關於一個指針,但若是咱們用sizeof(array)會發現其實不是一個指針),因此p實際上是一個變相的二級指針(你不信的話能夠利用**p測試看是否可以取到數組的第一個元素)
因此 *(p + 0) + 1; 表明int *向後位移了一個位置 也就不難理解了, p是一個二級指針, p+0表明的其實就是第一行數組的首地址。*(p+0) 仍是一個指針, 也就是一個int * 類型的變量(指針也是一個變量),*(p + 0) + 1;表明的就是int *向後位置了一個位置
*(p + 0) 表明的是指向第一行的指針。因此*(p + 0) + 1 是指向第一行第二個元素的位置的指針,*(*(p + 0) + 1 ) 就是第一行第二個元素的值;
灰色顏色代碼的部分: 這樣寫的緣由就是直接把二維數組的維度發過去,由於在接收端函數方是不知道二維數組的維度的,並且這樣寫之後更改數組的維度的時候,不用更改其餘代碼。