2016-08-15 102 views
-1
typedef struct nodes { 
    int da; 
    struct nodes *ptr; 
} node; 

node init; 

printf("%d %d %d\n", &init, &init-2 ,6295648-2); 

打印爲什麼用printf

6295648 6295616 6295646 

如何來自一個地址中減去2減去32(因此從地址減去1減去16),使用在地址動作怪異的表達?

+2

首先,init是什麼?其次,要打印一個指針,你應該使用''%p''格式來打印'void *'(需要強制轉換)。 –

+1

'init'是一個「長雙」嗎?還是某種結構類型?大多數其他內置類型不是16個字節長。 –

回答

2

當你做指針算術你的基本單位是基本類型。例如,如果您對指向int的指針(即int*)執行指針運算,則以sizeof(int)爲單位執行指針運算。

讓我來說明吧:假設我們有

int *pi = malloc(...); // Actual size doesn't matter for this example 

在內存方面它像

 
+-------+-------+-------+-------+ 
| pi[0] | pi[1] | pi[2] | ..... | 
+-------+-------+-------+-------+ 
^  ^ ^ ^
|  |  |  | 
pi+0 pi+1 pi+2 pi+3 

上圖應該有希望也解釋了指針和數組之間的關係之間的一個小,尤其是爲什麼表達式pi[x]*(pi + x)相同。這些表達式對於指針數組都是相同的。

現在,通過從一個指針減去,你將有一個指針什麼指針指向前。只需打印指針即可,但在大多數情況下,您無法對其進行取消引用(獲取它指向的值)。

1

因爲16是init指向的大小。

下面三者是等價的:

  • ptr[offset]
  • *(ptr + offset)
  • offset[ptr](但不這樣做)

所以,當你從init加上或減去東西時,計算出的地址取決於init指向的類型的大小。如果大小爲16,每一個偏移計算將是16

+0

'8'是任何'init'指向的大小(因爲OP減去2,而不是1) –

+0

不是我的DV,但我想問題是這個問題不使用下標,而且你不直接解釋你寫的如何適用於這個問題。 –

+0

@TomKnapen我相信他在減去1時減去16而在減去2時減去32。 – Kusalananda

4

首先的倍數,打印地址,你應該使用%p格式說明,並投了參數(void *)所要求的printf()。否則,對提供的格式說明符使用錯誤類型的參數會調用undefined behavior

這就是說,關於指針運算,引用C11,章§6.5.6

當具有整數類型的表達式被加到或減去一個指針, 結果具有的類型指針操作數。如果指針操作數指向數組對象的元素,並且該數組足夠大,則結果指向原始元素的偏移量 ,從而使得結果數組元素和原始數組元素的下標之差等於整數表達式。 [...]

這意味着,指針運算會對指針的數據類型表示支持。用指針加整數(或相減)的結果不是,而是另一個數,它是另一個(可能)元素的地址,只要存在。

分別

換句話說,如果表達式P指向 陣列對象的i個元素,表述(P)+N(等同於N+(P))和 (P)-N(其中N具有值n)指向, ,數組對象的i+nthth和i−n-第 個元素,只要它們存在。 [...]

3

當您對指針進行算術運算時,地址的加法或減法是以指針指向的數據類型爲單位完成的。這是允許的等價:

&arr[n] = arr + n; 

所以,如果sizeof init = 8,然後&init - 2將減去地址16個字節。

1

在C中,將2減去int或者指針是不一樣的。這是pointer arithmetic。 使用int指針,減去2將使指針位置移動2*sizeof(int)。 如果您在減量之前將指針指向int,您將檢索相同的值。

相關問題