如何处理不规则的位大小

时间:2014-07-22 16:11:16

标签: c++

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

我最初是通过屏蔽和移动Hex值来获取,以获得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 ++中的二进制文件相当新,所以可能有一个我没见过的内置函数。

4 个答案:

答案 0 :(得分:4)

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

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

首先测试n位数中的符号位。如果它被设置,int的高位也通过以-1的值开始(所有位在2的补码中设置)并屏蔽底部有效值来设置。位。

答案 1 :(得分:1)

这已经为您完成了 - 请参阅std::bitset - 只是有一个数组

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

C / C ++中很少使用一种称为位域的功能来解决您的问题。

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

&#39;的sizeof(大杂烩)&#39;应该是2(11位总共适合两个字节)

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

This link gives details

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