C语言代码大小优化,C语言代码优化三

当switch语句中的case标号很多时,为了减少比较的次数,明智的做法是把大switch语句转为嵌套switch语句。把发生频率高的case标号放在一个switch语句中,并且是嵌套switch语句的最外层,发生相对频率相对低的case标号放在另一个switch语句中。比如,下面的程序段把相对发生频率低的情况放在缺省的case标号内。

pMsg=ReceiveMessage();

switch (pMsg->type)

{

case FREQUENT_MSG1:

handleFrequentMsg();

break;

case FREQUENT_MSG2:

handleFrequentMsg2();

break;

。。。。。。

case FREQUENT_MSGn:

handleFrequentMsgn();

break;

default://嵌套部分用来处理不经常发生的消息

switch (pMsg->type)

{

case INFREQUENT_MSG1:

handleInfrequentMsg1();

break;

case INFREQUENT_MSG2:

handleInfrequentMsg2();

break;

。。。。。。

case INFREQUENT_MSGm:

handleInfrequentMsgm();

break;

}

}

如果switch中每一种情况下都有很多的工作要做,那么把整个switch语句用一个指向函数指针的表来替换会更加有效,比如下面的switch语句,有三种情况:

enum MsgType{Msg1,Msg2,Msg3}

switch (ReceiveMessage()

{

case Msg1;

。。。。。。

case Msg2;

。。。。。

case Msg3;

。。。。。

}

为了提高执行速度,用下面这段代码来替换这个上面的switch语句。

/*准备工作*/

int handleMsg1(void);

int handleMsg2(void);

int handleMsg3(void);

/*创建一个函数指针数组*/

int (*MsgFunction [])()={handleMsg1,handleMsg2,handleMsg3};

/*用下面这行更有效的代码来替换switch语句*/

status=MsgFunction[ReceiveMessage()]();

有些机器对JNZ(为0转移)有特别的指令处理,速度非常快,如果你的循环对方向不敏感,可以由大向小循环。

旧代码:

for (i = 1; i <= MAX; i++)

{

。。。

}

新代码:

i = MAX+1;

while (--i)

{

。。。

}

不过千万注意,如果指针操作使用了i值,这种方法可能引起指针越界的严重错误(i = MAX+1;)。当然你可以通过对i做加减运算来纠正,但是这样就起不到加速的作用,除非类似于以下情况:

旧代码:

char a[MAX+5];

for (i = 1; i <= MAX; i++)

{

*(a+i+4)=0;

}

新代码:

i = MAX+1;

while (--i)

{

*(a+i+4)=0;

}

一些公用处理模块,为了满足各种不同的调用需要,往往在内部采用了大量的if-then-else结构,这样很不好,判断语句如果太复杂,会消耗大量的时间的,应该尽量减少公用代码块的使用。(任何情况下,空间优化和时间优化都是对立的--东楼)。当然,如果仅仅是一个(3==x)之类的简单判断,适当使用一下,也还是允许的。记住,优化永远是追求一种平衡,而不是走极端。

要提升循环的性能,减少多余的常量计算非常有用(比如,不随循环变化的计算)。

不好的代码(在for()中包含不变的if()):

for( i。。。)

{

if( CONSTANT0 )

{

DoWork0( i );//假设这里不改变CONSTANT0的值

}

else

{

DoWork1( i );//假设这里不改变CONSTANT0的值

}

}

推荐的代码:

if( CONSTANT0 )

{

for( i。。。)

{

DoWork0( i );

}

}

else

{

for( i。。。)

{

DoWork1( i );

}

}

如果已经知道if()的值,这样可以避免重复计算。虽然不好的代码中的分支可以简单地预测,但是由于推荐的代码在进入循环前分支已经确定,就可以减少对分支预测的依赖。

在编程中,我们常常需要用到无限循环,常用的两种方法是while (1)和for (;;)。这两种方法效果完全一样,但那一种更好呢?然我们看看它们编译后的代码:

编译前:

while (1);

编译后:

mov eax,1

test eax,eax

je foo+23h

jmp foo+18h

编译前:

for (;;);

编译后:

jmp foo+23h

显然,for (;;)指令少,不占用寄存器,而且没有判断、跳转,比while (1)好。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值