C语言陷阱与技巧24节,做代码选择,你不一定都要使用if判断的

在C语言程序开发中,实现需求的解决方案往往不止一个。解决一个问题,程序员一般都能够设计出多个解决方案,并写出相应的C语言代码。可能有读者会觉得,解决问题的话,写出一种方法就可以了,给出多个方法没有意义,因为最终C语言程序也就只能使用其中一个而已,其他方案的工作都浪费了。

也许在其他编程语言的程序开发中,只要解决问题就可以,不过在C语言程序开发中,解决问题往往只是第一步,更多的工作一般都在接下来的精简代码和提升效率上。这是因为 C语言程序开发常常用在一些资源比较紧张,但是对效率要求又高的项目中。

在解决问题的多个解决方案中,各个方案的效率在不同的条件下使用,差异性常常比较大,所以C语言程序员要想写出优秀的程序,需要根据实际的情况,选择不同的方案。

编译时(compile time),和运行时(run time)

假设解决问题 P 有两套解决方案 funA() 和 funB()。不过,即使有两套解决方案,在实际应用中,也常只使用其中一套。确定解决方案后,作为C语言程序员,确定使用哪一套代码的方法有很多种,不过简要来说,这些选择方法可以分为“编译时”选择和“运行时”选择。

“编译时”选择代码主要借助C语言的预处理语法,下面是一个例子:

void solve()
{
#ifdef condition
    funA();
#else
    funB();
#endif
}

上面这段C语言代码使用了 #ifdef 预处理,如果希望使用解决方案 funA(),则C语言程序员应该 #define condition,此时 funB() 的代码不会参与编译。否则 solve() 就会使用解决方案 funB(),编译器不再编译 funA() 的代码。

究竟使用哪种解决方案,在编译时就确定了,所以这种选择方法称为“编译时”选择。

不过有时候C语言程序的用户希望可以在程序运行的过程中修改解决方案,这时显然就不能使用“编译时”选择了,因为要满足这种需求,funA() 和 funB() 的代码都必须参与编译。

void solve(bool cond)
{
    if(cond)
        funA();
    else
        funB();
}

麻烦的“运行时”选择

上面讨论的“运行时”选择相关的C语言代码非常简单,也非常常见,不过这种方法虽然能够解决问题,但是如果需要做选择的代码较多,整个C语言代码就显得啰嗦了。例如:

bool cond = user_choose;
void func1()
{
    if(cond)
        funA();
    else
        funB();
}
void func2()
{
    if(cond)
        funA();
    else
        funB();
}

显然,可能不止一处需要做解决方案选择,那么就得写多个 if 语句。要是 funcN() 非常多,对于程序员来说,就得写非常多的 if 语句,这显然太麻烦了,而且多处重复的C语言代码也不利于维护。对于C语言程序本身来说,做多个 if 判断也属于做多次重复工作,这会在一定程度上降低效率。

事实上,究竟使用哪种解决方案,只需要判断一次就可以了,请看:

bool cond = user_choose;
void (*funptr)();
void init()
{
    if(cond)
        funptr = funA;
    else
        funptr = funB;
}
void func1()
{
    funptr();
}
void func2()
{
    funptr();
}

上述C语言代码定义了函数指针 funptr,在 init() 函数中确定其指向,之后就无需再判断 cond 了。可以看出,使用函数指针后的代码相当简洁,而且也非常利于程序员维护,程序本身也无需做太多重复的处理。

事实上,不仅仅在选择解决方案时可以用到这个小技巧,在做程序向前兼容时,利用函数指针做代码选择也是一个不错的小技巧。

小结

本节主要介绍了C语言代码选择的两种方法,按照程序周期来说,可以简要分为“编译时”选择和“运行时”选择。在“运行时”选择中,借助函数指针常常可以精简代码,提升效率。

阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif