C語言復習---二維數組和二級指針的關系:沒關系,別瞎想(重點)


前提:一維數組和一維指針為什么可以替換使用?

    int a[3] = { 1, 2, 3 };
    int *p = a;
    for (int i = 0; i < 3; i++)
        printf("%d ", *(p + i));

上面測試表示可以相互替換使用

printf("%p %p, %p", a, &a[0],p);

a是數組名,在數組中代表了數組首地址,類似於&a[0]。
而int *p是一個int類型指針,也是指向每一個地址,所以兩者的類型相同,都是代表int類型字節地址。
int *p = a;是正確的。
我們再使用*(p+1),就是將指針P所指向的位置加上一個int類型字節(4),正好到達了a[1]的數據地址。所以這種使用方法是正確的。

一:二維數組的數組名代表了什么?

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

這里數組名,還是整個數組的首地址,也可以看做第一行的首地址,還可以看做第一行第一列元素的首地址
printf("%p %p %p\n", a, &a[0], &a[0][0]);

要是我們想要獲取每一行的地址呢?

其實我們上面就使用了&a[0]獲取了第1行的首地址
printf("%p %p\n",&a[1], &a[1][0]);  //測試第二行的地址

注意:

數組名a是一個地址,無論是幾維數組。都是數組的首地址

二:二級指針又代表了什么?

對於一級指針:

每次談到指針,想到的就是一個帶有門牌號的鑰匙,我們根據門牌號,才能找到對應的房間,才可以進去拿東西。

對於二級指針理解可以相同:

我們考慮,家里有個書房。書房要是在客廳。
那么我們現在人在外面,要回去去一本小黃書呵...
我們先要根據我們手中的要是找到房間號,開門進去,獲取到第二把鑰匙,查看標簽是書房的,我們就可以使用這把要是去開書房的門,獲取書籍來學習
我們可以看做:最靠近目標空間的那把鑰匙是一級指針,然后再遠一點的那把鑰匙就是二級指針,以此類推...就是多級指針了
就如同上面鑰匙和門牌號一樣,指針和地址也是密不可分的。指針變量中存放的就是地址
除了一級指針可以直接獲取到數據,其他級別的指針都是指向上一級指針的存儲地址。我們可以根據地址,一級一級直到獲取到一級指針就可以獲取到數據了,使用*就可以開門獲取數據了

*星號的理解

int* p;        //這是聲明了一個一級指針變量p,p是一個地址
*p;            //*p就是去這個地址中獲取數據



int **p        //這個P,也是一個指針變量,而且是一個二級,內部存放的也是一個地址
*p              //就是使用二級地址去獲取了其中內容(內容是一級指針的地址)
*(*p)         //*p先獲取了一級指針的地址,*(*p)就是根據一級指針地址去獲取數據

二:二級指針和二維數組的錯誤用法

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

或許你因為這只是一個警告而覺得無所謂。但是當你使用的時候,就會出現錯誤,崩潰

原因解析:

p是一個二級指針,p變量存放地址。a代表了數組的首地址。雖然間接級別不同,但是地址賦給地址,也沒有啥錯,所以只是警告

但是當我們試圖使用二級指針時:

num = *(*(p+0) + 0);
我們是想用*(p+0)獲取第一行的地址,然后使用*(*(p+0)+0)獲取第一行第一列的地址

但是會報錯

 

原因解析:

從上一個原因解析我們知道,是將a的地址賦給了二級指針p. 所以a=0x0028fce0 p=0x0028fce0 當我們使用*(p+0)==*p試圖去獲取一級指針地址時,結果發現地址0x0028fce0下存放的不是一個地址,而是1,
那么只能強制轉換1為地址0x00000001,所以*p=0x00000001。當我們再去嘗試訪問這塊地址時*(*(p+0)+0)==**p,這不是我們能訪問的,所以報錯

三:正確的使用指針和二維數組

(一)int(*p)[3] = a;

    int a[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
    int(*p)[3] = a;    //指針變量p指向包含3個整型元素的一維數組
    int num;
    printf("%p %p %p\n", p, p+1, p+2);
    num = *(*(p + 1) + 1);  //指向第二行第二個
    printf("%d\n", num);

指針變量p指向包含3個整型元素的一維數組,所以p的步長是其內部數據字節長度,所以p+1就是7B4-7A8=C===12就是含有3個整型元素的一維數組長度
int(*p)[3] = a;    
p+1==a[1]
p+2==a[2]

(二)int *p=a;//根據指針尋址是按照步長

int *p=a;將a的地址賦給p
而p是一個int* 指針,所以他的步長就是int類型4字節一步長。
因為數組在內存中的數據存儲時連續的,所以可以使用一級指針尋址獲取所有的數據
    int a[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
    int *p = a;
    for (int i = 0; i < 9;i++)
        printf("%d ", *p++);  //p就是一個地址,每次按照步長增加四

四:正確使用二級指針

    int **arr = (int **)malloc(n*sizeof(int*));
    for (int i = 0; i < n; i++)
    {
        arr[i] = (int *)malloc(n*sizeof(int));
        memset(arr[i], 0, n*sizeof(int));
    }

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
            printf("%2d", arr[i][j]);
        printf("\n");
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM