Char *转换为double,然后再转换回Char *(64位应用程序)

char* to double and back to char* again ( 64 bit application)

本文关键字:Char 转换 64位 应用程序 然后 double      更新时间:2023-10-16

我正在尝试将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;
}

在64位Windows指针是64位而int是32位。这就是为什么在强制转换时丢失上32位的数据。用long long代替int保存中间结果

char* hello = "hello";
unsigned long long hello_to_int = (unsigned long long)hello;

对反向转换进行类似的更改。但这并不能保证转换正确,因为双精度型可以很容易地表示整个32位整数范围而不会损失精度,但对于64位整数则不是这样。

同样,这是行不通的

unsigned int converted_int = (unsigned int)hello_to_double;

该转换将截断浮点表示中小数点之后的任何数字。即使您将数据类型更改为unsigned long long,问题仍然存在。你需要reinterpret_cast<unsigned long long>来让它工作。

即便如此,根据指针的值,仍然可能会遇到麻烦。转换为double可能会导致值为信号NaN,例如,在这种情况下,您的代码可能会抛出异常。

简单的答案是,除非你只是为了好玩,否则不要做这样的转换。

你不能在64位Windows上将char*转换为int,因为int是32位,而char*是64位,因为它是一个指针。由于double总是64位,您可能能够在doublechar*之间进行强制转换。

将任何整数(特别是位集合)编码为浮点值的几个问题:

    从64位整数到双精度的转换可能是有损的。双精度类型的实际精度为53位,因此高于2^52的整数(误差额外2)不一定能精确表示。
  1. 如果你决定将指针的位重新解释为double而不是(通过unionreinterpret_cast),如果你碰巧将指针编码为一组不是有效双表示的位,你仍然会有问题。除非你能保证double的值永远不会被FPU写回来,否则FPU可以无声地将一个无效的双精度体转换为另一个无效的双精度体(参见NaN),即一个表示相同值但具有不同位的双精度体。(有关使用浮点格式作为位的相关问题,请参阅此。)

您可能可以安全地将32位指针编码为双精度类型,因为它肯定适合53位精度范围。

只有最后32位是正确的。

这是因为int在你的平台上只有32位长。注意,reinterpret_cast只保证可以将指针转换为足够大小的int型(不是您的情况),然后再转换回来。

如果它适用于任何系统,任何地方,只要你自己幸运,继续前进。将指针转换为整数是一回事(只要整数足够大,你就可以摆脱它),但双精度浮点数是浮点数-你所做的事情根本没有任何意义,因为双精度浮点数不一定能够表示任何随机数。双精度对象有范围和精度限制,也限制了它表示事物的方式。它可以表示广泛范围内的数值,但不能表示该范围内的每个数字。

请记住,双精度数有两个组成部分:尾数和指数。它们合在一起可以表示非常大或非常小的数字,但是尾数的位数是有限的。如果你用完了尾数中的位数,你就会失去你想要表示的数字中的一些位数。

显然你在某些情况下侥幸逃脱了,但你要求它做一些它不应该做的事情,而且它显然是不合适的。

符合预期。

通常char*在32位系统上是32位,在64位系统上是64位;double通常在两个系统上都是64位。(这些尺寸是典型的,可能适用于Windows;语言允许更多的变化。)

据我所知,从指针到浮点类型的转换是未定义的。这不仅意味着转换的结果是未定义的;试图执行这种转换的程序的行为是未定义的。如果幸运的话,程序会崩溃或编译失败。

但是你正在从指针转换为整型(这是允许的,但由实现定义),然后从整型转换为双精度(这对于有意义的数值是允许的并且有意义的,但是转换后的指针值没有数字意义)。你会丢失信息,因为不是所有的双精度数的64位都用来表示数字的大小;通常使用11位左右来表示指数。

你所做的完全没有意义。

你到底想要完成什么?不管是什么,肯定有更好的方法。