C++ 在C+中正确地将'void*'强制转换为整数+;
我正在处理一些使用外部库的代码,在这个库中,您可以通过C++ 在C+中正确地将'void*'强制转换为整数+;,c++,pointers,casting,c,C++,Pointers,Casting,C,我正在处理一些使用外部库的代码,在这个库中,您可以通过void*值将值传递给回调 不幸的是,前一个处理此代码的人决定通过将整数强制转换为void指针((void*)val)将整数传递给这些回调 我现在正致力于清理这一混乱局面,我正试图确定一种“正确”的方法,将一个整数转换为一个void*。不幸的是,修复void指针的使用有些超出了我在这里所能做的返工的范围 现在,我正在进行两次转换,以从空指针转换为空指针: static_cast<int>(reinterpret_cast<i
void*
值将值传递给回调
不幸的是,前一个处理此代码的人决定通过将整数强制转换为void指针((void*)val
)将整数传递给这些回调
我现在正致力于清理这一混乱局面,我正试图确定一种“正确”的方法,将一个整数转换为一个void*
。不幸的是,修复void指针的使用有些超出了我在这里所能做的返工的范围
现在,我正在进行两次转换,以从空指针转换为空指针:
static_cast<int>(reinterpret_cast<intptr_t>(void_p))
原始的实现确实使用了<>代码> f>“/cDe>”,但我试图摆脱它的可维护性和与bug相关的问题,所以我试图“适当”地执行这个操作,例如C++的case.< 直接转换为整型(
静态转换(void\u p)
)失败(错误:无效的静态转换从类型“void*”转换为类型“int”
)。我对reinterpret\u cast的理解是,它基本上只会导致编译器将所讨论的值的地址视为数据类型的转换,而不会实际发出任何机器代码,因此,直接将int
强制转换为void*
将是一个坏主意,因为void*
大于int
(分别为4/8字节)
我认为在这里使用intptr\t
是正确的中间方法,因为它保证足够大,可以包含void*
的整数值,一旦我得到一个整数值,我就可以截断它,而不会引起编译器抱怨
这是正确的方法吗?甚至是一种理智的方法,因为我不得不通过空指针推送数据
“这是正确的方法吗?甚至是一种理智的方法,因为我不得不通过空指针推送数据?”
好吧,关于正确和理智,它是有严重争议的,特别是如果你是代码的作者,在界面中使用void*
我认为在这里使用intptr\u t
是正确的中间方法,因为它保证足够大,可以包含void*的整数值,一旦我得到一个整数值,我就可以截断它,而不会引起编译器的抱怨
是的,这是用于重新解释\u cast
的正确类型,但您需要确保已传入intptr\u t
指针类型,并且地址有效且不超出范围
当与API交互时,遇到这个问题并不罕见,这些API提供回调,允许您传入用户数据,这些数据将由它们透明地处理,除了您的入口点1之外,永远不会被触及 因此,客户机代码需要确定如何安全地重新解释
void*
1) 这种情况的一个经典示例是函数,在这里,除了使用static和reinterpret cast之外,您别无选择。强制转换为int将导致精度损失,这是不理想的。显式强制转换总是最好避免的,因为被强制转换的内容迟早会改变,并且不会出现编译器警告。但在这种情况下,你别无选择,这是可以理解的。还是你呢 您可以将回调定义更改为intptr_t或long int,而不是void*,这样就可以工作了,您不必执行任何类型转换 我认为在这里使用
intptr\t
是正确的中间方法,因为它保证足够大,可以包含void*
的整数值,一旦我得到一个整数值,我就可以截断它,而不会引起编译器抱怨
是的,因为你提到的原因,这是合适的中间类型。到目前为止,如果您的实现没有提供它,那么您可能会遇到比缺少typedef更多的问题
这是正确的方法吗?甚至是一种理智的方法,因为我不得不通过空指针推送数据
是的,考虑到这些限制,这是非常明智的。您可以考虑检查值拟合,而不是简单地在调试模式下从“代码>空隙*<代码>中解包它,或者甚至使该整数的所有进一步处理都使用<代码> 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);
}
您应该使用哪一个取决于您需要对数据做什么,以及修改数据的功能在将来是否有用。使用
无符号长整型
或uint64_t
,使其适合64位长度指针。因此,您正在通过void*
对整型进行往返,不要反过来,对吗?使用intptr\t
是否确实解决了有关强制转换错误的问题?事实上,它是正确的类型。@Deduplicator-yesp。以int
开头,以int
结尾。它必须通过一个只接受void*
的库,
error: cast from 'void*' to 'int' loses precision [-fpermissive]
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);
}