2012-05-26 147 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

非常感谢你 –