2013-10-15 197 views
0

爲什麼下面的代碼打印0?即爲什麼變量a位於變量d之後,即使指針變量c正在它們之間聲明?爲什麼這段代碼打印0

#include<iostream> 
using namespace std; 

int main() { 
    unsigned int a = 100; 
    unsigned int &b = a; 
    unsigned int *c = &b; 
    unsigned int d = (unsigned int)(c); 
    int e = &d - c; 
    int &f = e; 
    e ++; 
    cout << e << " " << endl; 
    return 0; 
} 
+14

減去指向不相關的對象是不確定的行爲。編譯器可以生成任何喜歡的代碼。它確實如此。 – rici

+2

它爲我打印2。 – deepmax

+0

而這並不打印0,對我來說它打印2? – Annabelle

回答

2

工作向後:

e ++; 
cout << e << " " << endl; 

如果打印0,那麼e這段代碼執行前的值一定是-1

int e = &d - c; 

所以上述地址相減的結果一定是-1

unsigned int a /* = whatever, the value of a doesn't matter */; 
unsigned int &b = a; 
unsigned int *c = &b; 
unsigned int d /* = whatever, the value of d doesn't matter */; 

ba的引用,所以&b相當於&a

所以&d - c相當於&d - &a,那減法得到-1

結論:d地址爲的a地址後sizeof (unsigned int)字節。 (指針減法按指定類型的大小縮放。)

可能。

實際上,減去指向兩個獨立定義對象的指針的行爲是undefined。該標準完全沒有說明它應該做什麼。

在實踐中,編譯器可能會產生一個指針減法儘可能簡單的代碼,並且簡單的代碼可能會治療無關的指針彷彿他們相媲美,即使語言不說他們是。

根據程序的輸出結果,很可能bd恰好相互分配。沒有說任何聲明的變量必須按照你聲明的順序進行分配。如果希望對象按定義順序分配到內存中,請將它們放入struct或將它們設置爲數組的元素。

如果您在不同的系統上運行它,或者在具有不同編譯器的同一系統上運行它,或者在具有不同編譯器選項的相同編譯器的同一系統上運行它,也可能會產生不同的結果。原則上,它甚至可以在一切相同但在月球的不同階段表現不同。

而編譯器被允許爲假設您的代碼的行爲已被很好地定義,並執行僅在給定假設的情況下有效的轉換。實際上,通過減去兩個不相關的指針,你已經答應編譯器它們都指向同一個數組對象的元素或剛剛超過它的末尾(其中一個對象被視爲1個元素的數組)是空指針;這是C和C++之間的區別)。你已經對編譯器撒謊了,這意味着它對你沒有進一步的義務。

不要這樣做。

+1

'b'實際上是一個綁定到'a'的引用,所以「向後工作」過程在技術上應該包含一個額外的步驟:'&b'實際上是'&a',這意味着'&d -c'等價於'&d - &a'。但OP顯然已經知道,因爲這正是問題中所說的。 – AnT

+0

@AndreyT:啊,我錯過了參考。固定。 –

0

除非你明確地使用自己的內存管理系統將物體,它們在內存中的相對位置將是反編譯和系統的依賴性。

-1

您的線路int e = &d - c;正在減速2 unsigned int *

在內存中,&d是8字節,然後是c(它取決於您的系統,但我們假設int是4字節)。實際上,你建立你的籌碼以這樣的方式

unsigned int a = 100;    // &a is 0x0 
unsigned int &b = a;     // &b is 0x0 (it's just an alias) 
unsigned int *c = &b;    // &c is 0x4 
unsigned int d = (unsigned int)(c); // &d is 0x8 

unsigned int使用內存4個字節。因此,當你在做&d - c時,它必須返回2,因爲你正在使用指針運算與unsigned int*(4 * 2 = 8);所以,當你在做&d - c時,它必須返回2

您可以嘗試使用int e = (short*)&d - (short*)c結果應爲4,因爲short大小爲2(2 * 4 = 8)。

你可以試試int e = (char*)&d - (char*)c結果應該是8,因爲char大小是1(1 * 8 = 8)。

嘗試打印變量和地址瞭解:

#include<iostream> 
using namespace std; 

int main() { 
    unsigned int a = 100; 
    unsigned int &b = a; 
    unsigned int *c = &b; 
    unsigned int d = (unsigned int)(c); 
    int e = (short*)&d - (short*)c; 
    //int &f = e;                                         
    //e ++;                                           

    cout << "&a: " << (unsigned int)&a << endl; 
    cout << "&b: " << (unsigned int)&b << endl; 
    cout << "&c: " << (unsigned int)&c << endl; 
    cout << "&d: " << (unsigned int)&d << endl; 

    cout << endl; 

    cout << " a: " << a << endl; 
    cout << " b: " << b << endl; 
    cout << " c: " << (unsigned int)c << endl; 
    cout << " d: " << d << endl; 

    cout << endl; 

    cout << " e: " << e << endl; 
    return 0; 
} 

這裏,int e = (short*)&d - (short*)c;,結果是:

&a: 3220197356 
&b: 3220197356 
&c: 3220197360 
&d: 3220197364 

a: 100 
b: 100 
c: 3220197356 
d: 3220197356 

e: 4