C語言指標的理解五 二重指標與二維陣列

2021-10-20 20:22:54 字數 4748 閱讀 3613

2.二維陣列

本質上來說,二重指標和一重指標的本質都是指標變數,占用相同的記憶體空間,而指標變數的本質就是變數。

二重指標本質上也是指標變數,和普通指標的差別就是它指向的變數型別必須是個一重指標。二重指標其實也是一種資料型別,編譯器在編譯時會根據二重指標的資料型別來做靜態型別檢查,一旦發現運算時資料型別不匹配編譯器就會報錯。

c語言其實是可以沒有二重指標的。一重指標完全可以做二重指標做的事情,之所以要發明二重指標(以及函式指標、陣列指標),之所以要區分這些指標,就是為了讓編譯器了解這個指標被定義時,定義它的程式設計師希望這個指標被用來指向什麼東西,定義指標時用資料型別來標記,比如int *p就表示p要指向int型資料。編譯器知道指標型別之後可以幫我們做靜態型別檢查,這種靜態型別檢查可以輔助程式設計師發現一些隱含性的程式設計錯誤,這是c語言給程式設計師提供的一種編譯時的查錯機制。

int

main

(int argc,

char

**ar**)

int

main

(int argc,

char

**ar**)

;//p1是指標陣列,即內部元素都是一重指標的陣列

int*

* p2 = p1;

//p1作右值的時候是二重指標

return0;

}

對於指標陣列p1,做右值的時候它是陣列首元素的位址,也就是說它指向陣列首元素,而這是乙個指標陣列,陣列首元素就是乙個一重指標,所以p1是乙個指向一重指標的指標,也就是二重指標,所以可以直接做右值賦值給p2

實際應用中二重指標用的比較少,大部分時候就是和指標陣列糾結起來用的。有時在函式傳參時為了通過函式內部改變外部的乙個指標變數,會傳這個指標變數的位址,也就是二重指標進去。

首先還是要明確:二重指標、陣列指標、結構體指標、一重指標、普通變數,這些的本質都是相同的,它們都是變數,和一段記憶體空間繫結,空間內會存入資料。

所有的指標變數本質也都是相同的,64位機器中都是8個位元組,用來指向別的變數,不同型別的指標變數只是可以指向的,或者說編譯器允許指向的變數型別不同。

二重指標大部分情況下就是用來指向指標陣列的。

一維陣列在記憶體中是連續分布的多個記憶體單元組成的,而二維陣列在記憶體中實際上也是由連續分布的多個記憶體單元組成的。從記憶體角度來看,一維陣列和二維陣列沒有本質差別。二維陣列int a[2][3]和一維陣列int b[6]在記憶體中的儲存方式其實沒有任何本質差別。

舉個栗子:

#include

intmain

(int argc,

char

**ar**)

;int a[2]

[3];

for(

int i=

0;i<6;

++i)

printf

("%p "

,&b[i]);

printf

("\n");

for(

int i=

0;i<2;

++i)

for(

int j=

0;j<3;

++j)

printf

("%p "

,&a[i]

[j])

;printf

("\n");

return0;

}

輸出:

0x7ffe4a7f1ad0 0x7ffe4a7f1ad4 0x7ffe4a7f1ad8 0x7ffe4a7f1adc 0x7ffe4a7f1ae0 0x7ffe4a7f1ae4 

0x7ffe4a7f1af0 0x7ffe4a7f1af4 0x7ffe4a7f1af8 0x7ffe4a7f1afc 0x7ffe4a7f1b00 0x7ffe4a7f1b04

既然二維陣列都可以用一維陣列來表示,那二維陣列存在的意義和價值在**?二維陣列a和一維陣列b在記憶體訪問效率上是完全一樣的,或者說差異是忽略不計的。在某種情況下用二維陣列而不用一維陣列,原因在於二維陣列好理解,**好寫而且利於組織。

總結:使用c語言提供二維陣列並不是必須的,而是一種簡化程式設計的方式。其實一維陣列的出現其實也不是必然的,也是為了簡化程式設計。

二維陣列int a[2][3]中,2是第一維,3是第二維。結合記憶體映像來理解二維陣列的第一維和第二維的意義:首先第一維是最外面一層的陣列,所以int a[2][3]這個陣列有2個元素,其中每乙個元素又是乙個含有3個元素的一維陣列,這個陣列就是第二維。

