C语言中的位选择

C语言中的位选择,c,binary,C,Binary,我正在尝试选择位字符串1010000000001的位[0:2]和位[6:8]。位[0:2]为001,位[6:8]为000。我尝试使用以下选项选择这些位: int instr = 0x1401; int src2 = (instr & 0x0006); //get bits [2:0] int src1 = (instr & 0x01C0) >> 6; //get bits [6:8] printf("%04x, %04x",src2, src1); 然而,我得到s

我正在尝试选择位字符串1010000000001的位[0:2]和位[6:8]。位[0:2]为001,位[6:8]为000。我尝试使用以下选项选择这些位:

int instr = 0x1401;
int src2 = (instr & 0x0006); //get bits [2:0]
int src1 = (instr & 0x01C0) >> 6; //get bits [6:8]

printf("%04x, %04x",src2, src1);

然而,我得到src1和src2都是0000。有人能帮我理解我做得不对吗?这样我就可以从我能看到的内容中选择位[0:2]和[6:8]。

如果从0x1401和0x0006得到结果,那么从0x1401和0x01c0得到相同的结果。在src1上执行的位移位只是0向右移位6位,这仍然是0

从我所看到的,如果从0x1401和0x0006得到结果,则得到0,从0x1401和0x01c0得到相同的结果。在src1上执行的位移位只是0向右移位6位,这仍然是0

看看这段代码:

#include <stdio.h>

int main (void) {
    unsigned instr = 0x1401;
    unsigned src2 = instr & 0x0007;        //  7 in hex == 0000 0000 0111 in binary
    unsigned src1 = (instr & 0x01C) >> 6;  // 1C in hex == 0001 1100 0000 in binary

    printf("%04x, %04x", src2, src1);
}
它屏蔽了instr中所需的位,并按正确的偏移量对它们进行移位。此外,在执行位操作时,首选无符号类型。

请查看以下代码:

#include <stdio.h>

int main (void) {
    unsigned instr = 0x1401;
    unsigned src2 = instr & 0x0007;        //  7 in hex == 0000 0000 0111 in binary
    unsigned src1 = (instr & 0x01C) >> 6;  // 1C in hex == 0001 1100 0000 in binary

    printf("%04x, %04x", src2, src1);
}

它屏蔽了instr中所需的位,并按正确的偏移量对它们进行移位。此外,在执行位操作时,首选无符号类型。

只需编写一个函数,在此处使用1而不是0作为最低有效位,即可计算任意位片:

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

int bit_select(int num, size_t start, size_t end)
{
    assert(end >= start);

    const int mask = (1 << (end-start+1)) - 1;
    const int shift = start - 1;

    return (num & (mask << shift)) >> shift;
}

int main(void)
{
    printf("Bits 1...3 of 01100101: %d\n", bit_select(0x65, 1, 3));
    printf("Bits 3...3 of 01100101: %d\n", bit_select(0x65, 3, 3));
    printf("Bits 4...4 of 01100101: %d\n", bit_select(0x65, 4, 4));
    printf("Bits 3...7 of 01100101: %d\n", bit_select(0x65, 3, 7));

    return 0;
}

在这里,只需编写一个函数,使用1而不是0作为最低有效位来计算任意位片,就更容易了:

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

int bit_select(int num, size_t start, size_t end)
{
    assert(end >= start);

    const int mask = (1 << (end-start+1)) - 1;
    const int shift = start - 1;

    return (num & (mask << shift)) >> shift;
}

int main(void)
{
    printf("Bits 1...3 of 01100101: %d\n", bit_select(0x65, 1, 3));
    printf("Bits 3...3 of 01100101: %d\n", bit_select(0x65, 3, 3));
    printf("Bits 4...4 of 01100101: %d\n", bit_select(0x65, 4, 4));
    printf("Bits 3...7 of 01100101: %d\n", bit_select(0x65, 3, 7));

    return 0;
}

因为你提供了一个错误的面具

如果您使用gcc,为了让生活更轻松,只需提供二进制文字而不是十六进制版本,这样您就可以毫不费力地看到要屏蔽的内容:

unsigned src2 = instr & 0b111;

因为你提供了一个错误的面具

如果您使用gcc,为了让生活更轻松,只需提供二进制文字而不是十六进制版本,这样您就可以毫不费力地看到要屏蔽的内容:

unsigned src2 = instr & 0b111;

啊,好的。那么如何得到前三位001呢?对于位[0:3],它是0x000f;[0:2]它是0x0007;[6:8]它是0x01c0Ah,好的。那么我如何得到前三位001呢?对于位[0:3]是0x000f,对于位[0:2]是0x0007,对于位[6:8]是0x01C0,我正在尝试选择位[0:2]和[6:8]1+2+4=7。因此,使用0x7获取三个最低有效位,而不是0x6。位0的值为1,而不是0,因此,您的掩码6是off-by-1.0x7是正确的,src1实际上是000-将您的输入更改为11011或类似的内容,以便于查看获取src1值的常量可能更容易确定,并且代码更容易读取,如果您>>先移位6,然后将最低的三位掩码为&7。我正在尝试选择位[0:2]和[6:8]1+2+4=7。因此,使用0x7获取三个最低有效位,而不是0x6。位0的值为1,而不是0,因此,您的掩码6是off-by-1.0x7是正确的,src1实际上是000-将您的输入更改为11011或类似的内容,以便于查看获取src1值的常量可能更容易确定,并且代码更容易读取,如果您>>6先移位,然后将最低的三位掩码为&7。使用断言和pow似乎使它有点低效。断言的效率是无关紧要的,因为它在发布版本中是无操作的。使用pow比手动计算、写出和调试一千个单独指定的掩码,然后编写有关它们的问题的堆栈溢出问题更有效。为什么不使用mask=1>shift&mask?但是,这是为了教育目的,不是为了生产,所以谁会在乎效率。@ndim:公平竞争第一点,这绝对值得修改,答案更新。第二个也是公平的,但我保留了答案,因为我认为它使事情变得更清楚了。assert和pow的使用似乎使它有点低效。assert的效率无关紧要,因为它是一个无操作版本。使用pow比手动计算、写出和调试一千个单独指定的掩码,然后编写有关它们的问题的堆栈溢出问题更有效。为什么不使用mask=1>shift&mask?但是,这是为了教育目的,不是为了生产,所以谁会在乎效率。@ndim:公平竞争第一点,这绝对值得修改,答案更新。第二个也是公平的,但我保留了答案,因为我认为这会让事情变得更清楚。