如何处理不规则的位大小

How to handle irregular bit sizes

本文关键字:不规则 何处理 处理      更新时间:2023-10-16

我正在研究一个项目,该项目包含来自二进制文件的不同位大小的变量。例如,文件的一行(十六进制)可能看起来像"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++中的二进制比较陌生,所以可能有一个我没有见过的内置函数。

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

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

首先测试n位数字中的符号位是什么。如果设置了,则int的上位也通过从-1的值开始设置(所有位都以2的补码设置)并屏蔽掉底部的有效位来设置。

这已经为您完成了-参见std::bitset -只需拥有它们的数组

对于问题中给出的两个例子,你可以这样做:

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;
}

在C/c++中有一个很少使用的特性,叫做位字段,它可以解决你的问题。

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

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

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

此链接提供详细信息

位字段一直都在那里但是没有人使用它们。注意,你可能需要教育你的同事(或适当地评论)