首先让我说我知道下面的代码会被认为是“坏”的做法..但是我受到环境的限制“一点点”:
在动态库中我希望使用“指针”(指向类) - 但是使用此dll的程序只能通过&获得双打。所以我需要将指针“装入”双精度。下面的代码试图实现这一点,我希望在64位环境中工作:
EXPORT double InitializeClass() {
SampleClass* pNewObj = new SampleClass;
double ret;
unsigned long long tlong(reinterpret_cast<unsigned long long>(pNewObj));
memcpy(&ret, &tlong, sizeof(tlong));
return ret;
}
EXPORT double DeleteClass(double i) {
unsigned long long tlong;
memcpy(&tlong, &i, sizeof(i));
SampleClass* ind = reinterpret_cast<SampleClass* >(tlong);
delete ind;
return 0;
}
现在我又一次意识到我可能会更好地使用矢量&amp;将指针存储在向量内。但是我真的希望使用指针(作为替代)来做到这一点。那么有谁可以告诉我可能的失败/更好的版本?
明显的失败是如果双重&amp; unsigned long long的大小不同(或指针长度超过64位)。有没有一种方法可以在编译时检查这个? - 如果大小不一样,给出编译错误?
答案 0 :(得分:2)
理论上,至少是一个64位指针,类型被削减为64位IEEE 加倍,可能导致陷阱NaN,这反过来陷阱。在 练习,这可能不是问题;我试图捕获NaN 实际做一些不被忽视的事情并非如此 成功的。
另一个可能的问题是值可能未标准化 (事实上,可能不会)。硬件的功能 非标准化值取决于:它可以直接传递它们 透明地,默默地将它们标准化(改变它的值) “指针”),或触发某种运行时错误。
还存在别名问题。通过一个访问指针
类型为double
的左值是未定义的行为,很多
假设,编译器在优化时会利用这一点
通过double*
或double&
引用进行的更改不会影响任何内容
指针(并在写入之前移动指针的负载)
修改后的双重或不重新加载指针
双)。
在实践中,如果您在英特尔环境中工作,我想全部 “64位”指针实际上将具有高16位0.这就是位置 指数居于IEEE双精度,指数为0是渐进的 下溢,不会陷阱(至少在默认模式下),也不会 变化。所以你的代码实际上似乎可以工作,只要 编译器没有太多优化。
答案 1 :(得分:1)
assert(sizeof(SampleClass*) <= sizeof(unsigned long long));
assert(sizeof(unsigned long long) <= sizeof(double));
答案 2 :(得分:0)
我会说你必须在64位和32位测试它以确保它有效。假设它在64位系统中确实有不同的行为,那么您可以使用这种格式来解决问题(因为您已经提到过您正在使用VS2010):
EXPORT double InitializeClass64() {
// Assert the pointer-size is the same as the data-type being used
assert(sizeof(void*) == sizeof(double));
// 64-bit specific code
return ret;
}
EXPORT double DeleteClass64(double i) {
// Assert the pointer-size is the same as the data-type being used
assert(sizeof(void*) == sizeof(double));
// 64-bit specific code
return 0;
}
EXPORT double InitializeClass32() {
// Assert the pointer-size is the same as the data-type being used
assert(sizeof(void*) == sizeof(double));
// 32-bit specific code
return ret;
}
EXPORT double DeleteClass32(double i) {
// Assert the pointer-size is the same as the data-type being used
assert(sizeof(void*) == sizeof(double));
// 32-bit specific code
return 0;
}
#if defined(_M_X64) || defined(_M_IA64)
// If it's 64-bit
# define InitializeClass InitializeClass64
# define DeleteClass DeleteClass64
#else
// If it's 32-bit
# define InitializeClass InitializeClass32
# define DeleteClass DeleteClass32
#endif // _M_X64 || _M_IA64