取得类成员的偏移量

提出问题

给定一个类:

struct A
{
	int a0;
	int a1;
	int a3;
};

如何取得各成员相对于类地址的偏移量?

解决问题

一种方法如下:

#define MEMOFFSET1(Class, Member) (reinterpret_cast<char*>(&static_cast<Class*>(0)->Member) - reinterpret_cast<char*>(0))

首先强制类型转换成为char*指针,保证计数是以字节为单位,然后指针做减法,得到整形,由于是用空指针做类型转换,因此后面的减数指针的值为0

另一个等效的方式是:

#define MEMOFFSET2(Class, Member) (reinterpret_cast<int>(&static_cast<Class*>(0)->Member))

当然这种表达方式让我很费解,为什么不能时使用static_cast将指针转换成为int型,反而要用reinterpret_cast来转换

其实一开始我想到的是另一种方法,使用指向类成员的指针,例如:

(int)&AAA::a1

但是这样会编译错误,而且以下的代码也会输出错误的结果:

cout << &A::a0 << endl;

因为相对于泛型的operator << (T),这个调用更偏好特化的operator << (bool)

但是printf就可以得出正确的结果,通过printf的源码可以知道其实在内存中&A::a0之类类成员指针都是以整型的方式储存的.只要以整型的方式来解析内存中的数据,就可以得到正确的结果!但是在强制转换被编译器阻止的时候,应该如何读出正确的结果呢?(printf可以通过挪动形参的指针来绕过编译器,当然使用这个方法也可以),但是有另一个方式union,就不用多说了,代码贴上,一目了然:

#include <iostream>
using namespace std;
struct A
{
	int a0;
	int a1;
	int a2;
};
#define MEMOFFSET1(Class, Member) (reinterpret_cast<char*>(&static_cast<Class*>(0)->Member) - reinterpret_cast<char*>(0))
#define MEMOFFSET2(Class, Member) (reinterpret_cast<int>(&static_cast<Class*>(0)->Member))
template<class T>
int RetAddr(T addr)
{
	struct
	{
		union
		{
			int uiAddr;
			T realAddr;
		}Addr;
	}hackClassPoint;
	hackClassPoint.Addr.realAddr = addr;
	return hackClassPoint.Addr.uiAddr;
}
int main()
{
	cout << MEMOFFSET1(A, a1) << endl;//4
	cout << MEMOFFSET2(A, a2) << endl;//8

	cout << &A::a0 << endl;//1
	cout << &A::a1 << endl;//1
	cout << RetAddr(&A::a0) << endl;//0
	cout << RetAddr(&A::a2) << endl;//8

//附上强制类型转换的奇怪之处
	float fa = 1.0f;
	int ia = 1;
	int *pia = &ia;
	reinterpret_cast<int>(fa);	//error C2440: 'reinterpret_cast' : cannot convert from 'float' to 'int'
								//Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast
	reinterpret_cast<int>(pia);
	static_cast<int>(fa);
	static_cast<int>(pia);// 'static_cast' : cannot convert from 'int *' to 'int' There is no context in which this conversion is possible
}

posted on 2011-09-03 17:12  Observer  阅读(699)  评论(0编辑  收藏  举报

导航