无符号字符数组转换为 long long [关闭]

Posted

技术标签:

【中文标题】无符号字符数组转换为 long long [关闭]【英文标题】:Unsigned char array casting to long long [closed] 【发布时间】:2014-01-10 15:49:49 【问题描述】:

我不确定这是否正确,我已经对其进行了测试,似乎有些字节已关闭... 基本上,我有以下几点:

unsigned char szBuffer[1024] = 0;
long long nValue = 1334553536;
memcpy(szBuffer, (char*)&nValue, sizeof(long long));

//

long long nNewValue = reinterpret_cast<long long>(szBuffer);
printf(nNewValue); //prints out a smaller number than previously stated

有人介意指出我哪里出错了吗?谢谢。

【问题讨论】:

printf 的第一个参数是格式字符串; printf(rNewValue) 可能无法编译。请贴出真实代码。 原来是std::cout,但后来我意识到我不小心添加了C标签,所以我把它改成了printf(),没有考虑它是否会编译。这只是一个微小的变化。其余的编译。 C 标签不再存在。再次,请发布真实代码,从您实际编译的内容中复制并粘贴。如果您知道代码中的哪些错误是相关的,则无需提出问题。 sscce.org 我不是根据它是否编译来问问题。我的问题是运行时的逻辑错误。但我明白你的意思,我会考虑的。我拥有的代码包含来自其他库的部分,与我的实际问题无关。因此,我试图保持简单。感谢您的关心。 是的,如果可以的话,你绝对应该简化代码并删除对外部库的依赖,但如果你不是在询问编译时错误,那么你发布的代码需要编译和运行。试图帮助您的人可能需要复制并粘贴您的代码并自己尝试(就像我一样)。你读过sscce.org吗? 【参考方案1】:

您将nNewValue 设置为szBuffer 的地址,而不是从该地址读取数据。使用:

long long nNewValue = *reinterpret_cast<long long*>(szBuffer);

【讨论】:

谢谢,这似乎有效。我想我得重新检查一下我的选角了…… 是的,它似乎起作用了。但是您怎么知道szBuffer 正确对齐以容纳long long 对象?见my answer。 我不知道——这就是为什么我要在谷歌上搜索更多关于缓冲区对齐的信息并找出你的意思。谢谢。【参考方案2】:

更改此语句

long long nNewValue = reinterpret_cast<long long>(szBuffer);

long long nNewValue = *reinterpret_cast<long long *>(szBuffer);

【讨论】:

坏主意。你怎么知道szBufferlong long 对象正确对齐? @Keith Thompson 我同意。他应该为缓冲区指定对齐方式 指定对齐方式可能不是最好的解决方案。我们不知道 OP 真正想要完成什么,但有很多更清洁的替代方案。 @Keith Thompson 你想建议使用联合吗? 我在回答中提到过使用联合。【参考方案3】:

这是您的程序的修改版本,在我的系统上运行(扩展为完整的程序):

#include <iostream>
#include <cstring>
int main() 
    unsigned char szBuffer[1024] = 0;
    long long nValue = 1334553536;
    std::memcpy(szBuffer, &nValue, sizeof(long long));
    long long nNewValue = *(reinterpret_cast<long long*>(&szBuffer));
    std::cout << nValue << "\n" << nNewValue << "\n";

memcpy的前两个参数是void*类型的,所以你不需要强制转换它们;如果您确实转换它们(C++ 中不推荐使用这种转换吗?),您应该转换为void*,而不是char*

nNewValue 的赋值将缓冲区的地址 转换为long long*,然后取消引用转换后的值。

但这是个坏主意。 g++ 给我一个关于转换指针的取消引用的警告:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

此外,不能保证szBufferunsigned char 的数组)正确对齐,因此可以安全地将其前几个字节视为long long 对象。您最有可能使用的 x86 或 x86_64 系统可以容忍未对齐的内存访问,但并非所有系统都这样做。

除非您确切地知道自己在做什么,否则指针转换通常是不安全的。

如果您想将字符数组的一部分重新解释为其他类型的对象,如果您确实需要将内存本身解释为不同类型的对象,则可以使用联合,或者使用memcpy。 (即便如此,请确保您确实需要这样做;很可能您不需要这样做。大多数情况下,如果您想存储一个 long long 对象,您应该只定义一个long long 对象。)

【讨论】:

如果你说的不安全——那我会考虑做点别的。将 long long 的值作为 ANSI 字符,sprintf() 然后进入缓冲区,然后 atoll() 将它返回到 long long 怎么样?这样会更好吗? @AndyCarter:那不会做同样的事情。首先,“ANSI 字符是 Microsoft 的 8 位字符集(例如 Windows-1252)的误称;甚至 MS 也不再这么称呼它了。没有值为 1334553536 的字符,因此这种方法行不通. 如果你的目标是获取1334553536 作为long long 值,你已经在nValue 中得到了它,不需要使用缓冲区。如果你的目标是别的,你需要告诉我们正是您想要完成的工作。(同样,请更新您的问题,向我们展示您的实际代码。) 你有点误解了我的意思。 1334553536当然没有字符。我的想法是把1334553536的“字符串”本身实际放入缓冲区中,占用10个字节。但我再次强调,我的项目中有很多代码,我敢肯定你和其他人都没有时间研究它。我要说的是,我正在为网络程序实现一个“ping/ms”计数器。你知道 - 获取自 1970 年以来的当前时间(以毫秒为单位),发送数据包,接收相同数据包,再次获取当前时间并减去差值以及任何开销。 @AndyCarter:如果这就是你要说的,那我就帮不上什么忙了。我看不出您的 ping/ms 程序如何需要将大整数值存储在 unsigned char 的数组中。但是,如果您能够决定如何存储这些值,则可以选择您喜欢的任何格式,包括人类可读的字符序列。 (顺便说一句,1334553536 很可能是自 1970 年以来以秒为单位的时间,除非是 1970 年 1 月中旬。) 正如你自己所说,我提供的代码不是真实的。 1334553536 只是我编的一个值。自 Epoch(1970 年)以来,它不止于此(尤其是以毫秒为单位),这就是为什么我期望 long long 足够大的原因。顺便说一句 - 我真的很感谢你的意见,我很抱歉打扰。

以上是关于无符号字符数组转换为 long long [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

将 Long/ULong 转换为带有填充零的无符号十六进制字符串

java里面请问下如何将long类型的数据转换成无符号的int数据

将 4 个字节转换为无符号 32 位整数并将其存储在 long

如何将字符串转换为无符号字符数组 [关闭]

将 Long 转换为 Unsigned Short Int / Strtol

从长度为无符号整数的 ByteBuffer 中读取 UTF-8 字符串