使用 C++ 从 6 个字节或更多字节生成一个整数

Make a Integer from 6 bytes or more using C++

我是 C++ 编程新手。我正在尝试实现一个代码,通过它我可以从 6 或更多 individual bytes.

中得到一个整数值

我已经为 4 bytes 实施了相同的方法并且它正在工作

我的4字节代码:

char *command = "\x42\xa0\x82\xa1\x21\x22";
__int64 value;
value = (__int64)(((unsigned char)command[2] << 24) + ((unsigned char)command[3] << 16) + ((unsigned char)command[4] << 8) + (unsigned char)command[5]);
printf("%x  %x  %x  %x  %x",command[2], command[3], command[4], command[5], value);

使用此代码 value 的值是 82a12122 但是当我尝试对 6 字节执行时结果是错误的。

6 字节代码:

char *command = "\x42\xa0\x82\xa1\x21\x22";
__int64 value;
value = (__int64)(((unsigned char)command[0] << 40) + ((unsigned char)command[1] << 32) + ((unsigned char)command[2] << 24) + ((unsigned char)command[3] << 16) + ((unsigned char)command[4] << 8) + (unsigned char)command[5]);
printf("%x  %x  %x  %x  %x  %x  %x", command[0], command[1], command[2], command[3], command[4], command[5], value);

value的输出值是82a163c2,这是错误的,我需要42a082a12122。 那么谁能告诉我如何获得预期的输出以及 6 Byte 代码有什么问题。

提前致谢。

在移位之前,只需将每个字节转换为足够大的无符号类型。即使经过整数提升(到 unsigned int),该类型也不足以移动超过 32 个字节(在通常情况下,这似乎适用于您)。

演示请看这里:https://godbolt.org/g/x855XH

unsigned long long large_ok(char x)
{
    return ((unsigned long long)x) << 63;
}

unsigned long long large_incorrect(char x)
{
    return ((unsigned long long)x) << 64;
}


unsigned long long still_ok(char x)
{
    return ((unsigned char)x) << 31;
}

unsigned long long incorrect(char x)
{
    return ((unsigned char)x) << 32;
}

简单来说:

移位运算符自动将其操作数提升为 int/unsigned int。这就是您的四字节版本有效的原因:unsigned int 足够大,适合您的所有班次。但是,(在您的实现中,与最常见的实现一样)它只能容纳 32 位,如果您移动超过 32 位,编译器将不会自动选择 64 位类型(编译器不可能知道) .

如果您为移位操作数使用足够大的整数类型,则移位将具有更大的类型作为结果,并且移位将按照您的预期进行。

如果您打开警告,您的编译器可能还会向您抱怨您移动的位数多于类型的位数,因此总是得到零(参见演示)。

(提到的位数当然是实现定义的。)


最后说明:以双下划线 (__) 或下划线 + 大写字母开头的类型保留用于实现 - 技术上不使用它们 "safe"。现代 C++ 为您提供了诸如 uint64_t 之类的类型,它们应该具有规定的位数 - 请改用这些类型。

您的班次溢出字节,您没有正确打印整数。

此代码有效: (注意打印格式以及如何在 uint64_t 中完成转换)

#include <stdio.h>
#include <cstdint>

int main()
{
    const unsigned char *command = (const unsigned char *)"\x42\xa0\x82\xa1\x21\x22";
    uint64_t value=0;
    for (int i=0; i<6; i++)
    {
        value <<= 8;
        value += command[i];
    }
    printf("%x  %x  %x  %x  %x  %x  %llx",
             command[0], command[1], command[2], command[3], command[4], command[5], value);
}