我正在尝试将char *转换为double并再次转换为char *。如果您创建的应用程序是32位但不适用于64位应用程序,则以下代码可以正常工作。当您尝试从int转换回char *时会发生此问题。例如,如果hello = 0x000000013fcf7888然后转换为0x000000003fcf7888,则只有最后32位是正确的。
#include <iostream>
#include <stdlib.h>
#include <tchar.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
char* hello = "hello";
unsigned int hello_to_int = (unsigned int)hello;
double hello_to_double = (double)hello_to_int;
cout<<hello<<endl;
cout<<hello_to_int<<"\n"<<hello_to_double<<endl;
unsigned int converted_int = (unsigned int)hello_to_double;
char* converted = reinterpret_cast<char*>(converted_int);
cout<<converted_int<<"\n"<<converted<<endl;
getchar();
return 0;
}
答案 0 :(得分:6)
在64位Windows指针上是64位而int
是32位。这就是您在投射时丢失高32位数据的原因。而不是int
使用long long
来保存中间结果。
char* hello = "hello";
unsigned long long hello_to_int = (unsigned long long)hello;
对逆转换进行类似的更改。但是这并不能保证转换功能正常,因为double可以很容易地表示整个32位整数范围而不会丢失精度,但对于64位整数则不一样。
此外,这不会起作用
unsigned int converted_int = (unsigned int)hello_to_double;
该转换将简单地截断浮点表示中小数点后的任何数字。即使您将数据类型更改为unsigned long long
,问题仍然存在。您需要reinterpret_cast<unsigned long long>
才能使其正常运行。
即便如此,根据指针的值,您仍可能遇到麻烦。转换为double
可能导致该值为信令NaN ,其中导致您的代码可能抛出异常。
简单的答案是,除非你是为了好玩而尝试这一点,否则不要做这样的转换。
答案 1 :(得分:2)
您无法在64位Windows上将char*
强制转换为int
,因为int
为32位,而char*
为64位,因为它是指针。由于double
始终为64位,因此您可以在double
和char*
之间进行投射。
答案 2 :(得分:1)
如果它适用于任何系统,任何地方,只有你自己幸运并继续前进。将指针转换为整数是一回事(只要整数足够大,你就可以侥幸逃脱),但是double是一个浮点数 - 你所做的只是没有任何意义,因为double不一定能代表任何随机数。双精度具有范围和精度限制,并限制它如何表示事物。它可以表示各种值的数字,但不能代表该范围内的每个数字。
请记住,double有两个组件:尾数和指数。总之,这些允许您表示非常大或非常小的数字,但尾数具有有限的位数。如果你在尾数中用完了比特,你将会丢失你想要代表的数字中的一些比特。
显然你在某些情况下侥幸逃脱了它,但是你要求它做一些它没有做的事情,而且显然是不合适的。
只是不要这样做 - 它不应该起作用。
答案 3 :(得分:1)
将任何整数(特别是位集合)编码为浮点值的几个问题:
2^52
以上的整数(给予或取一个额外的2)不一定能准确表示。double
(通过union
或reinterpret_cast
),如果您碰巧将指针编码为一组,则仍会出现问题不是有效双重表示的位。除非您可以保证FPU永远不会写回double
值,否则FPU可以无效地将无效的double转换为另一个无效的double(请参阅NaN),即表示相同的double值值但有不同的位。 (See this for issues related to using floating point formats as bits.) 你可以安全地使用双精度编码32位指针,因为它绝对符合53位精度范围。
答案 4 :(得分:0)
只有最后32位是正确的。
这是因为您平台中的int
只有32位长。请注意,reinterpret_cast
仅保证您可以将指针转换为足够大小的int(不是您的情况),然后返回。
答案 5 :(得分:0)
这是预期的。
通常,char*
在32位系统上为32位,在64位系统上为64位;两个系统上double
通常为64位。 (这些大小是典型的,对Windows来说可能是正确的;语言允许更多变化。)
据我所知,从指针到浮点类型的转换是未定义的。这并不仅仅意味着转换的结果是不确定的;尝试执行此类转换的程序的行为未定义。如果你很幸运,程序将崩溃或无法编译。
但是你要从指针转换为整数(允许但是实现定义),然后从整数转换为double(对于有意义的数值允许和有意义 - 但转换的指针值不是数值有意义的)。你丢失了信息,因为不是所有的64位都用来表示数字的大小;通常使用11个左右的位来表示指数。
你所做的事情完全没有意义。
你到底想要完成什么?不管它是什么,肯定有更好的方法。