#include <stdio.h>
int main() {
int arr[3] = { 1, 2, 3 };
int *p = arr;
int (*r)[3] = arr;
printf("%u %u", p, r);
printf("\n%d %d %d", p[0], p[1], p[2]);
printf("\n%d %d %d", r[0], r[1], r[2]);
printf("\n%d %d %d", *r[0], *r[1], *r[2]);
printf("\n%d %d %d", (*r)[0], (*r)[1], (*r)[2]);
}
輸出:
1483745184 1483745184
1 2 3
1483745184 1483745196 1483745208
1 0 -647513344
1 2 3
如您所見p并r包含相同的地址,然后
- 為什么
p[0]作業但r[0]沒有? - 后面是
p[0]什么? - 為什么
(*r)[0]作業但其他人不作業?
uj5u.com熱心網友回復:
這兩個宣告的區別
int *p = arr;
int (*r)[3] = arr;
是在第二個宣告中使用了錯誤的初始化程式。arr用作初始化器的陣列被隱式轉換為指向其型別的第一個元素的指標int *。所以在第二個宣告中,初始化物件和初始化器有不同的指標型別,并且型別之間沒有隱式轉換。
要使第二個宣告正確,您需要撰寫
int (*r)[3] = &arr;
現在兩個指標 p 和 r 存盤相同的值:陣列占用但型別不同的記憶體范圍的地址。
例如,如果你會寫
printf( "sizeof( *p ) = %zu\n", sizeof( *p ) );
printf( "sizeof( *r ) = %zu\n", sizeof( *r ) );
那么第一次呼叫將輸出型別int為等于的物件的大小,而第二次呼叫將輸出型別為4的整個陣列的大小。int[3]12
在此您對 printf 的呼叫
printf("%u %u", p, r);
使用了不正確的帶有指標的轉換說明符。相反,你必須寫
printf("%p %p", ( void * )p, ( void * )r);
運算式 r[0], r[1], r[2] 具有 int[3] 型別。在本次通話中使用
printf("\n%d %d %d", r[0], r[1], r[2]);
正如它所提到的,它們被隱式轉換為指向它們的第一個元素的指標。但是除了表示陣列 arr 的陣列 r[0] 之外,這些陣列都不存在。所以會發生對陣列 arr 之外的記憶體的訪問,
你可以寫
printf( "\n%p\n", ( void * )r[0] );
這個呼叫將相當于
printf("\n%p\n", ( void * )arr );
這個 printf 的呼叫
printf("\n%d %d %d", *r[0], *r[1], *r[2]);
也是不正確的,因為陣列r[1]和r[2]型別int[3]不存在。
這個 printf 的呼叫
printf("\n%d %d %d", (*r)[0], (*r)[1], (*r)[2]);
arr由于使用了運算式,輸出了陣列的元素*r。
uj5u.com熱心網友回復:
r和之間的區別p僅在于型別。
首先要注意的是賦值int (*r)[3] = arr;不正確;arrin assignments 衰減到指向其第一個元素 an 的指標,它與指向三個整數陣列的指標int不同。r現在誠然,C 最初并沒有那么挑剔,不同指標型別之間以及指標和整數之間的賦值沒有考慮太多——都是數字,對吧?但是現代 C 試圖更加型別安全,這是有充分理由的,所以正確的分配是int (*r)[3] = &arr;:如果你想要一個陣列的地址,只需獲取地址。您的代碼“有效”,因為數字上第一個元素的地址是陣列的地址。錯誤的是型別,而不是值。
現在讓您感到困惑:正如您所指出的,兩者都指向同一個地址;但是物件p指向的是一個簡單的 int (恰好后面跟著記憶體中的另外兩個 int,一起包含arr),同時r指向陣列本身。
因此, 的型別為*p,int而 的型別*r為int[3],因此sizeof *r == 3 * sizeof *p成立。
如您所知,C 在大多數情況下模糊了這種區別:例如,您可以合理地說p = *r;,因為陣列在賦值或引數初始化中被“調整”或“衰減”到指向它們的第一個元素的指標。
但因為sizeof他們沒有。那是因為索引增加index * sizeof(element)了指標的數值;如果指標指向整個陣列,like r(而不是它的第一個元素,like p),第二個元素將是下一個陣列,它不存在 - 只有一個陣列,所以你的程式有問題。
#include <stdio.h>
int main() {
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*r)[3] = arr;
printf("%p %p\n", (void*)r[0], (void*)r[1]);
}
這個小程式說明了這一點。注意arr再次衰減到它的第一個元素的地址;只是這一次,該二維陣列的第一個元素是一個陣列本身,由三個整陣列成,所以它非常適合。
uj5u.com熱心網友回復:
*p 是指向陣列的指標,而 (*r)[3] 是指向陣列的陣列指標。
*p 將指向陣列 arr 的值/索引。(*r)[i] 將指向索引的記憶體位置/地址。
*r 不會指向 (*r) 和 *r 不同的地方。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/430613.html
