C++ 错误:从“void*”转换为“int”失去精度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1640423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
error: cast from 'void*' to 'int' loses precision
提问by Joshua D. Boyd
I have a function with prototype void* myFcn(void* arg)
which is used as the starting point for a pthread. I need to convert the argument to an int for later use:
我有一个带有原型的函数,void* myFcn(void* arg)
用作 pthread 的起点。我需要将参数转换为 int 以供以后使用:
int x = (int)arg;
The compiler (GCC version 4.2.4) returns the error:
编译器(GCC 版本 4.2.4)返回错误:
file.cpp:233: error: cast from 'void*' to 'int' loses precision
What is the proper way to cast this?
投射这个的正确方法是什么?
回答by Ferruccio
You can cast it to an intptr_t
type. It's an int
type guaranteed to be big enough to contain a pointer. Use #include <cstdint>
to define it.
您可以将其强制转换为intptr_t
类型。它是一种int
保证足够大以包含指针的类型。使用#include <cstdint>
来定义它。
回答by onlooker
Again, all of the answers above missed the point badly. The OP wanted to convert a pointer value to a int value, instead, most the answers, one way or the other, tried to wrongly convert the content of arg points to to a int value. And, most of these will not even work on gcc4.
同样,上述所有答案都严重错过了这一点。OP 希望将指针值转换为 int 值,相反,大多数答案,以一种或另一种方式,试图错误地将 arg 点的内容转换为 int 值。而且,其中大部分甚至不适用于 gcc4。
The correct answer is, if one does not mind losing data precision,
正确答案是,如果不介意丢失数据精度,
int x = *((int*)(&arg));
This works on GCC4.
这适用于 GCC4。
The best way is, if one can, do not do such casting, instead, if the same memory address has to be shared for pointer and int (e.g. for saving RAM), use union, and make sure, if the mem address is treated as an int only if you know it was last set as an int.
最好的方法是,如果可以的话,不要进行这样的转换,相反,如果必须为指针和 int 共享相同的内存地址(例如为了节省 RAM),请使用 union,并确保是否处理了 mem 地址仅当您知道它最后设置为 int 时才作为 int。
回答by AnT
There's no proper way to cast this to int
in general case. C99 standard library provides intptr_t
and uintptr_t
typedefs, which are supposed to be used whenever the need to perform such a cast comes about. If your standard library (even if it is not C99) happens to provide these types - use them. If not, check the pointer size on your platform, define these typedefs accordingly yourself and use them.
int
在一般情况下,没有正确的方法可以将其转换为。C99 标准库提供intptr_t
和uintptr_t
typedef,它们应该在需要执行此类转换时使用。如果您的标准库(即使不是 C99)恰好提供了这些类型 - 使用它们。如果没有,请检查您平台上的指针大小,自己相应地定义这些 typedef 并使用它们。
回答by Joshua D. Boyd
Instead of:
代替:
int x = (int)arg;
use:
用:
int x = (long)arg;
On most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms. If you convert (void*
) to (long
) no precision is lost, then by assigning the (long
) to an (int
), it properly truncates the number to fit.
在大多数平台上,指针和长整型的大小相同,但整数和指针在 64 位平台上的大小通常不同。如果将 ( void*
)转换为 ( long
) 不会丢失精度,那么通过将 ( long
)分配给( int
),它会正确截断数字以适合。
回答by Martin York
Casting a pointer to void* and back is valid use of reinterpret_cast<>. So you could do this:
将指针投射到 void* 并返回是 reinterpret_cast<> 的有效使用。所以你可以这样做:
pthread_create(&thread, NULL, myFcn, new int(5)); // implicit cast to void* from int*
Then in myFcn:
然后在 myFcn 中:
void* myFcn(void* arg)
{
int* data = reinterpret_cast<int*>(arg);
int x = *data;
delete data;
Note: As sbi points out this would require a change on the OP call to create the thread.
注意:正如 sbi 指出的那样,这需要更改 OP 调用以创建线程。
What I am trying to emphasis that conversion from int to pointer and back again can be frough with problems as you move from platform to platform. BUT converting a pointer to void* and back again is well supported (everywhere).
我想强调的是,当您从一个平台移动到另一个平台时,从 int 到指针再返回的转换可能会遇到问题。但是很好地支持将指针转换为 void* 并再次返回(无处不在)。
Thus as a result it may be less error prone to generate a pointer dynamcially and use that. Remembering to delete the pointer after use so that we don't leak.
因此,动态生成指针并使用它可能不太容易出错。记住在使用后删除指针,这样我们就不会泄漏。
回答by Georg
Instead of using a long
cast, you should cast to size_t
.
而不是使用long
强制转换,您应该强制转换为size_t
.
int val= (int)((size_t)arg);
回答by Muhammad Aamir Ali
I meet this problem too.
我也遇到这个问题。
ids[i] = (int) arg; // error occur here => I change this to below.
ids[i] = (uintptr_t) arg;
Then I can continue compiling. Maybe you can try this too.
然后我可以继续编译。也许你也可以试试这个。
回答by AraK
The proper way is to cast it to another pointer type
. Converting a void*
to an int
is non-portable way that may work or may not! If you need to keep the returned address, just keep it as void*
.
正确的方法是将其转换为另一个pointer type
. 将 a 转换void*
为 anint
是不可移植的方式,可能有效也可能无效!如果您需要保留返回的地址,只需将其保留为void*
.
回答by MKaama
There is no "correct" way to store a 64-bit pointer in an 32-bit integer. The problem is not with casting, but with the target type loosing half of the pointer. The 32 remaining bits stored inside int
are insufficient to reconstruct a pointer to the thread function. Most answers just try to extract 32 useless bits out of the argument.
没有“正确”的方法可以将 64 位指针存储在 32 位整数中。问题不在于强制转换,而在于目标类型丢失了一半的指针。内部存储的 32 位剩余位int
不足以重建指向线程函数的指针。大多数答案只是尝试从参数中提取 32 个无用的位。
As Ferrucciosaid, int must be replaced with intptr_t
to make the program meaningful.
正如Ferruccio所说, int 必须被替换intptr_t
为使程序有意义。
回答by Akos Hamori
I would create a structure and pass that as void* to pthread_create
我会创建一个结构并将其作为 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;
...
}
Keep in mind that thrArgshould exist till the myFcn()uses it.
请记住,thrArg应该一直存在,直到myFcn()使用它为止。