以下代码可能出错的地方——以及编译时间要求
What can go wrong in following code - and compile time requirements?
首先让我说我知道下面的代码将被认为是"坏的"实践。但是我受环境的限制有一点点:
在动态库中,我希望使用"指针"(指向类)-然而,将使用此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;
}
现在我再一次意识到我使用矢量可能会更好;将指针存储在vector中。然而,我真的希望使用指针(作为替代方案)来做到这一点。所以谁能告诉我可能的失败/更好的版本?
明显的失败是if double &Unsigned long和Unsigned long在大小上不相同(或者指针长度大于64位)。有没有在编译时检查这个的方法?-并给出一个编译错误,以防大小不一样?
理论上,至少,一个64位的指针,类型双关到64位的IEEEdouble,可能导致捕获NaN,而NaN又会捕获。在练习,这可能不是问题;我试图诱捕NaN除了被人忽视,真正去做点别的已经不是很好了成功。
另一个可能的问题是这些值可能没有规范化(事实上,很可能不会)。硬件做了什么非规范化值取决于:它可以直接传递它们透明地、静默地规范化它们(改变"指针"),或触发某种运行时错误。
还有混叠的问题。通过类访问指针具有double
类型的左值是未定义的行为,并且有许多编译器在优化时会利用这一点,假设通过double*
或double&
引用的更改不会影响任何一个指针(并在写入指针之前移动指针的加载)对象修改后不重新加载指针双)。
实际上,如果你在英特尔环境中工作,我认为所有"64位"指针的上16位实际上是0。这就是指数为IEEE双精度,指数为0是渐进的下流,它不会捕获(至少在默认模式下),并且不会是变化。因此,您的代码实际上可能看起来可以工作,只要
assert(sizeof(SampleClass*) <= sizeof(unsigned long long));
assert(sizeof(unsigned long long) <= sizeof(double));
我想说您必须在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
- 使用简单类型列表实现的指数编译时间.为什么
- 在已经使用Git的情况下减少编译时间
- C++常量数组的编译时间较长
- 编译时间文本到数字转换 (atoi)
- 在C++中执行 N 阶乘编译时间的 3 种不同/相同方法
- DLLexport 类模板实例(专用化),减少了仅标头模板库的编译时间
- 替换枚举以最大化编译时间检查的最佳方法
- 不同C++功能的编译时间
- 在预编译标头中实例化模板会缩短编译时间吗?
- 使用 SCons 提取每个编译单元的编译时间
- 将 lambda 函数转换为另一个编译单元中的普通函数会缩短编译时间吗?
- std :: Invoke_result_t编译时间语法错误
- 模板;constexpr;编译时间
- 如何实现声明功能-C 11,编译时间
- 如何减少编译时间:在包含未触及的头文件的情况下
- C++编译时间类型确定
- 特征:返回对具有编译时间尺寸检查的矩阵块的引用
- 在编译时间定义多个派生类
- 在编译时间创建查找表
- C 函数在编译时间返回类型