2009-04-29 109 views
11

說,我們有以下代碼:數組c地址混淆

int main(){ 
    int a[3]={1,2,3}; 
    printf("  E: 0x%x\n", a); 
    printf(" &E[2]: 0x%x\n", &a[2]); 
    printf("&E[2]-E: 0x%x\n", &a[2] - a); 
    return 1; 
} 

當編譯和運行的結果是如下:

 E: 0xbf8231f8 
    &E[2]: 0xbf823200 
&E[2]-E: 0x2 

我明白& E的結果[2]其是8加上數組的地址,因爲索引2和int類型(在我的32位系統上是4個字節),但我無法弄清楚爲什麼最後一行是2而不是8?

另外,什麼類型的最後一行應該是 - 整數或整數指針?

我不知道是否這是使這種怪癖的C型系統(有點鑄造)?

+0

這幾乎是一個重複http://stackoverflow.com/questions/759663/pointer-arithmetic-in-c – finnw 2009-07-03 05:38:44

+0

什麼printf(「E:0x%x \ n」,&a); – dashesy 2012-11-29 19:17:49

回答

10

你要記住表達a[2]的真正含義。它完全等同於*(a+2)。如此之多,寫2[a]代替效果完全合法。

爲了工作和有意義,指針算術考慮了指向的東西的類型。但這是幕後照顧。你只需要在你的數組中使用自然偏移量,並且所有的細節都可以解決。

相同的邏輯適用於指針差異,這解釋了您的結果2

在你的例子中,索引乘以sizeof(int)得到一個字節偏移量,該偏移量被加到數組的基地址。您在地址的兩個打印中公開該細節。

8

當減去相同類型的指針時,結果是元素數量而不是字節數量。這是設計的,以便您可以輕鬆索引任何類型的數組。如果你想要的字節數 - 將地址轉換爲char *。

5

該行& E [2] -2正在做指針減法,而不是整數減法。指針減法(當兩個指針都指向相同類型的數據時)返回地址的差異除以它們指向的類型的大小。返回值是一個int。

要回答您的「更新」問題,請再次執行指針運算(此時指針添加)。它在C中以這種方式完成,以便更容易地「索引」指針指向的連續數據塊。

+1

返回值是一個int,而不是一個int *。 – paxdiablo 2009-04-29 08:55:33

+0

對不起,金髮女郎時刻......你說的對, – marcog 2009-04-29 08:57:55

0

如果你想看到的字節差,你就會有一種類型的大小爲1個字節,就像這樣:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0])) 
1

當添加和使用C減去指針,你使用的大小數據類型而不是絕對地址。

如果您有一個int指針並將數字2添加到它,它將提前2 * sizeof(int)。以相同的方式,如果你減去兩個int指針,你將得到以sizeof(int)爲單位的結果,而不是絕對地址的差異。

(具有使用該數據類型的大小球還是比較方便的,這樣就比如可以簡單地使用p++,而不必每次都指定類型的大小:p+=sizeof(int)

7

當你增加通過將指針加1(p + 1),指針將通過向p添加(p + sizeof(Type))字節來指向下一個有效地址。 (如果Type是int,那麼p + sizeof(int))

類似的邏輯也適用於p-1(當然在這種情況下是相減的)。

如果你只是在這裏適用這些原則:

簡單來說:

a[2] can be represented as (a+2) 
a[2]-a  ==> (a+2) - (a) ==> 2 

所以,在幕後,

a[2] - a[0] 
==> {(a+ (2* sizeof(int))) - (a+0) }/sizeof(int) 
==> 2 * sizeof(int)/sizeof(int) ==> 2 
1

Re:「另外,最後一行的類型應該是什麼?一個整數或一個整數指針?」

整數/數字。同樣的道理:今天 - 四月一號=號碼。沒有日期