2016-07-21 75 views
2

指針存儲的存儲器地址。因此,將這兩個內存地址加1應該可以得到相同的結果,這種情況不會發生。爲什麼? 下面是代碼爲什麼由指針1包含存儲器地址不同於的值地址被指向被指向因此通過指針包含存儲器地址是相同作爲價值存儲器地址的值+ 1個

int main() 
{ 
    int ages[] = {23, 43, 12, 89, 2}; 
    int *cur_ages = ages; 

    printf("\n&cur_ages=%p, &cur_ages+1=%p", &cur_ages, &cur_ages+1); 
    printf("\n&ages=%p, &ages+1=%p", &ages, &ages+1); 
    printf("\ncur_ages=%p, cur_ages+1=%p", cur_ages, cur_ages+1); 
    printf("\n*cur_ages=%d, *cur_ages+1=%d", *cur_ages, *(cur_ages+1)); 

    return 0; 
} 

輸出是

&cur_ages=0x1ffff85f3d0, &cur_ages+1=0x1ffff85f3d8 
&ages=0x1ffff85f3dc, &ages+1=0x1ffff85f3f0 
cur_ages=0x1ffff85f3dc, cur_ages+1=0x1ffff85f3e0 
*cur_ages=23, *cur_ages+1=43 

&年齡+ 1不等於cur_ages + 1。爲什麼?

+1

將非''void *'參數傳遞給'printf(「%p」)''的未定義行爲。你可能認爲這是迂腐的,但各種物體的類型確實是這件事的核心。 – EOF

+2

指針不是地址,將1加到指針不會將地址加1。 – user2357112

+3

@ user2357112:在C語言中,指針值*是*地址。這就是C標準中「地址」這個詞的用法。 C「地址」與機器級別「地址」不同。 –

回答

7

指針算術將指針的值乘以指定的值乘以指向的類型的大小。

所以,當你這樣做:

&ages+1 

你拿的ages地址(這是int [5]型),並添加sizeof(ages)指針值。假設sizeof(int)是4,這會將指針值加20。

同樣,當你這樣做:

cur_ages+1 

這裏,cur_ages指向int,所以加1加sizeof(int)指針值。

+4

這是一個很好的例子,說明爲什麼數組和指針是*不是同一個東西。 –

2

這裏發生了幾件事情。

  1. &cur_ages是一個指針到一個值的地址,而不是一個值的地址。由於C中的(arguably odd) semantics of array names&ages是值的地址。
  2. 指針運算(&<anything>+1)按整個項目工作,而不是按字節。因此,將int *加1會增加sizeof(int)字節,而不是一個字節。
+1

不好意思,但是從初學者的角度來看,這是一個糟糕的回答:)這部分特別指出'&cur_ages是指向一個值的指針的地址,而不是一個值的地址。 ' – Michi

3

& cur_ages是其中cur_ages存儲在棧上的地址。由於& cur_ages + 1大8,所以我會假設這是在64位模式下完成的,其中指針的大小是8字節。

&年齡類似於聲明int(* ptr_to_ages)[5],其中ptr_to_ages是一個指向5個整數數組的指針,可能是一個指向矩陣第一行的指針,其中每一行都是一個數組5個整數。 & ages =存儲數組的第一個成員的地址。正如dbush的答案中所提到的,由於年齡是一個由5個整數組成的數組,因此年齡+ 1分到5個整數後的數組是5個整數,所以+ 5 * 4,其中4是一個整數的大小整數,實際上與指向矩陣第二行的指針相同,其中每行是一個由5個整數組成的數組。

示例代碼不打印出的年齡和年齡+ 1,這將通過的sizeof(int)的不同,而不是由5 *的sizeof(int)的。如果沒有年齡上的前綴&,數組的大小並不重要。

cur_ages和cur_ages + 1點到在年齡在第一和第二整數,如所預期。

* cur_ages和*(cur_ages + 1)是年齡的第一個和第二個整數值。