Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中正确地将'void*'强制转换为整数+;_C++_Pointers_Casting_C - Fatal编程技术网

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);
}