簡體   English   中英

二維數組變量指針混淆

[英]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

arrayint[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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM