使用reinterpret_cast从char *返回long long

时间:2014-07-22 12:16:21

标签: c++ bits reinterpret-cast

我有以下代码:

char* p = "12345";

long long x = *reinterpret_cast<long long*>(p);

我继续为x获得228509037105 - 我当时期待12345.

我做错了什么?

更新:

由于我最初的理解,我错误地问了这个问题。但是,根据我后来的说法,可以使用reinterpret_cast从char数组中读取8个字节!毕竟,无论位构成值还是指针,它们在位级都是相同的东西!

3 个答案:

答案 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;

无论您使用的是小端还是大端架构,此程序都会打印40507659919799875053544952156018063160。那是因为:

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使用整数格式说明符之一而不是指针说明符输出值