正确地将“void*”转换为 C++ 中的整数
Properly casting a `void*` to an integer in C++
我正在处理一些使用外部库的代码,您可以在其中通过void*
值将值传递给回调。
不幸的是,处理此代码的上一个人员决定通过将整数转换为 void 指针 ( (void*)val
来将整数传递给这些回调。
我现在正在努力清理这个烂摊子,我正在尝试确定将整数转换为/从void*
转换的"正确"方法。不幸的是,修复 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*
的整数值,一旦我有一个整数值,我就可以截断它而不会导致编译器抱怨。
这是正确的,甚至是理智的方法,因为我不得不通过空指针推送数据?
我认为在这里使用
intptr_t
是正确的中间人,因为它保证足够大以包含void*
的整数值,一旦我有一个整数值,我就可以截断它而不会导致编译器抱怨。
是的,由于您提到的原因,这是正确的中间类型。到目前为止,如果你的实现没有提供它,你可能有更多的问题,而不仅仅是缺少 typedef。
是的,这是正确的,甚至是理智的方法,因为我不得不通过空指针推送数据?
考虑到限制,这是非常理智的。
您可以考虑检查值是否合适,而不是在调试模式下从void*
中解压缩时简单地截断它,甚至使该整数的所有进一步处理都使用intptr
而不是int
以避免截断。
您还可以考虑通过该参数将指针推送到实际int
而不是int
本身。请注意,效率较低,并且会让您面临终身问题。
根据您的问题,我假设您在某个库中调用一个函数,void*
传递它,然后在稍后的某个时间点,它调用您的一个函数,以相同的void*
传递它。
基本上有两种可能的方法可以做到这一点;第一种是通过显式强制转换,如您在当前代码中所示。
另一个,重复数据删除器提到,效率稍低,但允许您保持对数据的控制,并可能在调用库函数和调用回调函数之间修改数据。这可以通过类似于下面的代码来实现:
void callbackFunction(void* dataPtr){
int data = *(int*)dataPtr;
/* DO SOMETHING WITH data */
delete dataPtr;
}
void callLibraryFunction(int dataToPass){
int* ptrToPass = new int(dataToPass);
libraryFunction(ptrToPass,callbackFunction);
}
应该使用哪一个取决于您需要对数据执行的操作,以及修改数据的能力将来是否有用。
"这是正确的,还是一个理智的方法,因为我不得不通过一个空白指针推送数据?"
好吧,关于正确和理智,这是值得商榷的,特别是如果您是在界面中void*
的代码的作者。
我认为在这里使用
intptr_t
是正确的中间人,因为它保证足够大以包含 void* 的整数值,一旦我有一个整数值,我就可以截断它而不会导致编译器抱怨。
是的,这是与reinterpret_cast<intptr_t>
一起使用的正确类型,但您需要确定,intptr_t
指针类型已传入,并且地址有效且不会超出范围。
在与 c API 交互时,偶然发现这个问题并不罕见,这些回调允许您传入用户数据,这些数据将由它们透明地处理,并且永远不会被触及,除了您的入口点1。
因此,它由客户端代码确定如何安全地重新解释该void*
。
1)
这种情况的一个经典例子是pthread_create()
函数
你别无选择,只能在这里使用静态和重新解释强制转换。转换为 int 将导致精度损失,这从来都不是理想的。最好始终避免显式转换,因为迟早要转换的内容可能会更改,并且不会有编译器警告。但在这种情况下,您可以理解地别无选择。还是你?
您可以将这边的回调定义更改为 intptr_t 或 long int 而不是 void*,然后它应该可以工作,并且您不必进行任何类型转换......
- 如何反转整数参数包
- enum是C++中的宏变量还是整数变量
- 努力将整数转换为链表。不知道我在这里做错了什么
- 整数不会重复超过随机数
- 在C++中手动调整数组大小
- 检查输入是否不是整数或数字
- C++使用整数的压缩数组初始化对象
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 如何只允许用户输入正整数
- 如何在c++中从文本文件中逐行读取整数
- C++:如何循环通过向量中的整数元素
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 序列化,没有库的整数,得到奇怪的结果
- 在一定长度后从数组中打印时缺少整数
- std::当在256字节边界上写入整数时,流的奇怪行为
- 内联程序集printf将整数解释为地址
- 是否基于数组B整数打印数组A中的整数
- 如何在C++中将整数转换为其数字数组