int main()
{
int arry[3][5]={
{1,2,4},
{4,5,6,7},
{6,5,3,8}
};
int (*p)[5];
p=arry;
printf("%x\n",*(p+1)+3);
printf("%x\n",*(*(p+1)+3));
printf("%x\n",*(p+1)+3);
printf("%x\n",*(p+1)+2);
printf("%x\n",p);
printf("%x\n",p+1);
printf("%x\n",*p+1);
printf("%x\n",p[0]+1);
printf("%x\n",**p);
printf("%x\n",&p);
定義了一個二維數組arry,printf("%x\n",*(p+1)+3);為什麼這樣輸出來的是一個地址?
其中printf函數中的輸出項表,到底是不是在計算表達式的左值還是右值,如果是的
話,到底是哪個值? 謝謝解決問題
再解決該問題之前,想講一下,定義一個指針的語句,代表的含義.
接下來,根據這個題來講.
int main()
{
int arry[3][5]={{1,2,4},{4,5,6,7},{6,5,3,8}};//數組名代表的是一塊內存的首地址
int (*p)[5];//定義一個數組指針.這個指針,指向一個一維數組的首地址.該一維數組含有5個成員.可以把這條語句理解成int5;那麼指針p指向的是一個int[5] 類型,p的尋址能力是sizeof(int)*5. p+1指向的地址和p指向的地址相差20. 在二維圖中,(p+1)就到下一行.
//在一些參考書中,把*(星號)解釋成降低維度(降維).本來p是指向int型數組的指針.用星號降維之後,(*p)就是一個int型的指針.那麼(*p)+1,就是往後移動了sizeof(int)個字節,就是4個字節.記住,現在(*p)還依然是一塊內存地址.
p=arry;//p指向數組arry的首地址
printf("%x\n",*(p+1)+3);//在附加的參考圖中,p指向0XFFFF0002,p是一個int[5]類型的指針,所以,p+1往後移動sizeof(int)*5個字節,也就是移動到第二行,p+1就是第二行的首地址.*(p+1)就是降維,接下來如果再移動,就是移動sizeof(int)個字節.切記,這時候*(p+1)仍然是一個地址,*(p+1)並不是取(p+1)這個地址的值.因為p一開始指向的是一個數組,所以,這時候的星號只是降維.現在*(p+1)是一個地址了,也可以理解為是一個int型的指針了.如果再進行取值,那麼就是一個數值.例如:*(*(p+1)+0)是第二行第一個的值, ((p+2)+4)是第三行第五個的值.
printf("%x\n",*(*(p+1)+3));//第二行第三個的值
printf("%x\n",*(p+1)+3);//第二行第四個的地址
printf("%x\n",*(p+1)+2);//第二行第三個的地址
printf("%x\n",p);//數組的首地址,也是第一行的首地址,也是第一行第一個元素的首地址.
printf("%x\n",p+1);//第一行第二個元素的首地址.p是一個int[5]類型的指針,所以你要承認,(p+1)仍然是一個int[5]類型的指針,並不是int型的指針,所以,要先用星號對它進行降維,才是int型的指針.然後才可以使用星號取這個地址的值.
printf("%x\n",*p+1);//第一行第二個元素的地址.
printf("%x\n",p[0]+1);//p[0]相當於*(p+0).所以,這個是第一行第二個元素的地址.在這裡再多講一點數組方式訪問和星號方式訪問的轉換.*(p+0)和p[0]相同,*(p+3)+2和p[3]+2相同,p[2][3]和*(*(p+2)+3)相同.
printf("%x\n",**p);//第一行第一個元素的值.
printf("%x\n",&p);//p是一個指針變量,p在內存中也有一個存儲它的空間.這句話就是輸出存放變量p的內存地址.
}
我猜你可以這麼想:
你如果不能理解,你可能會說:”p是一個內存地址,那麼*p就該是取這塊內存地址中存放的值”.那麼,我們拿上面這個題為例,定義p的時候是這樣定義的.int (*p)[5];然後,請你告訴我如果訪問第一行第三個空間的值?是*(p+2)嗎?如何訪問第三行第二個空間的值?是*(p+11)嗎?拜托大哥,如果你想這樣訪問的話,你定義指針變量p的時候,可以這樣定義,int *p=arry;那麼,你就可以盡情的通過*(p+11)訪問到第三行第二個空間的值了.