[英]C++. reinterpret_cast from double to unsigned char*
我今天在C ++上玩了一段小游戏,遇到了我认为很奇怪的事情,但可能是由于我的误解以及最近缺乏纯C编码的缘故。
我最初想要做的是将一个double转换为一个无符号字符数组。 我的理解是double的64位(sizeof(double)为8)现在将表示为8个8位字符。 为此,我使用了reinterpret_cast。
因此,这里有一些代码可以从double转换为char数组,或者至少我认为这就是这样做的。 问题是它从strlen返回15,而不是8,为什么我不确定。
double d = 0.3;
unsigned char *c = reinterpret_cast<unsigned char*> ( &d );
std::cout << strlen( (char*)c ) << std::endl;
所以这是我的第一个问题。 但是,然后我尝试了以下操作,发现它返回了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;
因此,我查看了字符的地址,它们是。
0x28fec4
0x28fec0
0x28febc
0x28feb8
既然我的系统上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;
}
这将打印11、11、11、11!
因此,这里发生的事情很明显,内存在某些地方已被覆盖,并且重新解释演员表无法按我认为的那样工作(即,我使用错了)。 在C ++中使用字符串已经很长时间了,有时候回到原始字符数组时,您会忘记这些事情。
所以我想这是一个三部分的问题。
为什么最初被吓到返回15? 为什么这4个strick呼叫的大小会增加? 为什么循环返回11、11、11、11?
谢谢。
strlen
通过遍历数组(假定传递的const char*
指向该数组)直到找到一个值为0的char
来工作。这是一个以空字符结尾的字符,该字符自动添加到字符串文字的末尾。 组成double
值表示形式的字节不以空字符结尾。 strlen
会一直越过double
对象的末尾, 直到找到值0的字节为止 。
考虑字符串文字"Hello"
。 在内存中,使用与ASCII兼容的执行字符集,它将被存储为以下字节(十六进制):
48 65 6c 6c 6f 00
strlen
会通读它们中的每一个,直到找到值为0
的字节并报告到目前为止已看到多少字节。
IEEE 754的双精度表示形式为0.3
:
3F D3 33 33 33 33 33 33
如您所见,没有值0
字节,因此strlen
只是不知道何时停止。
函数返回的任何值都可能是它在内存中找到0之前的距离,但是您已经遇到了未定义的行为,因此对它进行任何猜测都是没有意义的。
您的问题是您使用strlen( (char*)c )
,因为strlen
需要一个以null终止的字符串的指针。
您似乎期望在第8个字节和第9个字节之间有某种“边界”,因为这些前8个字节最初是double
。
一旦将内存转换为char*
,该信息就会丢失。 知道多少个有效char
是您代码的责任。
有两件事:
sizeof(double)
可能不是4。通常是8。请使用运算符,而不要使用硬编码的假设。 reinterpret_cast<unsigned char*>(&d)
并不表示指向以空字符结尾的“字符串”的指针。 strlen
通过迭代直到找到null进行操作。 您在那里陷入不确定的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.