可视C++:开关语句中的结构成员
visual C++: struct member in a switch statement
我正在用C++编写一个微处理器模拟器,我的目标之一是使代码非常可读。 为了实现操作码,我有一个结构,我用它来表示单个处理器指令,它包含操作码和程序计数器的前进距离。 这个想法是将有关每个指令的相关信息分组。
struct instruction
{
const int opcode; // instruction opcode
const int op_size; // how far to advance Program Counter
};
const instruction HALT{0x76, 1};
const instruction NOP {0x00, 1};
我最初的计划是使用此结构定义所有操作码,因为我的印象是const
比使用#define
C++常量更可取。 此外,我将能够干净地对操作码的所有相关属性进行分组。
但是,这似乎不适用于 switch 语句,正如我最初打算的那样。 下面的代码将无法编译,Visual Studio 给出错误"case 表达式不是常量"。
switch (next_instruction) { // next_instruction is an int parsed from a file
case HALT.opcode:
// do stuff
break;
case NOP.opcode:
// do stuff
break;
default:
std::cout << "Unrecognized opcode" << std::endl;
break;
}
我还下载了最新的Visual Studio编译器(MSVC 2013年11月CTP(以尝试利用C++11中的constexpr
,但我遇到了同样的问题,它无法编译。 在这里,我将结构转换为类并尝试利用constexpr
,以确保instruction
的成员可以用作编译时常量。
class Instruction
{
public:
constexpr Instruction(int code, int size) : opcode(code), op_size(size) {}
const int opcode; // instruction opcode
const int op_size; // how far to advance Program Counter
};
constexpr Instruction HALT(0x76, 1);
constexpr Instruction NOP (0x00, 1);
我真的不确定此时该怎么做,因为编译器似乎不明白结构值被分配为常量。
那么有没有办法在 switch 语句中使用结构成员,或者我应该切换到使用 #define
? 或者,有没有更好的方法来做到这一点,同时仍然保留一些组织? 我非常感谢您能提供的任何帮助或见解,谢谢!
编辑:抱歉,我应该更清楚地表明next_instruction只是一个整数,而不是instruction
结构/对象
我已经使用MinGW 4.8.3编译器在Qt Creator 3.1.2中测试了您的代码。只是在每个指令定义中用constexpr替换const就让编译器很高兴:
struct instruction
{
const int opcode; // instruction opcode
const int op_size; // how far to advance Program Counter
};
// Replacing "const" by "constexpr" int these two lines
constexpr instruction HALT{0x76, 1};
constexpr instruction NOP {0x00, 1};
int main() {
int next_instruction = 0x76;
switch (next_instruction) { // next_instruction is an int parsed from a file
case HALT.opcode:
// do stuff
break;
case NOP.opcode:
// do stuff
break;
default:
std::cout << "Unrecognized opcode" << std::endl;
break;
}
}
编辑以添加一些引号:
C++编程语言(Fourh Edition(对switch语句中的标签说:
">案例标签中的表达式必须是常量表达式 的整型或枚举型。(9.4.2 切换语句"(。
从 Section 10.4 常量表达式:
C++提供了"常量"的两个相关含义:
- constexpr:在编译时求值
- const:不要在此范围内修改
基本上,constexpr的作用是启用和确保 编译时评估,而 const 的主要作用是指定 接口中的不可变性。
[...]
10.4.2 常量表达式中的常量
[...]使用常量表达式初始化的常量可以在 常量表达式。常量与 constexpr 的不同之处在于它可以 由不是常量表达式的东西初始化;在那 在这种情况下,常量不能用作常量表达式。
switch 语句中的标签需要 constexpr,以便在编译时完成计算。因此,const instruction HALT {0x76,1}
似乎不能确保编译时评估,而constexpr instruction HALT {0x076,1}
可以。
如果您不想冒险使用模板,那么没有可怕的宏的可能解决方案可能如下所示。
template<int code, int size>
struct InstructionType
{
static const int opcode = code ;
static const int op_size = size;
};
struct Instruction
{
int opcode;
int op_size;
};
typedef InstructionType<0x76, 1> HALT;
typedef InstructionType<0x00, 1> NOP;
int main()
{
Instruction next_instruction;
switch (next_instruction.opcode) {
case HALT::opcode:
// do stuff
break;
case NOP::opcode:
// do stuff
break;
default:
std::cout << "Unrecognized opcode" << std::endl;
break;
}
}
从树上退后一会儿,这是一个相当安全的赌注,你正在编写一个8080/Z80模拟器。 所以根本不要使用开关。 将指令结构排列在一个数组中,并使用要执行的操作码作为索引。
struct instruction
{
const int opcode; // instruction opcode
const int op_size; // how far to advance Program Counter
const void (*emulator)(parameter list); // code for this opcode
};
void illegal(parameter list)
{
std::cout << "Unrecognized opcode" << std::endl;
}
instruction opcodes[] = // assuming 8080 for now
{
{0x00, 1, nop_emulator}, // NOP
{0x01, 3, lxib_emulator}, // LXI B
etc.
{0x08, 1, illegal}, // 0x08 is invalid on the 8080
etc.
};
现在你的代码变成了
opcodes[next_instruction].emulator(parameter list);
您可以选择丢弃操作码,也可以进行预检查以确保每个操作码都位于表中的正确位置。
这也有一个优点,即通过将代码分解为每个操作码的一个例程来阻止您的代码成为一个整体例程。 如果您正在编写 Z80 仿真器,这将成为一个主要问题,因为0xCB、0xDD、0xED 和0xFD组,在切换模式中,这需要这四个伪操作码的每个大小写处理程序中的第二个开关。
- 具有结构成员char数组的sscanf
- 仅使用结构名称访问结构成员
- 使用 structType*& 赋给结构成员
- 使用结构成员指针在C++中填充结构
- 聚合初始化,将成员指针设置为同一结构成员
- 为什么结构化绑定不使用"auto&"返回对结构成员的引用,而是返回成员本身
- 是否可以将结构数组别名为结构成员数组?
- 结构成员在访问时被清除
- 如何指示结构成员没有锯齿?
- 为什么继承的结构成员在联合中无法访问?
- 尝试在 qml 中访问结构成员的 QList
- C++/CLI -- 访问结构成员
- 调用在类中声明的结构成员
- 对结构成员的临时绑定引用
- 无法使用 strcpy 将字符串复制到静态结构成员
- 为什么类成员数据必须是静态的才能被模板化类的模板化结构成员访问
- 填充模板化结构类型的结构成员
- C/C++intellisense 0.26.1不显示结构成员列表
- 在源文件中创建具有结构成员的结构
- 如何访问结构成员作为指针