我想在switch语句中使用宏函数,然后才意识到该语句需要保持不变。示例(不编译):
#define BAND_FIELD1(B) (10 * B + 1)
...
#define BAND_FIELD7(B) (10 * B + 7)
int B = myField % 10;
switch (myField) {
case BAND_FIELD1(B):
variable1[B] = 123;
break;
case BAND_FIELD7(B):
variable7[B] = 321;
break;
...
}
我宁愿使用.. else:
if (myField == BAND_FIELD1(B)
variable1[B] = 123;
else if (myField == BAND_FIELD7(B)
variable7[B] = 321;
为什么C ++ switch语句限于常量表达式?
C ++的优势之一就是它的静态检查。 switch
语句是一个静态控制流构造,其作用在于能够(静态)检查是否已考虑所有案例,并且能够合理地对案例进行分组(例如,落入公共部分)。
如果要动态检查条件,您已经可以使用多种技术(if
语句,条件运算符,关联数组,虚函数等等)进行检查。
为什么c ++ switch语句限于常量表达式?
因为switch
语句执行的检查是静态。这意味着需要在编译时知道这些表达式。
在C ++ 11中,您可以使用constexpr
(如果表达式是由其他常量表达式派生的)。例如,考虑以下功能(代替您的#define
):
inline constexpr int BAND_FIELD1(int B) {
return 10 * B + 1;
}
用于以下简化的代码版本:
constexpr int myField = 0;
constexpr int B = myField % 10;
int variable1 = 0;
switch (myField) {
case BAND_FIELD1(B):
variable1 = 123;
break;
// ...
default: break;
}
如您所见,上面的代码will easily compile。
当常量出现时,编译器可以为开关生成最快的代码,例如跳转表或二进制搜索树。
当给定非恒定值时,它无法生成比链式if
-else
语句快的代码。无论如何,您已经可以使用它!
我的回答是,C ++开关是C开关的遗留物,而C开关是PL / M之类的古董语言的遗留物。
这种情况的独特性只是我认为可以追溯到70年代的结构的偶然机会。它不保证以任何方式都涵盖所有情况,尤其是考虑到C ++枚举的弱类型。
考虑到C ++通常在幕后产生的大量汇编代码,我认为出于性能原因C ++开关仅限于常量看来对我来说有点丰富。
[许多其他语言在switch语句中支持变量和/或非数字表达式,而且我还没有看到很多程序员抱怨可能的重复大小写值。
为了帮助回答这个问题,请考虑以下内容(如果合法):
int a=15;
int b=16;
int c=15;
int value = a;
switch (value)
{
case a:
// Value is A
break;
case b:
// value is B
break;
case c:
// value is C
break;
default:
// value is unknown
}
我们将永远不会执行C的代码,因为将改为执行A。切换的目的是检查具有唯一可测试值的值。它是一个干净的if..else if..else..if..else。
编译器在编译时分析常数值,以生成优化的查找表和决策树以快速选择案例。例如,如果不能使用表,则编译器可以使用3个cpu指令集生成高效的三叉决策树:与一个值进行比较以设置cpu标志,分支到其他情况下的分支,分支到其他情况下的分支或跌倒直到平等的情况。请记住,C / C ++与性能有关。也许将来会添加新的语法或扩展编译器,但是标准的改进尝试是递增的,并且不会破坏已经编写的代码,也不会使现有的编译器无效。