char *再次加倍并返回char *(64位应用程序)

时间:2011-09-26 20:21:19

标签: c++ visual-c++ win32ole

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

6 个答案:

答案 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位,因此您可以在doublechar*之间进行投射。

答案 2 :(得分:1)

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

请记住,double有两个组件:尾数和指数。总之,这些允许您表示非常大或非常小的数字,但尾数具有有限的位数。如果你在尾数中用完了比特,你将会丢失你想要代表的数字中的一些比特。

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

只是不要这样做 - 它不应该起作用。

答案 3 :(得分:1)

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

  1. 从64位整数到双精度的转换可能是有损的。双精度具有53-bits的实际精度,因此2^52以上的整数(给予或取一个额外的2)不一定能准确表示。
  2. 如果您决定将指针的位重新解释为double(通过unionreinterpret_cast),如果您碰巧将指针编码为一组,则仍会出现问题不是有效双重表示的位。除非您可以保证FPU永远不会写回double值,否则FPU可以无效地将无效的double转换为另一个无效的double(请参阅NaN),即表示相同的double值值但有不同的位。 (See this for issues related to using floating point formats as bits.)
  3. 你可以安全地使用双精度编码32位指针,因为它绝对符合53位精度范围。

答案 4 :(得分:0)

  

只有最后32位是正确的。

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

答案 5 :(得分:0)

这是预期的。

通常,char*在32位系统上为32位,在64位系统上为64位;两个系统上double通常为64位。 (这些大小是典型的,对Windows来说可能是正确的;语言允许更多变化。)

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

但是你要从指针转换为整数(允许但是实现定义),然后从整数转换为double(对于有意义的数值允许和有意义 - 但转换的指针值不是数值有意义的)。你丢失了信息,因为不是所有的64位都用来表示数字的大小;通常使用11个左右的位来表示指数。

你所做的事情完全没有意义。

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