编程的过程中难免会使用到switch语句,case如果少的情况下,效率和性能还可以,如果出项比较多的case的情况下,
还使用swtich,将会大大影响程序的性能。如何优化这样比较大的switch语句呢?有三种方法:
第一种方法就是根据频率来排列case的位置,对于频率较高的case放到前面,而不是按照
case的值得有序排列,例如:
switch(type)
{
case1:
break;
case2:
break;
…
case20:
break;
default:
break;
}
假设18,和19地使用频率最高,则修改为
switch(type)
{
case18:
break;
case19:
break;
case1:
break;
case2:
break;
…
case20:
break;
default:
break;
}
这种方法只使用于一些case语句不多的情况,如果case语句很多,最好还是采用后面两种方法。
第二种方法就是使用嵌套的switch,将原来的线性判断,修改二级树的形式判断,例子如下
switch(type)
{
case1:
break;
case2:
break;
…
case100:
break;
…
case200:
break;
default:
break;
}
修改为:
if(1
switch(type)
{
case1:Thiscaseisusedmost.Andthefrequencydescendsonebyeone.
break;
case2:
break;
…
case49:
break;
default:
break;
};//Thismaybeencapsulatedasafunction.
}elseif(51
switch(type)
{
case51:Thiscaseisusedmost.Andthefrequencydescendsonebyeone.
break;
case52:
break;
…
case99:
break;
default:
break;
};//Thismaybeencapsulatedasafunction.
}elseif()
{
…
}
这样就可以减少判断地次数,从而提高效率,并且在每一个switch中需要将频率使用比较高的case放到前面。
第三种方法,如果case的值是有序递增或者有一定规律的,就可以使用函数数组:
例如:可以抽象出所有的case处理函数需要的参数,这里简单的以一个整形参数为例,建设函数
可以抽象为:
inthandleCase1(void);
inthandleCase2(void);
inthandleCase3(void);
inthandleCase4(void);
typedefvoid(*handleCaseFunc)(void);
handleCaseFuncg_apFuncArray[200]
={
handleCase1,
handleCase2,
handleCase3,
...
handleCase199
};
根据这种方法,可以把一下的switch语句:
switch(type)
{
case1:
break;
case2:
break;
…
case100:
break;
…
case200:
break;
default:
break;
}
可以修改为:
g_apFuncArray[(type)-1](type);
是不是很简单呢?
不过这种方法也有一个缺点,就是初始化数组要细心,如果函数的位置搞错了,可就麻烦了。
当然,如果type的值很分散,没有规律可以找,例如:1,5,13,29,57...就不太适合使用
函数数组。实在想使用的话就只有修改设计了,将type的值修改的有规例。
我在优化switch的过程中遇到过type的值是有两段的,第一段是1~109,第二段是10001~10031,
我就编写了一个宏实现从type值到函数数组索引得转换
#defineGET_YPE_INDEX(type)(type)<10000?(type):(type)-9850;
之所以减9850是预留109~150以防备将来扩展使用。
当然如果是2,4,6,8这样的可以通过type/2来获得等等。
总之,编写switch语句要十分小心,如果在关键的代码路径里使用更要主要考虑case的多少对性能
的影响。希望本文对你有一定的帮助。
补充:
Switch的变量可以定义为枚举类型,枚举虽然也是整型,但具体值不需要手工维护。
增加一条指令,只是增加一个标号,然后两边的程序各自重新编译一下就OK了。
比如:
enumA{op1,op2};
改成:
enumA{op1,op_new,op2};
之后,原来的op2相当于序号自动加1,而你所需做的只是把程序得新编译一下。原来的都不用改。