C - 按位连接导致信息丢失
C - Bitwise concatenation causing missing information
我有五个短类型变量,我想将它们连接成一个 32 位无符号整数类型。我需要连接五个短变量。这些变量的名称称为操作码(5 位)、reg1(4 位)、reg2(4 位)、reg3(4 位)、扩展(3 位)和 addr_constant(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;
...
二进制形式的输出应该是:
0000 1001 1010 0010 1000 0000 0000 0000.
但现在是:
1001 1010 0010 1000 0000 0000 0000.
如您所见,它遗漏了前 4 个零。
在下面的测试中"word"是:unsigned int *const word。在上面代码的最后,我写了“*word = machine_word”。在测试中,它比较:"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;
}
代码给出以下输出:
0000 1001 1010 0010 1000 0000 0000 0000
这应该是您要搜索的结果,它对应于 161644544
(0x9A28000
) 的无符号整数值。
我有五个短类型变量,我想将它们连接成一个 32 位无符号整数类型。我需要连接五个短变量。这些变量的名称称为操作码(5 位)、reg1(4 位)、reg2(4 位)、reg3(4 位)、扩展(3 位)和 addr_constant(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;
...
二进制形式的输出应该是:
0000 1001 1010 0010 1000 0000 0000 0000.
但现在是:
1001 1010 0010 1000 0000 0000 0000.
如您所见,它遗漏了前 4 个零。
在下面的测试中"word"是:unsigned int *const word。在上面代码的最后,我写了“*word = machine_word”。在测试中,它比较:"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;
}
代码给出以下输出:
0000 1001 1010 0010 1000 0000 0000 0000
这应该是您要搜索的结果,它对应于 161644544
(0x9A28000
) 的无符号整数值。