从整数转换为指针

时间:2012-05-26 09:41:24

标签: c++ pointers casting integer c-preprocessor

我正在学习使用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是数字,它如何更改为对象指针?对象指针如何减去整数?

3 个答案:

答案 0 :(得分:5)

#define是一个预处理器命令。它在代码编译之前得到评估。所有发生的事情是主函数中的SOME_VALUE将文本替换为文本SOME_VALUE定义为。那是8。

SOME_VALUE本身没有C ++类型,因为它只在预处理之前存在。在预处理之后,C ++程序中将不存在SOME_VALUE,您将只有一个字符值8,这是一个int。

对于第二个问题,对Base *的强制转换使用C样式转换。只需将原始内存转换为目标类型,即可将任何内容转换为任何内容。因此,如果正在转换的内存与目标类型不匹配,则会非常危险。对于C ++,我建议使用static_cast或reinterpret_cast来更明确地说明正在进行的内容。

我认为(Base *)SOME_VALUE最终将作为Base *到内存地址8.因此,这是一个指向Base对象的指针,该对象从内存中的第8个字节开始。在内存中的位置8可能没有Base对象,因此它实际上并不是非常有用。然后“ - 8”消除了Base *类型大小的8倍。在32位计算机上,指针是32位或4字节。所以,8 - (4 * 8)= -24十进制,这是十六进制的FFFFFFE8。

如果你想知道为什么计算机将负数表示为大数字,那就是另一个问题。从这里开始:http://en.wikipedia.org/wiki/Signed_number_representations

答案 1 :(得分:2)

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

基本上是一种(可怕的)做法:

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

8将默默地乘以Base的大小(因此你减去了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.

答案 2 :(得分:2)

SOME_VALUE是一个宏 - 它没有类型。但是,8是一个整数。

如果您希望#define SOME_VALUE ((Base*)8)始终像SOME_VALUE一样行动,请使用Base*