1

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

6 回答 6

6

在 64 位 Windows 上,指针是 64 位的,int而是 32 位的。这就是为什么您在投射时会丢失高 32 位数据的原因。而不是int用来long long保存中间结果。

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,在这种情况下,您的代码可能会引发异常。

简单的答案是,除非您是为了好玩而尝试这样做,否则不要进行此类转换。

于 2011-09-26T20:24:32.627 回答
2

您不能在 64 位 Windows 上将 a 强制转换为,因为 anchar*是32 位,而 a是 64 位,因为它是一个指针。由于 a始终是 64 位,因此您可以避免在 a和之间进行强制转换。intintchar*doubledoublechar*

于 2011-09-26T20:24:44.987 回答
1

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

请记住,双精度数有两个组成部分:尾数和指数。总之,这些允许您表示非常大或非常小的数字,但尾数的位数有限。如果尾数中的位用完,您将在尝试表示的数字中丢失一些位。

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

只是不要那样做 - 它不应该工作。

于 2011-09-26T20:33:07.150 回答
1

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

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

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

于 2011-09-26T20:34:03.843 回答
0

只有最后 32 位是正确的。

那是因为int你平台中的 a 只有 32 位长。请注意,reinterpret_cast仅保证您可以将指针转换为足够大小的 int (不是您的情况),然后返回。

于 2011-09-26T20:24:33.843 回答
0

这正如预期的那样。

通常 achar*在 32 位系统上是 32 位,在 64 位系统上是 64 位;double在两个系统上通常是 64 位。(这些尺寸是典型的,并且可能对 Windows 是正确的;该语言允许更多的变化。)

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

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

你在做什么完全没有意义。

你到底想完成什么?不管是什么,肯定有更好的方法来做到这一点。

于 2011-09-26T20:36:21.053 回答