[英]What is the difference between these two statements?
我有這兩個聲明:
printf("%u",a+1);
和
printf("%u",(int *)a+1);
實際上,當我遇到這種困惑時,我正在處理這段代碼。
#include<stdio.h>
int main()
{
int a[2][2]={1,2,3,4};
int i,j;
int *p[] = { (int*)a, (int*)a+1, (int*)a+2 };
for(i=0; i<2; i++){
for(j=0; j<2; j++){
printf("%d %d %d %d",* (*(p+i)+j), *(*(j+p)+i), *(*(i+p)+j), *(*(p+j)+i));
}
}
return 0;
}
Output:
1 1 1 1
2 2 2 2
2 2 2 2
3 3 3 3
為了理解上面程序的 output,我知道如果我知道上面兩個語句之間的區別,就可以解決造成這個 output 的區別。
我目前的理解: (a+1)
會給我數組第二個元素的地址。 在這種情況下,二維數組可以可視化為 2 1-d arrays,每個數組有 2 個元素。 所以(a+1)
會給我a[1][0]
的地址,但為什么(int *)a+1
會給我a[0][1]
的地址?
請說明區別和程序的output。
謝謝。
成語(int*)a+1
被解釋為((int*)a) + 1)
。 也就是說,轉換優先於添加。 所以它的計算結果為(int*) a)
,它是作為 ptr-to-int 的數組地址,偏移 1,返回數組中的第二個元素 ( 2
)。
編程的兩個關鍵規則:
規則 1:編寫代碼時,使布局反映功能。
規則 2:閱讀代碼時,閱讀功能,而不是布局。 (推論:調試代碼,而不是注釋。)
從概念上講,當你聲明
int a[2][2]={1,2,3,4};
你設想一個像這樣的二維數組:
1 2
3 4
但 C 實際上將數據存儲在 memory 的一個連續塊中,如下所示:
1 2 3 4
它在計算索引時“記住”數據表示一個 2×2 數組。 但是,當您將a
從其原始類型轉換為int *
時,您是在告訴編譯器忘記其原始聲明,從而有效地失去其二維性並成為int
的簡單向量。
以下是如何理解p
的聲明:
int *p[] = { (int*) a, (int*) a+1, (int*) a+2 }; // As written
int *p[] = { (int*) a, ((int*) a) + 1, ((int*) a) + 2 }; // As interpreted
int *p[] = { &a[0][0], &a[0][1], &a[1][0] }; // Resulting values
由此可見, p
是一個一維向量數組:
p[0] = { 1, 2, 3 }
p[1] = { 2, 3 }
p[2] = { 3 }
如果您認識到(p+i) == (i+p)
,那么最后兩項與該行中的前兩項相同
printf("%d %d %d %d\n",* (*(p+i)+j), *(*(j+p)+i), *(*(i+p)+j), *(*(p+j)+i));
這相當於:
printf("%d %d %d %d\n", p[i+j], p[j+i], p[i+j], p[j+i]);
有趣的是,因為以下都是等價的:
a[i]
*(a+i)
*(i+a)
那么寫i[a]
來表示相同的值是完全合法的。 換句話說,編譯器允許你寫
printf("%d %d %d %d\n", p[i], i[p], p[1], 1[p]);
當然,你的 tech lead 最好不要讓你這么寫。 如果你在我的小組里這樣寫,你就會被解雇。 ;-)
無,兩者都會產生未定義的行為。 打印指針值的正確格式是%p
。 將指針發送到printf
時將指針指向void*
。
多維 C arrays 表現得像單維 arrays 並排放置。 因此,如果您將a
(通常(int **)
) 轉換為(int *)
,您會得到與a[0]
相同的結果。 因此(int *) a + 1
是&a[0][1]
。 否則你的理解是正確的,這就是為什么a + 1
得到你&a[1][0]
。
(此行為由標准指定;但這並不是好的編程習慣。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.