Char *转换为double,然后再转换回Char *(64位应用程序)
char* to double and back to char* again ( 64 bit application)
我正在尝试将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位,您可能能够在double
和char*
之间进行强制转换。
将任何整数(特别是位集合)编码为浮点值的几个问题:
- 从64位整数到双精度的转换可能是有损的。双精度类型的实际精度为53位,因此高于
- 如果你决定将指针的位重新解释为
double
而不是(通过union
或reinterpret_cast
),如果你碰巧将指针编码为一组不是有效双表示的位,你仍然会有问题。除非你能保证double
的值永远不会被FPU写回来,否则FPU可以无声地将一个无效的双精度体转换为另一个无效的双精度体(参见NaN),即一个表示相同值但具有不同位的双精度体。(有关使用浮点格式作为位的相关问题,请参阅此。)
2^52
的整数(误差额外2)不一定能精确表示。您可能可以安全地将32位指针编码为双精度类型,因为它肯定适合53位精度范围。
只有最后32位是正确的。
这是因为int
在你的平台上只有32位长。注意,reinterpret_cast
只保证可以将指针转换为足够大小的int型(不是您的情况),然后再转换回来。
如果它适用于任何系统,任何地方,只要你自己幸运,继续前进。将指针转换为整数是一回事(只要整数足够大,你就可以摆脱它),但双精度浮点数是浮点数-你所做的事情根本没有任何意义,因为双精度浮点数不一定能够表示任何随机数。双精度对象有范围和精度限制,也限制了它表示事物的方式。它可以表示广泛范围内的数值,但不能表示该范围内的每个数字。
请记住,双精度数有两个组成部分:尾数和指数。它们合在一起可以表示非常大或非常小的数字,但是尾数的位数是有限的。如果你用完了尾数中的位数,你就会失去你想要表示的数字中的一些位数。
显然你在某些情况下侥幸逃脱了,但你要求它做一些它不应该做的事情,而且它显然是不合适的。
符合预期。
通常char*
在32位系统上是32位,在64位系统上是64位;double
通常在两个系统上都是64位。(这些尺寸是典型的,可能适用于Windows;语言允许更多的变化。)
据我所知,从指针到浮点类型的转换是未定义的。这不仅意味着转换的结果是未定义的;试图执行这种转换的程序的行为是未定义的。如果幸运的话,程序会崩溃或编译失败。
但是你正在从指针转换为整型(这是允许的,但由实现定义),然后从整型转换为双精度(这对于有意义的数值是允许的并且有意义的,但是转换后的指针值没有数字意义)。你会丢失信息,因为不是所有的双精度数的64位都用来表示数字的大小;通常使用11位左右来表示指数。
你所做的完全没有意义。
你到底想要完成什么?不管是什么,肯定有更好的方法。
- 将无符号char*转换为std::istream*C++
- 为什么这个函数将"const char*"转换为"void* const"而不是"const void*"
- 将函数参数"const char*"转换为"std::string_view"是
- C ++如何在使用"tolower"时将char转换为int
- 有没有办法在C++的赋值中将"char**"转换为"double"?
- JavaCPP 错误:无法将参数"1"的"char*"转换为"Abc*
- 为什么从 char 转换为 std::byte 可能是未定义的行为?
- 如何在虚幻引擎4中将char*转换为TCHAR?
- C++:将模板类型 char 转换为 std::string
- strcmp/char* 转换无法按预期工作
- C++中的SQLite char*转换
- 无法从 const char* 转换为 const char *&
- 在 C++ 中将 char 转换为 int,而无需符号位传播
- 如果必须包含西里尔字符,如何将 char* 转换为 std::string?
- 试图使用strCMP时的char转换错误
- 无法从'const char *'转换为'LPCTSTR'
- 将 std::vector<char> 转换为字符* 会导致字符缺陷
- 使用 static_cast 将 char 转换为 int c++
- 如何在 C++(MFC) 中将 char* 转换为 LPCTSTR
- 无法将const char转换为字符串构造字符串