关于一维数组和二位数组的数组指针
生活随笔
收集整理的這篇文章主要介紹了
关于一维数组和二位数组的数组指针
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 一維數組
?????????? c語言中, 數組占用的空間是一組連續的物理內存空間.
?????????? 所以對于1維數組來講,只需要知道數組頭1個元素的地址, 就可以逐個地得出各個元素的值了.
例子:
????????? 首先定義1個1維數字型數組, 并且賦值.
????????? int A[10]={10,1,2,3,4,5,6,7,8,9};
????????? 這里說明一下, c語言中大部分情況下如上面這個語句這樣, 定義1個數組的同時就對它賦值了, 這是最方便的.
????????? 也可以先定義再賦值.
????????? 如
????????? int A[10];???????? A[0]=10; A[1]=2;........
????????? 但是不能用A={10,1,2,3,4,5,6,7,8,9}; 會編譯失敗~
????????? 跟住定義1個指針.
????????? int *p;
????????? 這時這個指針p只是1個空指針, 所以下一步就是給這個指針賦值.
??????? p=A;??????????? //意思就是將數組A的頭部地址賦值給指針p
????????? 注意 : 對于一般的變量, 要把它的地址賦值給指針,必須使用尋址符"&", 例如p=&a, 但是對于數組變量來講, 是不需要尋址符的, 直接p=A就ok了.
???????? 原因是A這個數組名字本身是1個指針. 它指向數組A第1個元素A[0]的地址, 下面會詳細講解的啦~
???????? 這時指針p的值是A的頭1個元素的地址.
???????? printf("A[0] is %d\n", *p);?? //這時去訪問p指針指向的值, 就是指向數組A的第1個元素啊, 所以就是A[0], *p==10了
???????? 如果想訪問下1個元素的值A[1],? 則指針必須指向一下元素的地址:
???????? p+=1;????? //意思并不是指針的值加1, 而是指指針所指向的地址指向下數組1個元素的地址.同理p+i, 就是指向下i個元素的地址了.
??????????????????????? //實際上, 假如p是1個指針, 那么p+i 等價與p+ (i 乘以 p所指向元素的字節長度)
?????? 這時再對指針p取值, 就得到A[1]的地值了.
???????? printf("A[1] is %d\n", *p); //同理再執行p+1;, 就得到A[2]的地址...... 一直類推
???????? 這時要返回具體某個元素的地址, 則先執行
???????? p=A;? //重置p的地址指向A第1個元素.
?????? p=p+i-1;??? //指向數組A第i個元素A[i]
?????
?????? 或者執行p=&A[i] ,因為用取址符號能將數字型變量的地址取出來, 這時p存放的同樣是A[i]的地址. ?????
? ? ? ?? 而不能直接p=A[i] 因為A[i]已經是1個數字型變量了.
?????? 如果當p指向數組A最后1個地址時, 例如p當前的值已經是&A[9], 如果再執行p+1, 那么p繼續會已相同幅度指向下1個內存地址, 但是那個地址是不屬于數組A的, 要注意啊.
???????? 寫了1個小測試函數:
?
執行結果如下:
? ?
?
?其實, 好明顯可以看出只要給p賦值,如上圖紅色框框
?p=A;? ??
要獲取任何1個元素A[i]的值,
只要取值*(p+i)就ok
也就是
*(p+i) = A[i]
這個特性會在下面二維數組上講解的更加深刻
2. 二維數組
?????? 二維數組跟1維數組小許區別, 指針的用法也是不同的.
?????? 其實二維數組也可以看成1個特殊的一維數組. 只不過1一般的一位數組里面的元素是數字,或者字符串...等一般的類型值. 而這個特殊的一維數組里面的元素是若干個長度相當的一維數組.
?
?????? 也就是說二維數組是1個由相同長度的若干個一維數組組成的數組.
????? 例如1個2維數組B[3][4] 可以看成是由如下3個長度為4的一維數組組成.
?????? B0[0]??? B0[1]?? B0[2]?? B0[3]?????????????????????????????????????? //1維數組B0
?????? B1[0]??? B1[1]?? B1[2]?? B1[3]?????????????????????????????????????? //1維數組B1
?????? B2[0]??? B2[1]?? B2[2]?? B2[3]????????????????????????????????????? //1為數組B2
2.1 一般的指針
也做個例子:
????? 首先定義1個二位數組并賦值:
????? int B[3][4] = {{ 0, 1, 2, 3},
??? ??? ????????????????? {10,11,12,13},
??? ??? ????????????????? {20,21,22,23}};
???
???? 跟住定義1個指針:
? ?? int *p2;
? ?? 同樣,將指針指向整個數組的第1個元素的地址.
? ? ? p2=B[0];? //或者p2=&B[0][0]
===================================================================================================
? ? 這里有點奇怪, 為何不像之前一位數組那樣直接用B來賦值給指針(p2=B;), 而用B[0]呢?
?? 下面解析一下:
?? a1)???? 對于一維數組A[4]來講, 有4個元素, 他們分別是A[0],A[1],A[2],A[3], 數組每1個元素都存放著對應的值.
?? a1-1)? 對于二位數組B[3][4]來講, 我們可以將它看成1個特殊的1維數組, 這個數組有3個元素, 他們分別是 B[0],B[1],B[2].? 這3個元素分別是3個長度為4的子1維數組 .
??? a2-2) 對于每1個子數組B[x]來講, 它包含4個元素, 分別是B[x][0],B[x][1],B[x][2],B[x][3], 同樣, 這個4個孫元素都存放這對應的值.
??? a2-3) 但是! 對于父數組B來講, 他說包含的3個數組,只是存放了3個子數組的頭部地址. 并不是這3個子數組的值啊.?
??? b1)? 所以對于一維數組A來講, p=A; 指針p就指向A的首個元素的地址, 也就是A[0]地址啊. 對p進行取值*p 就是后A[0]的值了.
?????????? A的頭部地址p 取值后*p與A[0]是等價的
??? b2)? 對于二維數組B來講, p=B;指針p同樣就是指向B的首個元素的地址, 也就是B[0]的地址. 而B[0]的值并不是第1個元素B[0][0]的值, 而是B[0]這個子1維數組的首個元素的地址, 也就是B[0][0]的地址.
??????????
?? 也就是說p=B; 的話 ===> *p=B[0]?? 而*B[0]才是和B[0][0]等價的
?? 所以二位數組, 指針p想獲得第1個元素的地址的話, 要執行
?? P=B[0],? 這樣*p==*B[0]==B[0][0]
? 但是個人親測, 在64位linux系統上, 用P=B; 語句(B是二維數組), 一樣可以獲得B[0][0]的地址, 不過在編譯時會有如下的警告信息.
===================================================================================================
獲得二維數組首個元素地址后,就可以取得對應元素的值了.
printf("B[0][0] is %d\n", *p2);
獲得下1個元素的地址, 就是B[0][1]的地址
p++;
獲得下B[1][2]的地址,當前就地址是B[0][1], 對于B[i][j]來講, 則i+1, j+1,而這個二維數組有4個列, 則j+4相當于i+1,所以:
p+=1*4+1;? //p+=5;
下面以這個例子編寫了1個函數:
?
執行結果如下圖:
2.2 用二維數組名作地址表示數組元素
??????? 對于2維數組B[3][4]來講, 數組名字B其實算是1個指針,? 它指向了子一維數組B[0]的地址, 也就是說*B 與B[0]是等價的, 都是1個地址,指向元素B[0][0]的地址.
? ? ? ? B---->? B[0] ----->B[0][0]
? ? ? ? 既然B是1個指針, 指向B[0]的地址,? 那么指針(B+1) 就指向B[1]的地址了, *(B+1) !!注意不是*B+1哦, 與B[1]是等價的 ,都是指向元素B[0][1] 的地址.
?????? 也就是說,? (B+i )是1個行數組指針, 指向 子一維數組B[i]的地址,? 每當這個指針+1, 那么它就指向下1個子一維數組.?
?????? 而*(B+i) 就是B[i]的值的了. 而B[i]的值仍然是1個地址, 指向B[i][0]的地址, 所以*(B+i) 與 B[i]一樣 仍然是1個指針啊. 它指向B[i][0].
??????? (B+i) --> B[i] -->B[i][0];???
?????????????????? *(B+i)
?????? 也可以容易看出, 既然B[i] 是1個指針, 那么B[i]也可與進行指針移動運算, 即B[i]+j 也是1個指針, 它指向B[i][j]的地址.
?????? 即:
?????? B[i]+j --> B[i][j]
??????? 而上面提過 B[i] 就是 *(B+i)啊
?????? so:
?????? *(B+i)+j --> B[i][j]?
???????? 也就是說? *(B+1)+j 是1個指針, 它指向二位數組B的1個具體元素B[i][j]的地址
???????? 所以對這個指針取值*(*(B+1)+j) (也就是 *(B[i]+j)? 因為*(B+i) == B[i]嘛),???? 就是元素B[i][j]
???????? 亦即系講加如我們想獲取二位數組B里面的1個具體的元素B[i][j]的值, 只需要利用指針*(B+i)+j 就ok啦.
下面就是例子:
??????? 首先定義1個二位數組并賦值:
???? ? ?? int B[3][4] = {{ 0, 1, 2, 3},
??? ??? ????????????????? {10,11,12,13},
??? ??? ????????????????? {20,21,22,23}};
??????????????
????????? 跟住定義1個指針:
? ?????? int *p3;
?????????? 這時我們想獲取B[1][2]的值, 只需要給指針p3 賦值成 指針*(B+1)+2
?????????? p3 = *(B+1)+2
?????????
?????????? 接下來就很方便地獲取B[1][2]的值啦~
?????????? printf("B[1][2] is %d\n", *p3);???? //B[1][2] = 12
????????? 這時我們又想獲取B[2][1]的值, 只需要給指針p3 賦值成 指針*(B+2)+1
???????? ?? p3 = *(B+2)+1
?????????? printf("B[2][1] is %d\n", *p3);
? ? ? ?? 感覺很方便啦, 避免了無謂的行列換算啦. ????
也寫了1個函數:
??????????
?
執行結果:
?
??
2.3? 行數組指針.
?????? 上面已經提過,對于二維數組B來講,? 數組名(B+i)是1個指針, 但是(B+i)指向的B[i](也就是*(B+i))? 也是1個指針.???
???????? 而當你定義1個普通指針p時, p指向的*p 一般是一個值
???????? 也就是說指針(B+i) 與 普通指針p 所指向的對象性質不同, 1個是指針, 而另1個是值.
????????? 也可以說它們是兩個級別不同的指針.
????????? 所以說一般我們定義1個指針p 后.
???????? 不能直接用(B+i) 給p賦值
???????? 例如:
???????? p=B;??? //B是個二位數組,??? 如果B是1維數組的話 p=B;似乎正確的, 因為他們是同級別的指針.
???????? p=(B+1);
??????? 都是錯誤的.
????? ======================================================================================
????? 而有一種指針, 它的的級別比一般的指針高一級.? 這就是行數組指針.
?????
?????? 定義1個行數組指針:
?????? int (*p)[4];?? // []里面是4啊
??? ********************************************************************************************
?????? 特別說明:
????????? 這里的int (*p)[4],? 并不是這個行數組指針有4個元素, 這個4代表的是行數組指針p指向的行數組(也就是B的子一維數組里有4個元素)
?????????? 也就是說這個行指針數組p 是專門for有4個列的二位數組的指針
??????????? 如果有個二維數組B[3][5],?? 則對應定義的行指針數組為? int (*p)[5]
??????????? 就如一維數組的指針*p 一樣,? 這個(*p)[4] 不是1個數組, 而是1個指針 而這個指針是指向二位數組B的1個子一維數組的.
?
?
?? ********************************************************************************************
???
?????? 所以這個高一級別的指針p 跟二位數組B 名字指針是同級別的/
?????? 也就是說可以直接用B對其賦值.
??????? p=B; ?? 是正確的.
?
??????? 那么:
??????? p==B???????????????? -->?? *B ? ? ? ? == B[0]
????? *p??????????????? -->?? *B[0] == B[0][0]
????? *(*p)== *(*(p+0))?????? == *p[0]?????? == B[0][0]???? // *(p+i) = p[i] 見文2.2節
???? ? ? ? ? ? ? ?? *(*(p+0) +1)? == *(p[0]+1) == B[0][1]
? ???
????? p+1 = B+1?? --> ? ? *(B+1) == B[1]???????????????? //同上 見此文2.2 節
????? *(p+1)????? -->???? *B[1]???????? == B[1][0]?
????? *(*(p+1))???? ==??? *p[1]??????? == B[1][0]
????? *(*(p+1)+1)? ==??? *(p[1]+1)? == ? B[1][1]
????
???? 通用化:
????? p+i???????????? == B+i????????????? -->?? *(B+i)??? ? ? ? ? ? ? ? ? ? ? ==? B[i]
????? *(p+i) ? ? ?? == *(B+i)???????? -->? *B[i]?????????????????????????? ==? B[i][0]?
????? *(*(p+i))?? == *(*(B+i)) ? ? ==? *p[i]??????? == ?? *B[i]????? ==? B[i][0]
??? ? *(*(p+i)+j) == *(*(B+i)+j)? == ?? *(p[i]+j) == ? *(B[i]+j) == B[i][j]
????? 由上面紅色語句得出
?????
???? *(p+i)+j? == *(B+i)+j --> B[i][j]
???? 就是1個指向 1個具體元素B[i][j] 的指針
????
???? 而 *(B+i)+j 就是2.2 節那個以行數組名作的指針嗎?
???? 而且可以看出p 與 B是等價的?? (p=B;)嘛
???? 沒錯,? 二位數組B的名字B 本身就是i個行數組指針...
????
???? 艸.? 我承認自己也很難理解,? 我快吐血了!
?? 總之就是:
????? p[i]--> B[i][0]
????? p[i]+j --> B[i][j]
???? 所以:? *(p[i]+j) = B[i][j]????????????????? //注意這里的P是1個行數組指針啊
下面又是一個例子:
??????? 首先定義1個二位數組并賦值:
???? ? ?? int B[3][4] = {{ 0, 1, 2, 3},
??? ??? ????????????????? {10,11,12,13},
??? ??? ????????????????? {20,21,22,23}};
跟住定義1個行數組指針:
? ?????? int (*p4)[3];?? //p4是1個指針名字啦,數字4毫無其他意義 注意不要寫成 int *p4[3]啊
直接用數組名字給指針賦值, 就如一維數組一樣:
???????? p4=B;
接下來就很方便地獲取B[1][2]的值啦~
?????????? printf("B[1][2] is %d\n", *(p4[1]+2);???? //B[1][2] = 12
這時我們又想獲取B[2][1]的值,
???????? ???printf("B[2][1] is %d\n", *(p4[2]+1);?? //B[2][1] = 21
國際慣例又寫了1個函數如下:
執行結果:
2.4 指針數組
???? 上面2.2 2.3 節講的實質上都是行數組指針,?? 但是c 還有一種叫指針數組的數組, 可以用于二維數組,? 真的要吐了!
???? 假如有個二維數組B[3][4]
???? 定義1個指針數組:
???? int *p[3]?? //注意跟 行數組指針 int(*p)[3]的區別? 定義的語句只差1個括號, 意義就大大不同了.
???? 這就定義了1個指針數組了,?? 它是1個數組, 成員是3個指針(p[0],p[1],p[2]), 他們可以分別用于指向二維數組B的3個子一維數組.
?
???? p=B;?? 這個賦值是錯誤的, 因為p是1個指針數組, 而數組名B是1個行數組指針啊, 完全不同性質的對象.
???? p[0] = B[0];??
???? 那么p[0] 就指向了B[0]這個子一維數組的首元素地址(B[0][0])
???? 所以
???? *p[0] = *B[0] = B[0][0];
???? *(p[0]+1) = *(B[0]+1) = B[0][1];
???? 也就是:
????? *(p[i]+j) = *(B[i]+j) = B[i][j];
????????? p[i]+j --> B[i][j]
???? 又吐一口, 這不是跟行指針數組一樣嗎?
????
========================================================================================
??? 而因為我們上面剛剛對指針數組p執行了賦值 令
???? p[i] = B[i];??? //i=0
???? 首先p[i] 是1個指針, 而B[0]是1個子一維數組,實際上也是1個指針, 它指向B[i][0]的地址
???? 也就是說對于數組指針p來講:
???? p[i]是1個實質上的對象, 他是p數組的1個成員. 他是1個指針
???? 而對于行數組指針P來講,
???? 當執行P=B;時
???? 得P+i == B+i? ==>?? *(P+i) = *(B+i)
???? 因為對于行指針數組(B+i)來講
???? (B+i)--> B[i](子一維數組)的地址??? 所以*(B+i)== B[i]的
??? 而又因為p與B是等價的,都是行數組指針
??? 所以 *(P+i)== P[i]
??? 也就是說 P[i] 其實就是 B[i], 也是1個子一維數組,也是1個指針, 指向B[i][0]的地址,
??? 又因為 p[i] = B[i]; //見前15行
?? 所以
?? P[i]? = p[i]
?? 也即是說 對于行數組指針p 和 指針數組P來講,
?? 雖然它么你的定義方法不同,
?? 但是他們的p[i](P[i])是等價的.
??? 對于指針數組p來講 p[i] 數組p內的一個元素,是1個普通指針.
???? 而對于行指針數組P來將, P[i] 是通過對行數組指針P+i 執行*(P+i) 取值得出的.也就是P+i 指向地址的內容. 也就是B[i]啦, 而B[i]是1個數組名(子一維數組B[i], 也相當與1個普通指針啦) 所以B[i]與P[i]與p[i]都是等價的. 前提是已經賦值P=B; p[i]=B[i];哦
?
?
???
=======================================================================
????
最后也寫了1個函數
執行結果:
?
?
???
總結
以上是生活随笔為你收集整理的关于一维数组和二位数组的数组指针的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux GDB 简单用法以及例子
- 下一篇: C 语言里的字符串---字符数组