2016-02-12 52 views
-1

這是C.我正在學習C,這是一個幻燈片中的例子。爲什麼這個指針減法輸出這個?

int main(int argc, char *argv[]) { 
    int a = 5, b = 10, c; 
    int *p = &a, *q = &b; 
    c = p - q; 
    printf("%d", c); 
    return 0; 
} 

當我運行它的輸出是3,我不明白爲什麼。這似乎是因爲它使用&它會減去內存地址,輸出將是內存地址爲-5。

+2

你能解釋爲什麼你期望-5? –

+0

你問爲什麼從另一個減去一個指針而不是從另一個減去一個指針? –

回答

5

你正在減去指針的地址,而不是它們指向的地址,你會得到兩個存儲器地址之間的差異,不能保證是任何特定的。如果你在不同的機器或編譯器上運行它,它將很可能是完全不同的值,因爲ab可以分配到各種地址。例如,在我的機器上,它是1.類似的現象稱爲未定義的行爲出於某種原因,因爲您無法保證所有編譯器和機器都有相同的結果。

如果您改爲pq像這樣c = *p - *q;您將得到-5作爲c作爲兩組值之間的差異。此外,如果您將pq分配爲int *p = a, *q = b;,那麼您也會將c設置爲-5,因爲那樣您就可以將指針設置爲不同的地址,並在嘗試訪問之後嘗試訪問,在任何情況下都會是一個糟糕的主意。

+0

謝謝,但我沒有試圖減去他們指向的東西,這是一個來自老師的例子,我不理解它,我只是在腦海中想到它會是-5。你能解釋爲什麼它是3嗎? –

+0

@BenjaminDagg這正是我在回答中解釋的內存地址的差異。它現在可能是3,但是可以在不同的計算機或編譯器上重新編譯它,它很可能會非常不同,因爲地址會有所不同。 – Dom

+0

@BenjaminDagg沒有什麼特別的原因,它只是3.它碰巧是3.如果你拋硬幣,它可能會出現,但沒有理由出現在頭上。它只是。你爲什麼期望-5?這就是錯誤 - 你沒有理由期待這一點。 –

3

減去2個不是同一個數組的指針是未定義的行爲。

當兩個指針相減時,它們都應指向同一個數組對象的元素,或者指向數組對象的最後一個元素之後的元素;結果是兩個數組元素的下標差異。 C11§6.5.69

相反,得到一些數字差異,值轉換爲intptr_t

int main(int argc, char *argv[]) { 
    int a = 5, b = 10, c; 
    int *p = &a, *q = &b; 
    intptr_t ip = (intptr_t) p; 
    intptr_t iq = (intptr_t) q; 
    intptr_t diff = ip -iq; 
    printf("%lld", (long long) diff); 
    return 0; 
} 

當然您打印的值可能不是5. int的位置從編譯變化進行編譯。