2012-05-26 56 views
1

我正在學習使用C++進行投射,後面的代碼對我來說很神奇。轉換爲整數指針

#include <iostream> 
using namespace std; 

class Base { 
public: 
virtual void f() { } 
}; 

#define SOME_VALUE 8 

int main() { 
cout << SOME_VALUE <<endl; 
getchar(); 
} 

輸出爲:8

的代碼非常簡單,但什麼類型SOME_VALUE的? int,還是double或char?更復雜的

後:

#include <iostream> 
using namespace std; 

class Base { 
public: 
virtual void f() { } 
}; 

#define SOME_VALUE 8 
int main() { 
cout << (Base*)SOME_VALUE-SOME_VALUE <<endl; 
getchar(); 
} 

輸出是:FFFFFFE8

在此之後的代碼,我能理解SOME_VALUE是數值型。我也測試sizeof(SOME_VALUE)和輸出是4.但是,如果SOME_WHAT是數字,它如何改變爲對象指針?以及如何對象指針可以減去整數?

+0

我記得C++有'typeof'函數。檢查它,是的。但它是主要的延伸。 – gaussblurinc

回答

2

SOME_VALUE是一個宏 - 它沒有類型。然而,8是一個整數。

使用#define SOME_VALUE ((Base*)8),如果你想SOME_VALUE總是像Base*一樣行事。

+0

非常感謝你 –

5

#define是一個預處理器命令。它在編譯代碼之前得到評估。發生的情況是,主函數中的SOME_VALUE將其文本替換爲SOME_VALUE定義的文本。那是8.

SOME_VALUE本身沒有C++類型,因爲它只存在於預處理之前。經過預處理SOME_VALUE不會在C++程序中存在,您只需要一個8的整數值即int。

對於第二個問題,轉換爲Base *使用C風格轉換。只要將你轉換成目標類型的內容記錄下來,就可以將任何東西轉換爲任何東西。因此,如果正在建立的內存與目標類型不匹配,則可能會非常危險。對於C++,我建議使用static_cast或reinterpret_cast來更加明確地表明正在傳輸的內容。

我認爲(Base *)SOME_VALUE最終會成爲內存地址8的一個Base *。因此,這是一個指向內存中第8個字節的Base對象的指針。內存中的位置8可能沒有Base對象,所以它實際上並不是非常有用。然後「 - 8」帶走Base *類型的8倍的大小。在32位計算機上,指針爲32位或4位。因此,8 - (4 * 8)= -24十進制,即十六進制中的FFFFFFE8。

如果您想知道計算機爲什麼會將負數表示爲大數字,那麼這是一個不同的問題。從這裏開始:http://en.wikipedia.org/wiki/Signed_number_representations

+0

非常感謝你。我愛你 –

2
cout << (Base*)SOME_VALUE-SOME_VALUE <<endl; 

,基本上是做的(恐怖)的方式:

Base* b = 8; 
b = b - 8; 

8將通過對基本的,但(這樣你就減去8個基座槽的大小來默默相乘,不是8)。

指針通常是未簽名的,所以發生的事情是無符號指針正在環繞。

0xFFFFFFE8爲4294967272或(假設4字節的周圍通常包無符號整數)8 - 24

而且,你永遠不應該在實際代碼做到這一點。給一個指針指定一個任意值肯定會在一個火熱的爆炸中結束。

一個更容易理解的情況可能是這樣的:

int* p = (int*) 24; 
p -= 4; //like ((char*) p) - 4 * sizeof(int) 

隨着4個字節的整數,的p值將被8,因爲24 - 4 *的sizeof(INT)= 24 - 4 * 4 = 24 - 16 = 8。

+0

非常感謝你 –