假设我有一个函数vector<unsigned char> byteVector(long long UID)
,返回UID的字节表示,64位整数,作为vector
。该向量稍后用于将此数据写入文件。
现在,因为我决定用Python读取该文件,所以我必须遵守utf-8标准,这意味着我可以only use the first 7bits of each char。如果最高有效位为1,我就不能将其解码为字符串,因为它们只支持ASCII字符。此外,我必须通过命令行界面将这些字符串传递给其他进程,命令行界面也只支持ASCII字符集。
在出现这个问题之前,我将64位整数分成8个独立字节的方法如下,这非常有效:
vector<unsigned char> outputVector = vector<unsigned char>();
unsigned char * uidBytes = (unsigned char*) &UID_;
for (int i = 0; i < 8; i++){
outputVector.push_back(uidBytes[i]);
}
当然,这不再适用,因为约束&#34; HBit可能不是1&#34;将每个unsigned char
的最大值限制为127。
我现在最简单的选择当然是用这个替换一个push_back
来电:
outputVector.push_back(uidBytes[i] / 128);
outputVector.push_back(uidBytes[i] % 128);
但这似乎有点浪费,因为每个unsigned char
对中的第一个只能是0或1而我会浪费一些空间(6个字节),否则我就可以使用它。
由于我需要保存64位,并且每个字节可以使用7位,所以我需要64 // 7 + 64%7 = 10个字节。
它真的不多(我写的文件都没有达到1kB标记),但之前我使用的是8个字节,现在使用16个十(不是9,I&I)似乎有点浪费#39;对不起)就够了。所以:
如何将64位整数转换为10个7位整数的向量?
这可能是太多的优化,但是对于这个问题可能有一些非常酷的解决方案(可能使用移位运算符),我真的很想看到它。
答案 0 :(得分:4)
您可以使用位移来获取64位整数的7位数。但是,你需要10个7位整数,9个是不够的:9 * 7 = 63
,有点短。
std::uint64_t uid = 42; // Your 64-bit input here.
std::vector<std::uint8_t> outputVector;
for (int i = 0; i < 10; i++)
{
outputVector.push_back(uid >> (i * 7) & 0x7f);
}
在每次迭代中,我们将输入位移位7的倍数,并屏蔽掉7位部分。 8位数字的最高位将为零。注意,向量中的数字是“反向的”:最低有效位具有最低的索引。但是,如果您以正确的方式解码部件,则无关紧要。解码可以按如下方式进行:
std::uint64_t decoded = 0;
for (int i = 0; i < 10; i++)
{
decoded |= static_cast<std::uint64_t>(outputVector[i]) << (i * 7);
}
请注意,将结果向量解释为UTF-8编码文本似乎是一个坏主意:序列仍然可以包含控制字符和\0
。如果要以可打印字符对64位整数进行编码,请查看base64。在这种情况下,您将需要一个字符(总共十一个)来编码64位。
答案 1 :(得分:1)
我建议使用汇编语言。
许多汇编语言都有将位转换为&#34;备用&#34;进位并将进位位移入寄存器。 C语言没有方便或有效的方法来执行此操作。
算法:
for i = 0; i < 7; ++i
{
right shift 64-bit word into carry.
right shift carry into character.
}
您还应该考虑使用std::bitset
。