C-导致信息丢失的按位连接

C-导致信息丢失的按位连接,c,bit-manipulation,bitwise-operators,bit-shift,bitwise-or,C,Bit Manipulation,Bitwise Operators,Bit Shift,Bitwise Or,我有五个短类型变量,我想把它们连接成一个32位无符号int类型。我需要连接五个短变量。这些变量的名称称为操作码(5位)、reg1(4位)、reg2(4位)、reg3(4位)、扩展名(3位)和addr_常量(12位)。现在我的代码不适用于一个我不知道为什么的情况。我在下面列出了我的代码 这段代码的目的是将某些值转换为32位机器指令,这意味着即使我得到了等效值,我仍然需要一条32位指令 ... unsigned int *const word; unsigned short opcode = 1;

我有五个短类型变量,我想把它们连接成一个32位无符号int类型。我需要连接五个短变量。这些变量的名称称为操作码(5位)、reg1(4位)、reg2(4位)、reg3(4位)、扩展名(3位)和addr_常量(12位)。现在我的代码不适用于一个我不知道为什么的情况。我在下面列出了我的代码

这段代码的目的是将某些值转换为32位机器指令,这意味着即使我得到了等效值,我仍然需要一条32位指令

...
unsigned int *const word;
unsigned short opcode = 1;
unsigned short reg1 = 3; 
unsigned short reg2 = 4;
unsigned short reg3 = 5;
unsigned short extension = 0;
unsigned int addr_constant = 0;

unsigned int machine_word = 0;
machine_word = machine_word | (opcode << 27);
machine_word = machine_word | (reg1 << 23);
machine_word = machine_word | (reg2 << 19);
machine_word = machine_word | (reg3 << 15);

machine_word = machine_word | (extension << 12);
machine_word = machine_word | addr_constant;

*word = machine_word
return 0;
...
但现在是:

1001 1010 0010 1000 0000 0000 0000. 
如您所见,它未命中前4个零

在下面的测试中,“字”是:无符号int*const字。在上面代码的最后,我写了“*word=machine\uword”。在测试中,它比较:“word==0x09a28000” 我没有通过下面的测试

assert(word == 0x09a28000);
只需使用位字段——它们就是为此而设计的

struct all_the_things {
  unsigned opcode : 5;
  unsigned reg1 : 4;
  unsigned reg2 : 4;
  unsigned reg3 : 4;
  unsigned extension : 3;
  unsigned addr_constant : 12;
};
填充此类结构后,可以将其转换为32位整数,如下所示:

uint32_t num;
memcpy(&num, &things, 4);

(别担心,优化编译器不会真正调用函数来复制4个字节。)

也许问题只是结果解释。我运行了以下代码,它基于您提供的算法,并对逻辑操作和结果打印进行了一些修改。操作的核心逻辑与您发布的内容保持不变,因此可能是误读了结果

代码如下:

#include <stdio.h>

int main() {
    int i, j, mask;

    unsigned short opcode = 1;
    unsigned short reg1 = 3; 
    unsigned short reg2 = 4;
    unsigned short reg3 = 5;
    unsigned short extension = 0;
    unsigned int addr_constant = 0;

    unsigned int machine_word = 0;
    machine_word |= opcode << 27;
    machine_word |= reg1 << 23;
    machine_word |= reg2 << 19;
    machine_word |= reg3 << 15;

    machine_word |= extension << 12;
    machine_word |= addr_constant;

    for (i = 7; i >= 0; i--) {
        for (j = 3; j >= 0; j--){
            printf("%d", (machine_word & 0x00000001 << (4 * i + j)) >> (4 * i + j));
        }
        printf(" ");
    }
    printf("\n");
    return 0;
}

这应该是您正在搜索的结果,它对应于无符号整数值
161644544
0x9A28000
)。

printf(“%d\n”,机器字)无法打印
1001 1010 0010 1000 0000
。请显示进行打印的代码。
0000 1001 1010 0010 1000 0000 0000
1001 1010 0010 1000 0000 0000相同。
,正如
02
2
相同。测试是如何编写的?那么,
printf(“%08x\n”,machine\u word)
的输出是什么?“我在
assert(word==0x09a28000)
上失败了-可能是因为
word
machine\u word
不一样吧?你的代码可以工作,请看实时版本。不幸的是,我的老师不允许我们在讲座之外使用任何东西。因此,我只能使用位移位而不是位字段(0)。该答案不提供单个数字、数字或输出字符串中的级联位,因此它不满足“二进制形式的输出应为0000 1001 1010 0010 1000 0000”的规范。(1)此答案介绍了与实现相关的位字段排序问题,以及用于问题中不存在的位字段的存储单元。@EricPostChil:我在答案中添加了一个位,以说明如何将其转换为
uint32\t
。依赖于实现的部分在技术上是正确的,但我们都知道这样的代码可以在我们都熟悉和喜爱的编译器上工作。也许有更好的方法可以在控制台上打印二进制值,而不必使用掩蔽和循环。不幸的是,我不知道怎么做
#include <stdio.h>

int main() {
    int i, j, mask;

    unsigned short opcode = 1;
    unsigned short reg1 = 3; 
    unsigned short reg2 = 4;
    unsigned short reg3 = 5;
    unsigned short extension = 0;
    unsigned int addr_constant = 0;

    unsigned int machine_word = 0;
    machine_word |= opcode << 27;
    machine_word |= reg1 << 23;
    machine_word |= reg2 << 19;
    machine_word |= reg3 << 15;

    machine_word |= extension << 12;
    machine_word |= addr_constant;

    for (i = 7; i >= 0; i--) {
        for (j = 3; j >= 0; j--){
            printf("%d", (machine_word & 0x00000001 << (4 * i + j)) >> (4 * i + j));
        }
        printf(" ");
    }
    printf("\n");
    return 0;
}
0000 1001 1010 0010 1000 0000 0000 0000