總結:

一維陣列有陣列下標和指標偏移運算兩種訪問方式,以int b[6]為例:

int

*p = b;。b[0

]=5;//b[0]等同於 *(p+0); b[9

]=6;

//b[9]等同於 *(p+9); b[i] 等同於 *(p+i)

二維陣列同樣有兩種訪問方式,以int a[2][3]為例:

int

(*p)[3

];p= a;a[0

][0]

=3;//a[0][0]等同於*(*(p+0)+0); a[1

][4]

=3;//a[1][4]等同於*(*(p+1)+4); a[i][j]等同於 *(*(p+i)+j)

int a[2][3]是乙個二維陣列,其實它內部也是兩個元素,只不過這兩個元素也是陣列,而陣列名a是指向第乙個元素:乙個大小為3的int型陣列的,所以a的型別是乙個陣列指標,它首先是乙個指標,指向乙個大小為3的int型陣列,根據之前 [c語言指標的理解二:指標與陣列、陣列指標與指標陣列] 中陣列指標的定義和理解方法,就可以得到陣列指標p的定義語法為:int (*p)[3];

最常用情況:一維陣列用來表示乙個線性表,二維陣列用來表示一張單通道灰度影象,三維陣列可以表示三通道的rgb影象等。四維陣列也是可以存在的,在數學上有意義,現實空間中沒有對應,因為人類生存的宇宙是三維的。

總結:一般常用最多就到三維陣列,四維陣列除了做一些特殊與數**算有關的之外基本用不到。

1.指標指向二維陣列的陣列名:二維陣列的陣列名表示二維陣列的第一維陣列中首元素,也就是第二維的數的首位址。二維陣列的陣列名a等同於&a[0],這個和一維陣列的符號含義是相符的,用陣列指標來指向二維陣列的陣列名是型別匹配的,通過該指標可以訪問整個二維陣列元素。

#include

intmain

(int argc,

char

**ar**),}

;int

(*p)[3

]= a;

for(

int i=

0;i<2;

++i)

return0;

}

輸出:

1 2 3

4 5 6

2.指標指向二維陣列的第一維:前面的分析可以知道,第一維就是乙個陣列,例如a[0]實際上就是a[1]實際上就是所以可以直接用int *p來指向二維陣列第一維的各個元素a[i],通過該指標僅能訪問二維陣列的某一行元素。

#include

intmain

(int argc,

char

**ar**),}

;int

*p1 = a[0]

;int

* p2 = a[1]

;for

(int i=

0;i<3;

++i)

printf

("%d "

,p1[i]);

printf

("\n");

for(

int i=

0;i<3;

++i)

printf

("%d "

,p2[i]);

printf

("\n");

return0;

}

輸出:

1 2 3

4 5 6

3.指標指向二維陣列的第二維:二維陣列的第二維元素其實就是普通變數了,例如a[1][1]其實就是int型別的4,已經不能用指標型別和它相互賦值了。除非int *p = &a[i][j];,類似於指標指向普通int型變數。

理解二維陣列和指標的關鍵就是2點:

c語言中的一重指標和二重指標的理解

1 前言 1 指標變數如同int變數一樣,在函式中,儲存在棧區,此時為區域性變數。其標誌是 可以理解為其型別是個 2 不論指標變數指向的是何種變數,對於指標變數來說所佔位元組都是一樣的,例如 int p 和double q,p和q都是佔4個位元組,不同的是,p 和q 前者挪動了4個位元組,後者挪動了...

C語言之函式指標和二重函式指標

在分析uboot程式時發現乙個函式指標的用法,花了點時間研究一下。做個記錄。先說一下函式指標的基本用法。如下 int init01 void typedef int init func1 void 宣告一種函式型別 typedef int init func2 void 宣告一種函式指標型別 int...

C語言指標用法詳解 (三) 二重指標

二重指標 int ptr1 null cout 1 三省指標 指標 ptr1 的型別是 int 指向的型別 int 指定為空 2 ptr1 是 ptr 指向的指向 即空的指向,非法 3 ptr1 是 ptr 指向的指向的指向 即空的指向的指向,非法 1 三省指標 指標 p 的型別是 int 指向的型...