[英]2D array variable pointer confusion
我對2D數組(C語言)有一個基本的疑問。 考慮如下的2D數組的聲明
int array[3][5];
現在,當我執行以下操作時,兩個printf的輸出都是相同的:
printf("%u\n", array);
printf("%u\n", *(array));
現在嘗試以下內容:
printf("%u\n", array+1);
printf("%u\n", *(array)+1);
輸出是不同的。 我得到第二個printf引用數組[0] [1]而第一個引用數組[1] [0]。 這是如何運作的? 數組是什么指針?
提前致謝
我會嘗試給你一個技術上正確的解釋,這樣你就會知道發生了什么。 不是很復雜,但確實是反直覺的。
介紹:
在C中,存在“左值”,其基本上表示在存儲器中具有位置的“可分配”對象,以及“右值”,其表示“概念”值(不需要特別放置在任何地方)。
例如,如果你定義int a = 5;
,則a
是int類型和值5的左值。它也可以解釋為(或者更確切地說,轉換為)int類型的右值。 這樣一個rvalue仍將被已知是等於5,但它不再包含關於信息a
在存儲器中的位置。
有些表達式需要左值(比如運算符的左側=因為你必須分配給一個對象),有些需要rvalues(比如operator +因為你只需要添加時的積分值,或者運算符的右側=) 。 如果表達式需要rvalue但是傳遞左值,則它將轉換為rvalue。
此外,只有rvalues傳遞給C中的函數(這意味着C嚴格按值調用,而不是按引用調用)。
一些例子:
int a = 1;
a; // a is an lvalue of type int and value 1
a = a+3; // here the `a` is converted to an rvalue of type int and value 1, then after the addition there's an assignment, on the lhs there's an lvalue `a` and an rvalue `4`
從左值到左值的轉換通常是微不足道的,並且是不可察覺的(就像從標a
a的架子上取5號)。 數組基本上是例外。
重要的是: C中沒有數組類型的右值 。 有指針左值和右值,整數左值和右值,結構左值和右值等......但只有左值數組。 當您嘗試將數組類型的左值轉換為右值時,您不再擁有數組,您有一個指向該數組的第一個成員的指針。 這是C(和C ++)中數組混淆的根源。
說明:
array
*(array)
array+1
*(array)+1
array
是int[3][5]
類型的左值(5個整數的3個整數的數組)。 當你試圖將它傳遞給一個函數時,它會收到一個類型為int (*)[5]
指針(指向5個整數的數組),因為這是在左值到右值轉換后剩下的。
*(array)
是tricker。 首先執行左值到右值,得到一個類型為int(*)[5]
rvalue,然后operator*
取該rvalue並返回一個類型為int[5]
的左值,然后你嘗試傳遞給該函數。 因此它再次轉換為右值,產生一個int*
。
array+1
導致數組轉換為int(*)[5]
類型的rvalue,並且rvalue增加1,所以(根據指針算術的規則)指針移動1 * sizeof(int[5])
字節轉發。
*(array)+1
:之前看到2個點,但int*
類型的最終rvalue再次通過指針算術規則增加1 * sizeof(int)
。
這里沒有神秘感!
C中的2D數組令人困惑。
array和* array都是相同的指針,但類型不同。
array的類型為int [3] [5](這是一個大小為5的int [3]數組的數組)。
* array是數組的第一行,類型為int [3]。
array + 1表示數組加一個元素。 數組的元素是int [3],所以前進了12個字節。
* array + 1表示*數組加一個元素。 *數組的元素是int,因此前進了4個字節。
數組不是指針。 忽略任何試圖告訴您的答案,書籍或教程。
陣列型的表達,在大多數情況下,被轉換 (在編譯時)到一個指針數組的第一個元素。 例外情況是:
sizeof
的操作數( sizeof arr
產生數組的大小,而不是指針的大小) &
( &arr
的操作數產生數組的地址,而不是它的第一個元素 - 相同的內存位置,不同的類型)。 這與您的示例特別相關。 char s[6] = "hello";
不復制字符串文字的地址,它復制其值) 二維數組不過是一個數組數組。 還有其他數據結構可以與相同的x[y][z]
語法一起使用,但它們不是真正的二維數組。 你的是。
[]
索引操作符是根據指針算法定義的。 x[y]
表示*(x+y)
。
代碼的行為遵循這些規則。
閱讀comp.lang.c FAQ的第6部分。 這是我見過的最好的解釋。
並且不要使用"%u"
來打印指針值; 轉換為void*
並使用"%p"
。
printf("%p\n", (void*)array);
printf("%p\n", (void*)*(array));
你可以這樣理解:
數組指向3行,每行5列
當你做數組+ 1時,行改變,所以你去第1行。 您應該嘗試使用*(array + 1)進行訪問。
當你執行*(數組)時,你指向第0行,*(數組)+1在列中向前移動,因此元素是數組[0] [1]
指針中的單位增量與數據類型的大小一致。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.