2015-08-19 42 views
4

我試圖打印兩個指針之間的距離,但我發現有時代碼不能正常工作。任意指針之間的距離

#include <stdio.h> 
#include <math.h> 

/** 
* Print the distance between 2 pointers 
*/ 
void distance(int * a0, int * a1){ 
    size_t difference = (size_t) a1 - (size_t) a0; 
    printf("distance between %p & %p: %u\n" ,a0, a1, abs((int) difference)); 
} 

試試這個作品完美!

int main(void){ 
    int x = 100; 
    int y = 3000; 
    distance(&x, &y); 
    return 0; 
} 

印刷(例如):

distance between 0028ff18 & 0028ff14: 4 

但開始使用此代碼

int main(void){ 
    int x = 100; 
    int p = 1500; 
    int y = 3000; 
    distance(&x, &y); 
    p = p + 2; // remove unused warning 
    // &p 
    return 0; 
} 

印刷(例如)腳麻:

distance between 0028ff18 & 0028ff14: 4 

當有因爲o打印8 f分隔這個值的整數!

但是,如果我取消註釋//&p,它再次工作。

就好像變量p直到它的內存地址被使用時才存在。

我使用的是Windows 7中(64位)

+0

GCC是優化它拿走。嘗試用'-O0',儘管它可能仍然會留下一些優化。此外,您可以使用['ptrdiff_t'](http://en.cppreference.com/w/c/types/ptrdiff_t)而不是'size_t '投下。但請注意,嚴格來說,只有指向同一陣列中元素的指針可能會從彼此中有意義地減去。 – Kninnug

+0

就像你已經注意到的那樣,編譯器正在優化你的變量p,因爲即使你賦值給它,也不會使用它,只剩下x和y。 –

+0

你最好使用一個數組來進行這種實驗。你不能依賴鏈接器放置一堆可能與彼此沒有任何關係的不同變量。 – Dmitri

回答

2

指針運算僅在指向同一數組元素的指針之間有效,反對這將有不可預測的和實現定義的結果。在這種情況下,似乎你自己找到了答案:gcc正在優化p,但在任何情況下,你都不能在內存中假設任何特定的變量順序,但單獨做指針運算。

此外,該:

size_t difference = (size_t) a1 - (size_t) a0; 

應該是:

ptrdiff_t difference = a1 - a0; 

的正確類型的兩個指針之間的差ptrdiff_t(在stddef.h定義)。您不應將指針投射到size_t,因爲指針值不一定代表size_t(如果您希望將數字類型轉換爲指針,請使用uintptr_tintptr_t)。

%p格式說明需要一個void *,所以你應該投的三分球,並以正確的格式說明符ptrdiff_t%td

printf("distance between %p & %p: %td\n", (void *) a0, (void *) a1, difference); 
+0

我的印象是任何類型的指針都可以傳遞給期望爲void的函數;不需要演員。我過時了嗎? (有時候我記得早期的C標準的東西,沒有意識到自己已經改變了。) –

+0

@ArlieStephens這通常是真實的(當函數原型明確期望一個'void *'指針類型時),但是對於'printf 3)',這些指針作爲變量參數列表的一部分被傳遞,因此不會自動轉換爲'void *'。因爲指針的表示在轉換爲void *時可能會有所不同,並且'%p'格式說明符需要'void *',所以我們需要對其進行轉換。 –

4

p沒有在你的程序中使用,並有可能被優化掉了GCC 4.9.3。無論如何,這是實現細節,編譯器甚至可以自由更改內存中的對象xy的順序。

4

這是因爲如果不存在變量p,直到它的內存地址用於

GCC將優化掉不影響程序的行爲的任何變量。

其次,你不能假設變量按任何特定的順序在內存中佈局,任何兩個之間的「距離」可能是完全沒有意義的。唯一一次可以依靠兩個指針之間的距離來獲得任何意義的時候,它們都指向同一個數組對象中的元素。

+0

更糟糕的是,減去指向同一個對象(或剛剛過去的對象)的指針是* undefined behavior *。 – Jens