C++ 我该如何处理;从‘;无效*’;至‘;int’;“失去精度”;在64位机器上编译32位代码时?

C++ 我该如何处理;从‘;无效*’;至‘;int’;“失去精度”;在64位机器上编译32位代码时?,c++,linux,portability,32bit-64bit,C++,Linux,Portability,32bit 64bit,我有一个可以在32位机器上编译并运行良好的软件包。我现在试图让它在64位机器上编译,并发现以下错误- error: cast from ‘void*’ to ‘int’ loses precision 是否有编译器标志来抑制这些错误?或者我必须手动编辑这些文件以避免这些强制转换吗?您必须手动编辑这些文件,以便用不太可能有缺陷和不可移植的代码替换它们。从可移植性的角度来看,将指针强制转换为int非常可怕。int的大小由编译器和体系结构的混合定义。这就是创建stdint.h头的原因,它允许您显式

我有一个可以在32位机器上编译并运行良好的软件包。我现在试图让它在64位机器上编译,并发现以下错误-

 error: cast from ‘void*’ to ‘int’ loses precision

是否有编译器标志来抑制这些错误?或者我必须手动编辑这些文件以避免这些强制转换吗?

您必须手动编辑这些文件,以便用不太可能有缺陷和不可移植的代码替换它们。

从可移植性的角度来看,将指针强制转换为int非常可怕。int的大小由编译器和体系结构的混合定义。这就是创建stdint.h头的原因,它允许您显式地声明在许多不同平台上使用的类型的大小,这些平台具有许多不同的字号


你最好使用uintpr______________________________________________________________________________(是32位整数)将保存指针值


当移动到64位时,您不能再将指针存储在int中-它不够大,无法容纳64位指针。该类型就是为此而设计的。

您不想抑制这些错误,因为它们很可能表明代码逻辑有问题

如果您抑制错误,这甚至可以工作一段时间。当指针指向前4 GB中的地址时,上面的32位将为0,并且不会丢失任何数据。但是一旦您获得大于4GB的地址,您的代码将开始“神秘地”不工作


你应该做的是修改任何可以保存指向intptr\t的指针的int。

这是一个错误,原因是:
int
在你的机器上只有
void*
的一半大,所以你不能只将
void*
存储在
int
中。你会丢失一半指针,当程序稍后试图将指针取出时,你会丢失一半如果
int
再次出现,它将不会得到任何有用的结果


即使编译器不会给出错误,代码也很可能无法工作。代码需要更改并检查64位兼容性。

抑制警告是个坏主意,但可能有编译器标志使用64位整数,具体取决于编译器和体系结构,这是解决问题的安全方法(当然,假设代码没有同时假设int是32位的)


我想,最好的解决办法仍然是修复代码,但如果是遗留的第三方代码,而且这些警告非常猖獗,我认为这种重构不能非常有效地利用您的时间。不过,绝对不要在任何新代码中使用int指针。

您的代码已被破坏。忽略警告不会减少破坏性编译器给你的

当您尝试将64位宽的指针存储到32位整数中时,您认为会发生什么情况?您的一半数据将被丢弃。我无法想象在许多情况下这样做是正确的,或者不会导致错误

修复您的代码。或者留在代码当前工作的32位平台上

如果编译器定义了
intptr\u t
uintptr\u t
,请使用它们,因为它们是保证足够大以存储指针的整数类型


如果这些类型不可用,
size\u t
ptrdiff\u t
也足够大,可以在大多数(并非所有)平台上容纳指针。或者使用
long
(在GCC编译器的64位平台上通常为64位)或
long
(大多数但并非所有编译器都支持的C99类型)在64位平台上,至少有64位宽的其他实现定义的整数类型。

< P>由当前的C++标准定义,没有保证指针的整数类型。有些平台将有一个ItPrtRT,但这不是C++的标准特征。从根本上说,处理指针的位好像是它们是一个整数,这不是一件可移植的事情(尽管它可以在许多平台上工作)

如果强制转换的原因是使指针不透明,那么void*已经实现了这一点,因此代码可以使用void*而不是int。typedef可能会使代码中的这一点更好

typedef void * handle_t;
如果强制转换的原因是使用字节粒度执行指针算法,那么最好的方法可能是强制转换到(char const*)并使用它进行计算


如果强制转换的原因是为了实现与某些无法修改的现有库(可能是较旧的回调接口)的兼容性,那么我认为您需要查看该库的文档。如果库能够支持您所需的功能(即使在64位平台上),那么它的文档可能会解决预期的解决方案。

我猜OP的情况是一个void*被用作int的通用存储,其中void*大于int。因此,例如:

int i = 123;
void *v = (void*)i;    // 64bit void* being (ab)used to store 32bit value
[..]
int i2 = (int)v;       // we want our 32bits of the 64bit void* back
编译器不喜欢最后一行

我不想讨论这样滥用void*是对还是错。如果你真的想愚弄编译器,下面的技术似乎也能奏效,即使使用-Wall:

int i2 = *((int*)&v);

在这里,它获取v的地址,将地址转换为所需数据类型的指针,然后跟随指针。

我遇到了类似的问题。我用以下方法解决了它:

 #ifdef 64BIT
 typedef uint64_t tulong;
 #else
 typedef uint32_t tulong;
 #endif

 void * ptr = NULL; //Whatever you want to keep it.
 int  i;
 i = (int)(tulong)ptr;
我认为,问题在于将指针类型转换为较短的数据类型。但对于将较大的类型转换为
int
,则效果良好

我将这个问题从键入指向
long
的指针转换为将64位整数键入到32位整数,效果很好。我还在GCC/Clang中搜索编译器选项。

//You only need this if you haven't got a definition of UInt32 from somewhere else
typedef unsigned int UInt32;

//x, when cast, points to the lower 32 bits
#define LO_32(x) (*( (UInt32 *) &x))

//address like an array to get to the higher bits (which are in position 1)
#define HI_32(x) (*( ( (UInt32 *) &x) + 1)) 
//Wherever your pointer points to
void *ptr = PTR_LOCATION 

//32-bit UInt containing the upper bits
UInt32 upper_half = HI_32(ptr); 

//32-bit UInt containing the lower bits
UInt32 lower_half = LO_32(ptr);