我有以下代码:
char* p = "12345";
long long x = *reinterpret_cast<long long*>(p);
我继续为x
获得228509037105 - 我当时期待12345.
我做错了什么?
更新:
由于我最初的理解,我错误地问了这个问题。但是,根据我后来的说法,可以使用reinterpret_cast
从char数组中读取8个字节!毕竟,无论位构成值还是指针,它们在位级都是相同的东西!
答案 0 :(得分:4)
reinterpret_cast
指针强制编译器重新解释不同数据类型的内存地址。要将字符串"12345"
转换为长12345
,您需要转换数字:
#include <sstream>
long long str2ll(const char* p) {
std::sstream ss;
ss << p;
long long r;
ss >> r;
return r;
}
正如评论中的克里斯所说,在C ++ 11中,您可以使用std::stoll
:
const char* p = "12345";
long long n = std::stoll(std::string(p));
更新:您可以从8个字节的内存中读取long long
,但字符串&#34; 12345678&#34;重新解释为long long
指针不会是整数&#34; 12345678&#34;但取决于endianess of your architecture:
const char* p = "12345678";
long long n = *reinterpret_cast<const long long*>(p);
std::cout << n << std::endl;
无论您使用的是小端还是大端架构,此程序都会打印4050765991979987505
或3544952156018063160
。那是因为:
hex(4050765991979987505) = 0x38 37 36 35 34 33 32 31
hex(3544952156018063160) = 0x31 32 33 34 35 36 37 38
0x38
是ASCII数字8
的十六进制表示。
答案 1 :(得分:2)
您误解了reinterpret_cast的用法。请read this documentation page for reinterpret_cast。
您的功能如下:
行char* p = "12345";
创建一个名为p
的指向char的变量,该变量指向包含用6字节\0x31\0x32\0x33\0x34\0x35\0x00
初始化的常量缓冲区的内存区域。当您将此变量p传递给例如printf时,它会将p
指向的内存解释为以null结尾的字符串,并打印&#34; 12345&#34;。
行long long x = *reinterpret_cast<long long*>(p);
创建一个用p值初始化的临时指针到long-long,这意味着它指向与p相同的内存区域(这实际上是未定义的行为,如链接中的情况6所示)上面),然后取消引用它并将值赋给x
。因为long long
通常是8个字节长,而p只指向6个有效字节,所以这个取消引用又是未定义的行为,但是你得到的是228509037105(二进制0x3534333231),这意味着你的机器是小端的,额外的2字节也是0.
如果您想获得x == 12345
,正确的方法是long long x = std::stoll(p)
。
你也误解了&#34;然而,从我后来被告知可以使用reinterpret_cast&#34;从char数组中读取8个字节。
您可以做的是将char*
值转换为long long
值,假设您的计算机上的sizeof void*
不大于sizeof(long long)
(请参阅上面链接中的案例2) 。如果sizeof void*
等于8,那么你是&#34;从&#39; char数组中读取8个字节&#39;(实际上是从指向char的指针):
long long x = reinterpret_cast<long long>(p)
。这将为您提供最初包含的p的地址,在变量x中存储为long long
值。除了将其转换回char*
之外,使用此值执行的任何操作都是未定义的行为。
例如,您可以执行printf(reinterpret_cast<char*>(x))
,它将打印您的原始字符缓冲区&#34; 12345&#34;。
答案 2 :(得分:0)
0x31, 0x32, 0x33, 0x34 and 0x35
的ascii值的基础字节为1,2,3,4 and 5
。获取您收到的价值并将其转换为十六进制,您就会看到我在说什么。
reinterpret_cast通常用于在指针类型之间转换或转换为另一种整数类型。例如,您可以将指针转换为数字,然后使用sprintf使用整数格式说明符之一而不是指针说明符输出值