使用reinterpret_cast从char*返回long long

Using reinterpret_cast to return long long from char*

本文关键字:long 返回 char reinterpret cast 使用      更新时间:2023-10-16

我有以下代码:

char* p = "12345";
long long x = *reinterpret_cast<long long*>(p);

和我一直得到228509037105 x -我期待12345。

我做错了什么?

更新:

由于我最初的理解,我问错了问题。然而,从我后来被告知有可能从使用reinterpret_cast的字符数组读取8个字节!毕竟,无论位是指向一个值还是指向一个指针,它们在位级别上都是一样的!

指针的reinterpret_cast强制编译器以不同的数据类型重新解释内存地址。要将字符串"12345"转换为长12345,您需要转换数字:

#include <sstream>
long long str2ll(const char* p) {
    std::sstream ss;
    ss << p;
    long long r;
    ss >> r;
    return r;
}

正如chris在评论中所说,在c++ 11中你可以使用std::stoll:

const char* p = "12345";
long long n = std::stoll(std::string(p));

更新:您可以从8字节的内存中读取long long,但是字符串"12345678"重新解释为long long指针将不会是整数"12345678",但取决于您的架构的端序:

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的十六进制表示。

您误解了reinterpret_cast的用法。请阅读reinterpret_cast的文档页面。

函数的作用如下:char* p = "12345";行创建了一个名为p的指向字符的指针变量,该变量指向一个内存区域,该区域包含一个用6字节x31x32x33x34x35x00初始化的常量缓冲区。当您将这个变量p传递给printf时,它会将p指向的内存解释为一个以空结束的字符串,并打印"12345"。

long long x = *reinterpret_cast<long long*>(p);行创建了一个指向long-long的临时指针,初始化为p的值,这意味着它指向与p相同的内存区域(根据上面链接中的案例6,这实际上是未定义的行为),然后对其解引用并将值赋给x。因为long long通常是8字节长,而p只指向6个有效字节,所以这种解引用也是未定义的行为,但是您得到的是228509037105(二进制0x3534333231),这意味着您的机器是小端,额外的2个字节也是0。

如果你想得到x == 12345,正确的方法是long long x = std::stoll(p)

你也误解了这样一个事实:"然而,从我后来被告知的情况来看,使用reinterpret_cast从char数组读取8个字节是可能的"。您可以做的是将char*值转换为long long值,假设您的机器上的sizeof void*不大于sizeof(long long)(参见上面链接中的案例2)。如果sizeof void*等于8,那么你正在"从'char数组'中读取8个字节(实际上是从指针到char):long long x = reinterpret_cast<long long>(p)。这给了你p最初包含的地址,作为long long值存储在变量x中。你对这个值所做的任何事情,除了将其转换回char*,都是未定义的行为。例如,您可以执行printf(reinterpret_cast<char*>(x)),它将打印原始字符缓冲区"12345"。

底层字节为1,2,3,4 and 5的ascii值的0x31, 0x32, 0x33, 0x34 and 0x35。把你收到的值转换成十六进制,你就会明白我在说什么了。

reinterpret_cast通常用于指针类型之间的转换或到另一个整型之间的转换。例如,可以将指针转换为数字,然后使用sprintf输出值,使用整数格式说明符之一而不是指针说明符