【发布时间】:2015-08-26 10:27:29
【问题描述】:
我正在处理一些使用外部库的代码,您可以在其中通过 void* 值将值传递给回调。
不幸的是,之前编写此代码的人决定通过将整数强制转换为 void 指针 ((void*)val) 将整数传递给这些回调。
我现在正在清理这个烂摊子,我正在尝试确定将整数转换为/从void* 的“正确”方式。不幸的是,修复 void 指针的 use 有点超出了我在这里可以做的返工的范围。
现在,我正在执行两次强制转换以从/转换为 void 指针:
static_cast<int>(reinterpret_cast<intptr_t>(void_p))
和
reinterpret_cast<void *>(static_cast<intptr_t>(dat_val))
由于我在 64 位机器上,直接投射 ((int)void_p) 会导致错误:
error: cast from 'void*' to 'int' loses precision [-fpermissive]
最初的实现确实与-fpermissive一起工作,但我试图摆脱可维护性和与错误相关的问题,所以我试图“正确”地做到这一点,例如c++ 强制转换。
直接转换为 int (static_cast<int>(void_p)) 失败 (error: invalid static_cast from type 'void*' to type 'int')。我对reinterpret_cast 的理解是,它基本上只是导致编译器将有问题的值的地址视为转换为数据类型而不实际发出任何机器代码,因此将int 直接转换为void*这是个坏主意,因为void* 比int 大(分别为4/8 字节)。
我认为使用intptr_t 是正确的中间值,因为它保证足够大以包含void* 的整数值,一旦我有一个整数值,我就可以在不引起编译器抱怨的情况下截断它。
鉴于我不得不通过 void 指针推送数据,这是正确的,甚至是理智的方法吗?
【问题讨论】:
-
使用
unsigned long long int或uint64_t,使其适合 64 位长度的指针。 -
所以,您是通过
void*来回往返int,反之亦然,对吧? -
那么使用
intptr_t真的解决了关于演员阵容错误的问题吗?事实上,它是正确使用的类型。 -
@Deduplicator - 是的。以
int开头,以int结尾。它必须通过一个只接受void*的库,尽管它不会改变它们(它是一个带有 C++ 包装器的 C 库,这就是它喜欢void*的原因)。 -
@πάνταῥεῖ - 是的,它适用于
intptr_t,只是我不确定我是否从正确的角度解决了这个问题。 this question 似乎并不暗示intptr_t在这里是一个很好的方法(否则它有什么用?),但我发现的大多数其他解决方案都涉及大量返工,我真的很不舒服考虑到现有代码库的大小。