一維陣列傳參
二維陣列傳參
一級指標傳參
二級指標傳參
小引
在指標的學習階段,有不少同學都十分畏懼這個物什,甚至「談指標色變」。其實對指標的不理解,其實本質上是對記憶體的不理解,本篇部落格就從零開始、系統的來講解指標這個話題。
首先我們應該明確以下的一些基礎常識:
指標是乙個變數,用來存放位址,位址唯一標識一塊記憶體位址。
指標的大小是固定的4 或 8
個位元組。(32
或64
位平台)
指標是有型別的,指標的型別決定了指標加減整數運算的步長,以及指標解引用時的許可權。
顧名思義,就是指向字元變數的指標,指標內存放的內容是乙個字元。它的一般寫法如下:
int main()
如果此時對指向單個字元的使用方式簡單明瞭,但是相對於下面的這種常見的指向字串的使用方式,就相形見絀了。ptr
進行strlen
,就會記憶體訪問越界,屬於未定義行為,結果不可預期。因為指標指向的是乙個字元而不是字串。
int main()
這樣也可以間接的表現為指標指向了字串
。
**中char *ptr_1 = "this is a c string";
語句看似是將字串放入了指標內,但其本質是將這個字串的首位址存放到了指標內。
如果此時對請看**:ptr_1
進行strlen
,就會正確的列印出字串的個數,因為此時指標的指向不再是單個字元,而是字串。其實編譯器
無法識別
指標的指向是字元陣列 還是字串,所以它的指向需要使用者來定義保證。
int main()
它的本質是指標,指標的指向是乙個陣列
。它的定義如下:
int (*arr)[20];
因為【二維陣列也是乙個陣列指標】的優先順序高於
*
,而()
的優先順序高於。所以加上圓括號
()
改變優先順序順序。(不加圓括號的情況下面會提及)先進行括號
( )
內的操作,這裡變數名arr
與*
結合就明確了他是乙個指標變數
,括號操作符完成再與其他元素進行結合,它指向了乙個大小為10個整型元素的陣列。
請看如下**:
int main()
;printf
("%p\n"
, arr)
;printf
("%p\n"
,&arr)
;return0;
}
執行結果為:
二者輸出內容相同,這就說明陣列名
和& 陣列名
是等價的嗎?其實不然,請看如下**:
int main()
;printf
("arr = %p\n"
, arr)
;printf
("&arr = %p\n"
,&arr)
;printf
("arr+1 = %p\n"
, arr+1)
;printf
("&arr+1 = %p\n"
,&arr+1)
;return0;
}
執行結果為:
這裡對陣列名 + 1
和& 陣列名 + 1
操作發現二者出現了區別,說明它們有著本質上的差別。
arr
指向陣列首元素,&arr
是陣列指標,指向陣列,二者指向的位址是相同的但型別不同。
arr + 1
是指向陣列首元素之後乙個元素的指標。
而&arr + 1
是指向下乙個陣列,跨過了整個陣列,步距為陣列元素的大小之和。
與陣列指標相混淆的有另乙個名詞:指標陣列
。
int *p1[10];
它的本質是陣列,陣列中的所有元素都是指標
。
【二級指標也是乙個指標陣列】
int *arr1[10]
;//整型指標的陣列
char *arr2[4]
;//一級字元指標的陣列
char **arr3[5]
;//二級字元指標的陣列
具體舉例:
const char *arr=
;
對於陣列:
int arr[10] = ;
使用以下函式進行傳參:
// 情況 1
void
test
(int arr[
])
// 情況 2
void
test
(int arr[10]
)
// 情況 3
void
test
(int *arr)
所以以上三種方法都是正確的,內涵也是相同的,讀者使用時可以根據具體情況選擇不同的表現形式,提高**可讀性。對於陣列:
int *arr2[20] = ;
使用以下函式進行傳參:
// 情況一
void
test2
(int *arr[20]
)
// 情況二
void
test2
(int **arr)
所以指標陣列可以當做二級指標來傳參。
對於陣列:
int arr[3][5] = ;
使用以下函式進行傳參:
// 情況 1
void
test
(int arr[3]
[5])
// 情況 2
void
test
(int arr[
])
// 情況 3
void
test
(int arr[5])
【小結】:
二維陣列傳參,函式形參只能省略第乙個的數字,第二個[ ]中的數字不可省略。
對乙個二維陣列,可以不知道有多少行,但是必須知道一行多少元素。
// 情況一
void
test
(int
(*arr)[5
])
// 情況二
void
test
(int* arr[5]
)
// 情況三
void
test
(int *arr)
// 情況四
void
test
(int **arr)
【小結】:二維陣列可以作為 陣列指標 傳參。
常見的傳參方式如下:
void
print
(int *p, int sz)
}int main()
; int *p = arr;
int sz =
sizeof
(arr)
/sizeof
(arr[0]
);print
(p,sz)
;//一級指標p,傳給函式print
return0;
}
q:那麼當乙個函式的引數部分為一級指標的時候(例如int *
),函式能接收什麼引數?
int*
型別的一級整型指標
陣列元素型別為int
的一維陣列
常見的傳參方式如下:
void
test
(int** ptr)
int main()
q:當函式的引數是二級指標時(例如int **
),可以接收什麼引數?
二級指標
指標陣列
指標陣列 陣列指標 陣列傳參
指標陣列 實際上是乙個陣列,陣列中存放的元素是指標 例如 int arr 10 char arr1 5 陣列指標 實際上是乙個指標,指向乙個陣列的指標 例如 int p 10 這就表示乙個p指標,指向乙個大小為10陣列 在陣列傳參的過程中,由於c語言的對於速度的要求的特點,是不會傳整個陣列的,最終陣...
指標陣列陣列傳參 指標引用傳參
指標和陣列作為引數傳入函式時,傳入的是位址,即指向變數的位址和陣列的首位址,可以在函式中改變指標或陣列的值,但本質上它們還是值的傳遞 區別於變數的值傳遞的是 變數值傳遞不會改變實參原來的值。我們無法對指標和陣列的位址進行操作 如 位址賦值,分配記憶體等 要進行位址操作需要使用指標引用或指標的指標。示...
陣列和指標傳參
在我們寫函式時,有沒有被引數型別難到呢?如果有,那就耐心看完本篇部落格吧 一維陣列傳參 二維陣列傳參 總結 陣列傳參時,降級為其內部元素型別的指標,二維陣列傳參,函式的引數只可以省略第乙個 的數字,因為對二維陣列,可以不知道有多少行元素,但必須知道一行有多少元素。引申為,多維陣列傳參,只有第乙個 的...