使用 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);
}
我是 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);
}