在C中访问字符中的位

在C中访问字符中的位,c,C,我有一个十六进制数0x37,它的二进制表示是00110111。如何访问二进制表示法的前2位,即“11”?如何使用位移位或掩蔽来实现这一点?我可以一点一点地访问,但不能一次访问两位?如果您用0x03输入您的号码,您将获得最后两位 char c = 0x37; char mask = 0x03; char lastTwo = c & mask; 正如您所提到的,您最好使用位掩蔽。 像这样的事情应该可以做到: x = 0x37; y = x&0x30; //Mask out the

我有一个十六进制数0x37,它的二进制表示是00110111。如何访问二进制表示法的前2位,即“11”?如何使用位移位或掩蔽来实现这一点?我可以一点一点地访问,但不能一次访问两位?

如果您用0x03输入您的号码,您将获得最后两位

char c = 0x37;
char mask = 0x03;
char lastTwo = c & mask;

正如您所提到的,您最好使用位掩蔽。 像这样的事情应该可以做到:

x = 0x37;
y = x&0x30; //Mask out the first two bits of the higher nibble
y = y>>4;

下面是一个逐位访问它的示例:

#include <stdio.h>
int main()
{
    char byte = 0x37;
    int i;

    for(i = 7; 0 <= i; i --)
        printf("%d\n", (byte >> i) & 0x01);

    return 0;
}
#包括
int main()
{
字符字节=0x37;
int i;
对于(i=7;0>i)&0x01);
返回0;
}

您也可以使用位字段来执行此操作。位字段的缺点是它们的工作方式在某种程度上依赖于编译器,但是如果您不需要将代码移植到许多体系结构,那么它可能是好的

下面是一个在Ubuntu Linux计算机上编写并用GCC测试的示例

#include <assert.h>
#include <stdio.h>

#pragma pack(1)
typedef struct
{
    unsigned int low2: 2;  // 2 bits of the byte
    unsigned int high6: 6;  // 6 more bits of the byte
} MYBYTE;

typedef union
{
    MYBYTE mybyte;
    unsigned char b;
} MYUNION;

main()
{
    MYUNION m;

    assert(sizeof(m) == 1);
    m.b = 0x03;
    assert(m.mybyte.low2 == 0x03);
    assert(m.mybyte.high6 == 0x00);

    printf("low2 of 0x03 is: %u\n", m.mybyte.low2);
    printf("high6 of 0x03 is: %u\n", m.mybyte.high6);

    m.b = 0xff;

    printf("low2 of 0x03 is: %u\n", m.mybyte.low2);
    printf("high6 of 0x03 is: %u\n", m.mybyte.high6);
    assert(m.mybyte.low2 == 0x03);
    assert(m.mybyte.high6 == 0x3f);

    m.mybyte.high6 = 0x1c;
    m.mybyte.low2 = 0x01;
    assert(m.b == 0x71);
    printf("m.b is: 0x%02x\n", m.b);

    return 0;
}
传入一个值,然后输入要从哪个位获取位,以及需要多少位。因此,要从位位置2开始获取6位,测试值为0x71,您可以调用:

x = bits(0x71, 2, 6);  // x is set to 0x1c
如果您不喜欢查找表,并且希望使用最小的代码来执行此操作,则可以使用:

unsigned int
bits(unsigned int x, unsigned int i_bit, unsigned int c_bits)
{
    const unsigned int mask_bits = 0xffffffff;

    assert(UINT_MAX >= 4294967295U); // unsigned int must be at least 32-bit
    assert(i_bit <= 31);
    if (i_bit > 31)
        return 0;
    c_bits = MIN(c_bits, 32 - i_bit);

    // shift-and-mask to grab the requested bits, and return those bits
    return (x >> i_bit) & (mask_bits >> (32 - c_bits));
}
无符号整数
位(无符号整数x、无符号整数i_位、无符号整数c_位)
{
常量无符号整数掩码\u位=0xffffffff;
断言(UINT_MAX>=4294967295U);//无符号整数必须至少为32位
断言(i_位31)
返回0;
c_位=最小值(c_位,32-i_位);
//移位和掩码以获取请求的位,并返回这些位
返回(x>>i_位)和(掩码_位>>(32-c_位));
}
您需要确保掩码位声明为
无符号
,因为如果它们有符号,右移位操作将符号扩展


如果您将函数的最后一个版本声明为内联,将其放入头文件,并使用
i_位
c_位
的常量值调用它,它将编译到最小的代码以解决问题。(例如,如果
i_位
为0,编译器知道
>0
什么都不做,只会不生成该代码。如果编译器知道
c_位
是常量,它可以在编译时执行所有移位
掩码位
的工作。)但是,您需要确保您使用的是在发布版本中编译为空的
assert()
,或者使用您自己的
assert()
宏并使宏编译为空。

这是最容易使用的函数,我不希望其他人在得到类似的东西之前挣扎很长时间-

char get_bits(char a, char no_of_bits)
{
    return a & ((no_of_bits << 1) - 1);
}
char a = 0x37;
char b = get_bits(a, 2);
char get_位(char a,char no_of_位)
{

这里返回一个&((没有)个位,我假设您想将11与“0011”隔离。如果您只需要两个最低阶位,x&0x03就可以工作,如dasblinkenlight所示。
char get_bits(char a, char no_of_bits)
{
    return a & ((no_of_bits << 1) - 1);
}
char a = 0x37;
char b = get_bits(a, 2);