将多个布尔值放入无符号字符中
Putting mutiple booleans into an unsigned char?
目前我正在开发NES模拟器,并且正在开发CPU核心。我在互联网上搜索了很多,但我找不到合适的关键词来找到我问题的答案,所以我想我应该在这里问它。我有七个布尔值,它们充当我的处理器状态标志。我正在处理的当前操作码希望我将处理器状态标志推送到堆栈。我的堆栈是无符号char数据类型。我以为我可以像这样把布尔体打在一起:
bool C, Z, I, D, B, V, N;
unsigned char example;
example = {C, Z, I, D, B, V, N, 0};
这不起作用,那么我该如何将所有布尔处理器状态标志放入无符号char数据类型中,以便将这些标志推送到堆栈中呢?
enum { C=0x01, Z=0x02, I=0x04, D=0x08,
B=0x10, V=0x20, N=0x40 };
unsigned char flags = 0;
这是因为在每个常量中只设置了一个位。要确定是否设置了标志,请像使用(flags & C)
一样使用(flags & FLAGNAME)
来确定是否已设置。注意不要将我使用的按位AND(&)与布尔/逻辑AND(&aamp;&&;操作员不会代替&操作人员若要设置标志,请使用(flags |= FLAGNAME)
;若要取消设置标志,则使用flags &= ~FLAGNAME;
。按照正确的顺序调整常数,以便NES指令能够正确检查标志。毕竟,如果它们的顺序不正确,可能会使用错误的标志值,这显然是个问题。
另外,不要忘记括号。逐位运算符的优先级非常低,因此表达式周围的括号是必不可少的。
如果你不知道比特运算符,它们值得一读。
编辑
一套方便的宏:
#define FLAG_ISSET(x) (flags & (x))
#define FLAG_SET(x) (flags |= (x))
#define FLAG_CLEAR(x) (flags &= ~(x))
...
if (FLAG_ISSET(C))
...
FLAG_SET(V);
FLAG_CLEAR(Z);
尝试std::bitset
。http://en.cppreference.com/w/cpp/utility/bitset我找不到使用初始值设定项列表构建它的方法,但您可以始终使用operator[]
或set()
来设置每个位,并使用to_ulong()
将其转换为数字(然后您可以简单地将无符号长字符转换为无符号字符)。
#include <stdio.h>
#include <bitset>
using namespace std;
int main()
{
bitset<7> reg;
bool C = true, Z = false, I = false, D = false, B = true, V = true, N = false;
reg[6] = C;
reg[5] = Z;
reg[4] = I;
reg[3] = D;
reg[2] = B;
reg[1] = V;
reg[0] = N;
unsigned char example = static_cast<unsigned char>(reg.to_ulong());
printf("0x%xn", example);
return 0;
}
试试这个:
bool C, Z, I, D, B, V, N;
unsigned char example = 0;
if(C)
example |= (1 << 7)
if(Z)
example |= (1 << 6)
if(I)
example |= (1 << 5)
if(D)
example |= (1 << 4)
if(B)
example |= (1 << 3)
if(V)
example |= (1 << 2)
if(N)
example |= (1 << 1)
假设int status
是您的CPU状态寄存器。你可以创建一些这样的定义:
#define CPU_REG_STATUS_C 0x00000040
#define CPU_REG_STATUS_Z 0x00000020
#define CPU_REG_STATUS_I 0x00000010
#define CPU_REG_STATUS_D 0x00000008
#define CPU_REG_STATUS_B 0x00000004
#define CPU_REG_STATUS_V 0x00000002
#define CPU_REG_STATUS_N 0x00000001
然后通过使用逐位二进制运算符&和|
示例1:设置ZERO标志
status |= CPU_REG_STATUS_Z;
示例2:检查ZERO标志的值:
if(status & CPU_REG_STATUS_Z)
{
//zero flag is set
}
else
{
//zero flag is unset
}
然而,有很多CPU核心源代码,尤其是6502CPU(Commodore C64、Nintendo NES和许多其他),所以你只需要关心控制台的模拟。
http://www.6502.org/tools/emu/
这对于放入模拟器来说可能有点重,但为什么不将每个布尔值转换为字符中的一位,然后在需要将其从堆栈中取出时对其进行解码呢。
unsigned char encodeBits(bool bools[8]) {
unsigned char retval = 0;
for(int i = 0; i < 8; i++) {
retval += (bools[i] ? 1 : 0);
retval = (i < 7 ? retval << 1 : retval);
}
return retval;
}
这段代码基本上只是将布尔值转换为一个字符。
然后解码,通过引用传递一个空数组,
void decodeBits(bool (&bools)[8], unsigned char input) {
for(int i = 0; i < 8; i++) {
bools[i] = (input & 0x00000001 ? true : false);
input = (i < 7 ? input >> 1 : input);
}
}
该代码应该比较字符的第一位,然后对其进行移位等。
这可以在没有数组的情况下完成,但为了简单起见,我使用了数组。
编辑:一个工作示例:http://ideone.com/hQ47nn
这应该是您想要的:
bool C, Z, I, D, B, V, N;
unsigned char example = 0;
const unsigned char mask = 0x01;
if(N)
example |= mask << 1;
if(V)
example |= mask << 2;
//...
if(C)
example |= mask << 7;
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- C++中无符号字符溢出
- 使用无符号字符数组有效存储内存
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 如何在保持其值的同时将 c++ 无符号字符变量转换为 char 变量
- 从 std::vector<无符号字符>切片中提取 int?
- 将无符号字符的向量存储在数组中会给我 std::bad_alloc
- 使用 fopen 打开 .pak 文件并使该文件应用于 const 无符号字符* (C++)
- 库特无符号字符
- 寻找一种更好的方法来表示无符号字符数组
- C++ 无符号字符 *{varName};-> C#
- 如何返回/复制unique_ptr<无符号字符[]>的值?
- 将浮点数转换为无符号字符数组并打印出来
- 在函数中返回无符号字符数组,但不返回指针
- 如何在 C/C++ 中将无符号字符*转换为无符号字符数组?
- 如何返回实际值(在我的例子中是无符号字符数组)而不是来自 C++ 函数的指针?
- 如何将带有十六进制值的 std::string 转换为 std::vector<无符号字符>
- 无符号字符打印其 ASCII 值
- 字符数组到无符号字符 *
- 是否可以在 c++ 中将两位数保存在无符号字符中