[英]Pointer arithmetic and 2-D array in c?
我是C的新手並且堅持“如何將多維數組傳遞給函數”。 我知道你必須傳遞列大小,這樣如果你想從a[0][0]
到a[1][0]
它可以計算一維數組的大小,並可以跳過它。
我寫了一個小程序:
#include<stdio.h>
void foo(char[][2]);
int main()
{
char arr[2][2] = {'a','b','c','d'};
foo(arr);
return 0;
}
void foo(char temp[][2])
{
temp++;
printf("%c",*temp);
}
我期望這段代碼會打印字母c
,因為temp
最初指向'a'
,一旦我們遞增它,它將跳過第一個1-d數組並轉到第二個1-d數組的第一個元素'c'
。 但是我認為這種方式不起作用。
請解釋編譯器如何計算這些地址。
指針算術很好。 你忘了取消引用*temp
,它有char[2]
類型。
將其更改為**temp
,您將獲得輸出c
。
對於函數參數char temp[][2]
, temp
衰減為指針。 但僅限於第一(外)維度。 所以它實際上是一個指向char
數組[2]
的指針 。
正如您已經假設的那樣,遞增指針將使其前進到下一個外部索引。
因此,您必須使用(*temp)[0]
或**temp
來獲取第一個元素。 **temp
有效,因為*temp
是一個數組本身,所以它衰減到指向內部數組的第一個元素的指針。 第二個(左) *
然后取消引用這個指針: c
。
請注意,雖然它使用與char **temp
相同的語法,但它們根本不同。 指針不是一個數組,在這里,遞增temp
只會前進一個指針的大小,這不是你想要的。
請注意,初始化程序最好是根據2維性質:
{ { 'a', 'b' } , { 'c', 'd' } }
這可以確保您獲得內部數組的正確值,這是一種很好的做法。 省略非嵌套表單中的值將導致內部數組的序列錯誤。 當至少啟用了推薦警告( -Wall
) 時 ,gcc會警告缺少大括號。
除了當它是的操作數sizeof
或一元&
操作員,或者是一個字符串被用來初始化一個聲明另一個數組,類型“的N元件陣列的表達 T
將被轉換(“衰變”)”,以“指向T
指針”類型的表達式,表達式的值將是數組中第一個元素的地址。
在main
,函數調用foo(arr)
中的表達式arr
的類型是“2元素數組char
的2元素數組”; 因為它不是sizeof
或一元&
運算符的操作數,所以它“衰變”為類型為“指向2元素char
數組的指針”或char (*)[2]
的表達式。
因此,參數temp
是char (*)[2]
,它指向arr
的第一個元素。 參數聲明char temp[][2]
等同於char (*temp)[2]
。 表達式*temp
等同於temp[0]
,並且都具有類型“ char
2元素數組”( char [2]
)。 表達式temp + 1
為您提供下一個2元素char
數組的地址,因此*(temp + 1)
等效於temp[1]
。
這是一個總結所有這些的表格:
Expression Type Decays To Value
---------- ---- --------- -----
arr char [2][2] char (*)[2] &arr[0][0]
*arr char [2] char * arr[0]
&arr char (*)[2][2] n/a &arr[0][0]
arr[i] char [2] char * &arr[i][0]
*arr[i] char n/a arr[i][0]
&arr[i] char (*)[2] n/a &arr[i][0]
arr[i][j] char n/a arr[i][j]
temp char (*)[2] n/a &arr[0][0]
*temp char [2] char * arr[0]
&temp char (**)[2] n/a addr of temp variable
temp[i] char [2] char * &arr[i][0]
*temp[i] char n/a arr[i][0]
&temp[i] char (*)[2] n/a &arr[i][0]
temp[i][j] char n/a arr[i][j]
arr + 1 char [2][2] char (*)[2] &arr[1][0]
*(arr + 1) char [2] char * arr[1]
temp + 1 char (*)[2] n/a &arr[1][0]
*(temp + 1) char [2] char * arr[1]
arr[0][0] char n/a 'a'
arr[0][1] char n/a 'b'
arr[1][0] char n/a 'c'
arr[1][1] char n/a 'd'
**temp char n/a 'a'
*temp[0] char n/a 'a'
temp[0][0] char n/a 'a'
**(temp + 1) char n/a 'c'
*temp[1] char n/a 'c'
temp[1][0] char n/a 'c'
所以,在你的print語句中,你會寫
printf("%c", **temp); // temp == &arr[1][0] after temp++
要么
printf("%c", *temp[0]); // temp[0] == arr[1] after temp++
要么
printf("%c", temp[0][0]); // temp[0][0] == arr[1][0] after temp++
表達式arr
, &arr
, *arr
, arr[0]
, &arr[0]
, *arr[0]
和&arr[0][0]
都產生相同的值 - arr
的第一個元素的地址(記住,數組的地址和數組的第一個元素的地址是相同的)。 他們的類型不同。
請注意, &temp
為我們提供了與 &arr
不同的值。 由於temp被聲明為指針而不是數組,因此&temp
為我們提供了指針變量的地址。
圖片可能會有所幫助:
+---+
arr: |'a'| arr[0][0] <------------------+ before temp++
+---+ |
|'b'| arr[0][1] |
+---+ |
|'c'| arr[1][0] <--+ after temp++ |
+---+ | |
|'d'| arr[1][1] | |
+---+ | |
... | |
+---+ | |
temp: | |---------------+---------------+
+---+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.