76

我有一个带有原型的函数,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

投射这个的正确方法是什么?

4

18 回答 18

71

您可以将其转换为intptr_t类型。它是一种int保证足够大以包含指针的类型。用来#include <cstdint>定义它。

于 2009-10-28T22:13:40.370 回答
35

同样,以上所有答案都严重错过了重点。OP 想要将指针值转换为 int 值,相反,大多数答案都试图错误地将 arg 点的内容转换为 int 值。而且,其中大多数甚至无法在 gcc4 上运行。

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

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

这适用于 GCC4。

最好的方法是,如果可以,不要进行这种转换,相反,如果必须为指针和 int 共享相同的内存地址(例如,为了节省 RAM),请使用 union,并确保是否处理了 mem 地址仅当您知道它最后设置为 int 时才作为 int。

于 2011-08-26T13:37:25.300 回答
14

代替:

int x = (int)arg;

利用:

int x = (long)arg;

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

于 2009-10-28T22:09:13.143 回答
13

int在一般情况下,没有适当的方法可以将其转换为。C99 标准库提供intptr_tuintptr_ttypedef,应该在需要执行此类转换时使用。如果您的标准库(即使它不是 C99)碰巧提供了这些类型 - 请使用它们。如果没有,请检查您平台上的指针大小,自己定义这些类型定义并使用它们。

于 2009-10-28T22:38:36.190 回答
8

将指针转换为 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 调用以创建线程。

我要强调的是,当您从一个平台移动到另一个平台时,从 int 到指针再返回的转换可能会遇到问题。但是(在任何地方)都很好地支持将指针转换为 void* 并再次返回。

因此,结果是动态生成指针并使用它可能不太容易出错。记住在使用后删除指针,这样我们就不会泄漏。

于 2009-10-28T22:28:09.597 回答
7

而不是使用long强制转换,您应该强制转换为size_t.

int val= (int)((size_t)arg);
于 2013-09-04T11:04:29.893 回答
5

我也遇到这个问题。

ids[i] = (int) arg; // error occur here => I change this to below.

ids[i] = (uintptr_t) arg;

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

于 2014-04-03T06:45:09.260 回答
3

正确的方法是将其转换为另一个pointer type. 将 a 转换void*为 anint是不可移植的方式,可能有效也可能无效!如果您需要保留返回的地址,只需将其保留为void*.

于 2009-10-28T22:06:03.530 回答
2

最安全的方式:

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

long保证任何机器上 Linux 上的指针大小。Windows 也只有 64 位的 32 位。因此,您需要将其更改为long long而不是long在 windows 中为 64 位。因此reinterpret_cast,已将其转换为longtype ,然后static_cast安全地转换longint,如果您准备好截断数据。

于 2011-04-07T10:21:16.723 回答
2

没有“正确”的方式将 64 位指针存储在 32 位整数中。问题不在于强制转换,而在于目标类型丢失了一半的指针。内部存储的 32 个剩余位int不足以重建指向线程函数的指针。大多数答案只是试图从论点中提取 32 个无用的位。

正如Ferruccio所说,必须将 int 替换为intptr_t才能使程序有意义。

于 2017-02-25T13:07:16.220 回答
1

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

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

然后void*到达的内部myFcn具有int您放入其中的值。所以你知道你可以像这样把它扔回去

int myData = reinterpret_cast<int>(arg);

即使编译器不知道您只与整数一起传递myFcnpthread_create

编辑

正如 Martin 所指出的,这假定sizeof(void*)>=sizeof(int). 如果您的代码有机会被移植到某些平台上,而这并不适用,那么这将行不通。

于 2009-10-28T22:33:36.450 回答
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()使用它。

于 2015-02-05T12:09:38.773 回答
0

你可能想要的是

int x = reinterpret_cast<int>(arg);

这允许您将 重新解释void *int.

于 2009-10-28T22:28:53.543 回答
0

在我的例子中,我使用了一个 32 位的值,该值需要作为 void * 传递给 OpenGL 函数,表示缓冲区的偏移量。

您不能只将 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);
于 2014-07-30T07:07:09.103 回答
0

不要将您的 int 作为 avoid*传递,将 a 传递int*给您的int,因此您可以将 the 强制void*转换为 anint*并将取消引用的指针复制到您的int.

int x = *static_cast<int*>(arg);
于 2009-10-28T22:23:44.503 回答
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;

希望这可以帮助

于 2010-11-05T18:42:42.087 回答
0

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

于 2015-07-29T19:53:45.313 回答
-3

之所以这样做,是因为您将 64 位指针转换为 32 位整数,因此您会丢失信息。

您可以使用 64 位整数来代替,但是我通常使用具有正确原型的函数并转换函数类型:例如。

void thread_func(int arg){
...
}

我创建这样的线程:

pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);
于 2009-10-28T22:22:39.860 回答