我有一个原型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
投这方法的正确方法是什么?
答案 0 :(得分:61)
您可以将其转换为intptr_t
类型。它是int
类型,保证足够大以包含指针。使用#include <cstdint>
进行定义。
答案 1 :(得分:26)
同样,上面的所有答案都严重错过了这一点。 OP想要将指针值转换为int值,相反,大多数答案,无论是哪种方式,都试图将arg点的内容错误地转换为int值。而且,其中大部分都不适用于gcc4。
正确答案是,如果不介意丢失数据精确度,
int x = *((int*)(&arg));
这适用于GCC4。
最好的方法是,如果可以的话,不要进行这样的转换,相反,如果必须为指针和int共享相同的内存地址(例如,为了保存RAM),请使用union,并确保,如果mem只有当您知道它最后设置为int时,才将地址视为int。
答案 2 :(得分:11)
在一般情况下,没有正确的方法将其强制转换为int
。 C99标准库提供了intptr_t
和uintptr_t
typedef,它们应该在需要执行此类转换时使用。如果您的标准库(即使它不是C99)恰好提供这些类型 - 请使用它们。如果没有,请检查平台上的指针大小,自己定义这些typedef并使用它们。
答案 3 :(得分:8)
而不是:
int x = (int)arg;
使用:
int x = (long)arg;
在大多数平台上,指针和长整数的大小相同,但是在64位平台上,整数和指针的大小通常不同。如果您将(void*
)转换为(long
)没有精度丢失,那么通过将(long
)分配给(int
),它会正确地将数字截断为配合。
答案 4 :(得分:7)
将指针转换为void *并返回有效使用reinterpret_cast&lt;&gt;。所以你可以这样做:
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调用进行更改以创建线程。
我想强调的是,当你从一个平台移动到另一个平台时,从int转换为指针再返回可能会出现问题。但是,将指针转换为void *并再次返回可以得到很好的支持(无处不在)。
因此,结果可能不太容易错误地生成指针并且使用它。 记得在使用后删除指针,这样我们就不会泄漏。
答案 5 :(得分:4)
而不是使用长投射,你应该施放到size_t。
int val =(int)((size_t)arg);
答案 6 :(得分:3)
正确的方法是将其投射到另一个pointer type
。将void*
转换为int
是不可移植的方式,可能有效,也可能无效!如果您需要保留返回的地址,请将其保留为void*
。
答案 7 :(得分:2)
我也遇到了这个问题。
ids [i] =(int)arg; //这里发生错误=&gt;我将此更改为以下内容。
ids [i] =(uintptr_t)arg;
然后我可以继续编译。也许你也可以尝试一下。
答案 8 :(得分:1)
没有“正确”的方法将64位指针存储在32位整数中。问题不在于强制转换,而是目标类型丢失指针的一半。存储在int
内的32个剩余比特不足以重建指向线程函数的指针。大多数答案只是试图从论证中提取32个无用的位。
正如Ferruccio所说,int必须替换为intptr_t
才能使程序有意义。
答案 9 :(得分:1)
我会创建一个结构并将其作为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()使用它。
答案 10 :(得分:1)
最安全的方式:
static_cast<int>(reinterpret_cast<long>(void * your_variable));
long
保证Linux在任何机器上的指针大小。 Windows在64位上也只有32位长。因此,您需要在Windows中为64位将其更改为long long
而不是long
。
因此,reinterpret_cast
已将其转换为long
类型,然后static_cast
安全地将long
转换为int
,如果您准备好,请截断数据。
答案 11 :(得分:1)
如果你像这样调用你的线程创建函数
pthread_create(&thread, NULL, myFcn, reinterpret_cast<void*>(5));
然后void*
到达myFcn
内的int
具有您放入其中的int myData = reinterpret_cast<int>(arg);
的值。所以你知道你可以像这样把它丢回来
myFcn
即使编译器不知道你只是将pthread_create
与sizeof(void*)>=sizeof(int)
一起传递给整数。
修改:
正如马丁所指出的,这假设{{1}}。如果您的代码有机会被移植到某个不能保持的平台,那么这将无效。
答案 12 :(得分:0)
//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;
希望这有帮助
答案 13 :(得分:0)
你可能想要的是
int x = reinterpret_cast<int>(arg);
这允许您将void *
重新解释为int
。
答案 14 :(得分:0)
就我而言,我使用的是32位值,需要传递给OpenGL函数,作为void *表示缓冲区的偏移量。
您不能只将32位变量强制转换为指针,因为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);
答案 15 :(得分:0)
不要将您的int作为void*
传递,将int*
传递给int
,这样您就可以将void*
转换为int*
并且将解除引用的指针复制到int
。
int x = *static_cast<int*>(arg);
答案 16 :(得分:0)
函数指针与void *(以及任何其他非函数指针)
不兼容答案 17 :(得分:-3)
这样做是因为您将64位指针转换为32位整数,因此您会丢失信息。
你可以使用64位整数代替howerver我通常使用一个带有正确原型的函数,然后我转换函数类型: 例如
void thread_func(int arg){
...
}
我创建了这样的线程:
pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);