【问题标题】:How to handle irregular bit sizes如何处理不规则的位大小
【发布时间】:2014-07-22 16:11:15
【问题描述】:

我正在处理一个项目,该项目包含来自二进制文件的不同位大小的变量。例如,文件的一行(十六进制)可能看起来像“FF C0 AA 00 FE”。例如,从这一行开始,我需要的信息是 4 位、7 位、11 位、8 位等。 我遇到的问题是提取的一些数字将被签名,而其他数字将是无符号的(4 位和 7 位可能是有符号的,11 位和 8 位可能是无符号的)。

我最初是通过屏蔽和移位十六进制值来提取 4、7、11、8 位的 c++ char/short/int。但是,如果我查看二进制的 4 位,它将显示为 00001011。这个数字应该是基于前导 1 的负数(应该只是 4 位 1011),但 C++ 将其识别为正数,因为它正在查看所有8 位。

另一个澄清的例子,我可能会从文件中提取 11 位为 (11100101101),但在 c++ 短格式中它显示为 (0000011100101101),应该基于 11 位中的前导 1 进行签名。

我想知道处理这个问题的理想方法是什么。我正在考虑创建一个位/字节类,唯一的问题是位大小不同(4、7、11、8)。

谢谢,希望它有意义。我对 C++ 中的二进制相当陌生,所以可能有一个我没见过的内置函数。

【问题讨论】:

  • "FF C0 AA 00 FE" 是一个4bit, 7bit, 11bit, 8bit,...数据的序列?
  • 使用bitfield 结构怎么样?或者std::bitset 似乎对您的情况也有用。
  • 如果 FF C0 AA 00 FE 来自文件,在二进制中它显示为 (11111111 1100000 10101010...) 那么我需要将前 4 位作为一个数字,所以 1111。然后下一个数字是 7 位,它将是 1111110(4 位来自 FF,4 位来自 C0),11 位将是 00000101010,等等...

标签: c++


【解决方案1】:

我假设您已经可以通过移位和屏蔽以及或将不同的部分组合在一起来提取所需的位,问题只是处理符号位。

int make_signed(int value, int bits)
{
    if (value & (1 << (bits - 1)))
        value |= -1 & ~((1 << bits) - 1);
    return value;
}

首先要测试 n 位数中的符号位。如果已设置,int 的高位也会通过以 -1 的值开始(所有位设置为二进制补码)并屏蔽低位有效位来设置。

【讨论】:

  • +1,但您可以简单地移动两次以获得符号扩展(假设 value 的签名类型):value = value &lt;&lt; (bits - 1) &gt;&gt; (bits - 1)。编辑:实际上,从头开始,这只适用于右移是算术运算的环境,这是特定于实现的。
  • @Cameron 感谢您指出我错过了一些非常重要的事情。我坚持使用一个小模型的原始公式。
  • 只是出于好奇:他不能只是重置符号位并将值乘以-1吗?
  • @cassiorenan 不,因为它不会是相同的值。例如 4 位序列 1011 应该是 -5,而不是 -3。
  • 当然。我的想法完全错了。更像是乘以 -1,清除所有“溢出”的 MSB 位,乘以 -1。
【解决方案2】:

这已经为你完成了 - 见 std::bitset - 只是有一个数组

【讨论】:

  • std::bitset 不能满足用户的需求。他正在尝试存储小整数,而不是位集合。
【解决方案3】:

以下是您问题中给出的两个示例的目的:

char src = 0x0B;              // 00001011
char dst = (char)(src<<4)>>4; // 11111011

short src = 0x072D;             // 0000011100101101
short dst = (short)(src<<5)>>5; // 1111111100101101

一般来说,您可以为signed 值实现一个函数,为unsigned 值实现一个函数:

#include <limits.h>

signed int GetSignedVal(signed int val,int numOfBits)
{
    int shift = sizeof(val)*CHAR_BITS-numOfBits;
    return (val<<shift)>>shift;
}

unsigned int GetUnsignedVal(unsigned int val,int numOfBits)
{
    int shift = sizeof(val)*CHAR_BITS-numOfBits;
    return (val<<shift)>>shift;
}

【讨论】:

    【解决方案4】:

    在 C/C++ 中有一个很少使用的功能,称为位域,可以解决您的问题。

        struct HodgePodgge {
                bool oneBooleanBit:1;
                int fourBitsOfSignedInteger:4;
                unsigned int sixUnsignedIntegerBits:6;
        };
    

    'sizeof(HodgePodge)' 应该是 2(总共 11 位适合两个字节)

    编译器会生成代码来为您执行移位、屏蔽和符号扩展。这是一件好事,因为它不能保证 HodgePodge 中的位布局。

    This link gives details

    位域一直存在永远,但没有人使用它们。请注意,您可能需要教育您的同事(或适当评论)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      相关资源
      最近更新 更多