错误:从'void *'转换为'int'失去精度

我有一个原型void* myFcn(void* arg)的函数,用作pthread的起点。 我需要将参数转换为一个int以供以后使用:

 int x = (int)arg; 

编译器(GCC版本4.2.4)返回错误:

 file.cpp:233: error: cast from 'void*' to 'int' loses precision 

什么是适当的方式来施加这个?

您可以将其转换为intptr_ttypes。 这是一个inttypes,保证足够大以包含一个指针。 使用#include <cstdint>来定义它。

再一次,所有的答案都错过了这个观点。 OP想要将一个指针值转换为一个int值,相反,大多数答案是这样或那样,试图错误地将arg点的内容转换为一个int值。 而且,其中大部分甚至不会在gcc4上工作。

正确的答案是,如果不介意丢失数据的精度,

 int x = *((int*)(&arg)); 

这适用于GCC4。

最好的方法是,如果可以的话,不要做这样的转换,而是如果必须为指针和int共享相同的存储器地址(例如,用于保存RAM),请使用union,并确保如果处理了mem地址只有当你知道它最后被设置为一个int时才是int。

在一般情况下,没有正确的方法将其转换为int 。 C99标准库提供了intptr_tuintptr_t定义,当需要执行这样的uintptr_t ,应该使用它。 如果你的标准库(即使不是C99)碰巧提供了这些types – 使用它们。 如果没有,请检查您的平台上的指针大小,相应地定义这些types定义并使用它们。

代替:

 int x = (int)arg; 

使用:

 int x = (long)arg; 

在大多数平台上,指针和长整型是相同的大小,但是整数和指针在64位平台上的大小通常不一样。 如果您将( void* )转换为( long ),那么不会丢失精度,那么通过将( long )分配给( int ),它会正确地截断数字以适合。

将指针投射到void *并返回是reinterpret_cast <>的有效使用。 所以你可以这样做:

 pthread_create(&thread, NULL, myFcn, new int(5)); // implicit cast to void* from int* 

然后在myFcn:

 void* myFcn(void* arg) { int* data = reinterpret_cast<int*>(arg); int x = *data; delete data; 

注:正如sbi指出,这将需要在OP调用创build线程的变化。

我正在试图强调从int到pointer的转换,然后再返回到从平台到平台的转换。 但是,将指针转换为void *并再次返回(各处)。

因此,可能不太容易产生dynamic指针并使用它。 记住在使用后删除指针,这样我们就不会泄漏。

而不是使用长时间投射,你应该投射到size_t。

int val =(int)((size_t)arg);

正确的方法是将其转换为另一个pointer type 。 将void*转换为int是非可移植的方式,可以工作或不可以! 如果您需要保留返回的地址,请将其保留为void*

我也遇到这个问题。

ids [i] =(int)arg; / /错误发生在这里=>我改变这下面。

ids [i] =(uintptr_t)arg;

然后我可以继续编译。 也许你也可以试试这个。

如果你像这样调用你的线程创build函数

 pthread_create(&thread, NULL, myFcn, reinterpret_cast<void*>(5)); 

那么到myFcn里面的void*就有你放入的int的值。 所以你知道你可以像这样扔回去

 int myData = reinterpret_cast<int>(arg); 

即使编译器不知道你只有将myFcn传递给pthread_create和一个整数。

编辑

正如Martin指出的那样,这个假定sizeof(void*)>=sizeof(int) 。 如果你的代码有机会被移植到这个不支持的平台上,这将不起作用。

最安全的方式:

 static_cast<int>(reinterpret_cast<long>(void * your_variable)); 

在任何一台机器上,都能保证Linux上的指针大小。 Windows在64位上也有32位长。 因此,您需要在64位的窗口中将其更改为long long而不是long 。 所以reinterpret_cast把它转换成longtypes,然后static_cast安全地把long转换为int ,如果你准备好的话就截断数据。

我会创build一个结构,并将其作为void *传递给pthread_create

 struct threadArg { int intData; long longData; etc... }; threadArg thrArg; thrArg.intData = 4; ... pthread_create(&thread, NULL, myFcn, (void*)(threadArg*)&thrArg); void* myFcn(void* arg) { threadArg* pThrArg = (threadArg*)arg; int computeSomething = pThrArg->intData; ... } 

请记住, thrArg应该存在,直到myFcn()使用它。

没有“正确”的方式来存储一个32位整数的64位指针。 问题不是铸造,而是目标types丢失指针的一半。 存储在int中的32位余数不足以重build指向线程函数的指针。 大多数答案只是尝试从参数中提取32个无用的位。

正如Ferruccio所说,int必须被intptr_treplace,以使程序有意义。

你可能想要的是

 int x = reinterpret_cast<int>(arg); 

这可以让你重新解释void *作为int

 //new_fd is a int pthread_create(&threads[threads_in_use] , NULL, accept_request, (void*)((long)new_fd)); //inside the method I then have int client; client = (long)new_fd; 

希望这可以帮助

不要把你的int作为void*传递,把一个int*传递给你的int ,这样你就可以将void*成一个int*并将解引用的指针复制到你的int

 int x = *static_cast<int*>(arg); 

在我的情况下,我使用一个32位的值,需要传递给一个OpenGL函数作为一个void *代表一个缓冲区的偏移量。

你不能只将32位variables转换为指针,因为64位机器上的指针长度是原来的两倍。 你的指针的一半将是垃圾。 你需要传递一个实际的指针。

这会得到一个32位偏移的指针:

 int32 nOffset = 762; // random offset char * pOffset = NULL; // pointer to hold offset pOffset += nOffset; // this will now hold the value of 762 correctly glVertexAttribPointer(binding, nStep, glType, glTrueFalse, VertSize(), pOffset); 

函数指针与void *(以及其他非函数指针)不兼容

那么这是因为你正在转换一个64位指针到一个32位整数,所以你松散的信息。

你可以使用一个64位的整数来代替高效的我通常使用一个正确的原型的函数,我投了函数types:例如。

 void thread_func(int arg){ ... } 

我创build这样的线程:

 pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);