Muc*_*ewe 5 c++ double char reinterpret-cast
今天我正在玩C++,并且遇到了这个我认为奇怪的事情,但也许更可能是由于我的误解和最近缺乏纯C编码.
我原本想要做的是将double转换为无符号字符数组.我的理解是double的64位(sizeof(double)是8)现在将表示为8个8位字符.要做到这一点,我使用reinterpret_cast.
所以这里有一些代码可以从double转换为char数组,或者至少我认为这就是它正在做的事情.问题是它从strlen而不是8返回15,为什么我不确定.
double d = 0.3;
unsigned char *c = reinterpret_cast<unsigned char*> ( &d );
std::cout << strlen( (char*)c ) << std::endl;
Run Code Online (Sandbox Code Playgroud)
因此strlen是我的第一个问题.但后来我尝试了以下内容,发现它返回了11,19,27,35.这些数字之间的差异是8,所以在某种程度上正确的事情正在发生.但为什么这不会返回15,15,15,15,(因为它在上面的代码中返回15).
double d = 0.3;
double d1 = 0.3;
double d2 = 0.3;
double d3 = 0.3;
unsigned char *c_d = reinterpret_cast<unsigned char*> ( &d );
unsigned char *c_d1 = reinterpret_cast<unsigned char*> ( &d1 );
unsigned char *c_d2 = reinterpret_cast<unsigned char*> ( &d2 );
unsigned char *c_d3 = reinterpret_cast<unsigned char*> ( &d3 );
std::cout << strlen( (char*)c_d ) << std::endl;
std::cout << strlen( (char*)c_d1 ) << std::endl;
std::cout << strlen( (char*)c_d2 ) << std::endl;
std::cout << strlen( (char*)c_d3 ) << std::endl;
Run Code Online (Sandbox Code Playgroud)
所以我查看了字符的地址,它们是.
0x28fec4
0x28fec0
0x28febc
0x28feb8
Run Code Online (Sandbox Code Playgroud)
现在这是有意义的,因为我的系统上的unsigned char*的大小是4个字节,但我认为将从强制转换中分配正确的内存量,否则看起来reinterpret_cast是一个非常危险的事情......此外,如果我做
for (int i = 0; i < 4; ++i) {
double d = 0.3;
unsigned char *c = reinterpret_cast<unsigned char*> ( &d );
std::cout << strlen( (char*)c ) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这打印11,11,11,11!
那么这里发生了什么,显然内存被覆盖的地方被重写并且重新解释强制转换并不像我想象的那样(即我使用它错了).在C++中使用字符串这么长时间,有时当你回到原始字符数组时,你会忘记这些事情.
所以我想这是一个3部分的问题.
为什么strlen最初会回来15?为什么4个strlen调用的大小增加?为什么循环返回11,11,11,11?
谢谢.
Jos*_*eld 11
strlen通过迭代遍历它所采用的传递const char*点的数组来工作,直到它找到char值为0.这是一个空终止字符,它自动添加到字符串文字的末尾.组成您的值表示的字节double不以空字符结尾.将strlen只会继续下去,你过去的结束double对象,直到它找到一个字节值为0.
考虑字符串文字"Hello".在内存中,使用ASCII兼容的执行字符集,它将存储为以下字节(十六进制):
48 65 6c 6c 6f 00
Run Code Online (Sandbox Code Playgroud)
strlen将读取它们中的每一个,直到找到具有值的字节0并报告它到目前为止看到的字节数.
IEEE 754双精度表示法0.3是:
3F D3 33 33 33 33 33 33
Run Code Online (Sandbox Code Playgroud)
如您所见,没有带有值的字节0,所以strlen只是不知道何时停止.
无论函数返回什么值,可能只是它在内存中找到0之前得到的距离,但是你已经达到了未定义的行为,所以对它进行任何猜测都是没有意义的.
你的问题是你的使用strlen( (char*)c ),因为strlen需要一个指向以null结尾的字符串的指针.
看起来你期望在第8和第9字节之间存在某种"边界",因为前8个字节最初是a double.
一旦你将内存转换为a,那么这些信息就会丢失char*.您的代码有责任知道char有效的数量.