过马路,左右看
作者:乾坤一笑
其实,仔细想想,“过马路,左右看”是个很有道理的话。中国的车辆都是靠右行驶,所以过马路的时候前一半的过程(就是从路始边走到路中间的过程)总是车辆从我们左边开过来,而后一半的过程(从路中间到路右边的过程)总是车辆从右边开向左边。
于是,这个俗语就教导我们先看左边再看右边,甚至可以说走前一半的时候可以只看左边,走后一半的时候可以只看右边。如果把口诀反过来做,就做了无用功;如果没有这个口诀,没准过马路时头会摇的跟一个波浪鼓似的。(注1)。
中国人做事很讲究总结一个口诀,内功讲究心法,练刀有刀谱,练剑有剑诀,甚至书圣王曦之还写了个什么书诀(我忘了多少招了,那个兄弟提示下)。再比如《西游记》中说孙悟空过火焰山的时候把毛都烤糊了,于是左手捏了个避火诀冲了下去。这说明口诀很有用,本领大如孙大圣都用的上:虽然你不知道他是怎么来的,但是照着口诀做就没错——老祖宗已经验证过了才总结成口诀传下来。
其实软件开发的时候也有很多口诀,即便是不明白道理,但是照着做,总没错。如果不照着做,没准还真就捅了篓子,或者在代码中埋下了一时难以出现的隐患。下面就举一个C中的应用口诀的例子(C++我不懂,就不献丑拉。~)
比如,有个口诀叫做“定义宏常量或宏公式的时候,一定要加圆括号”,有很多人就不理解,于是他们就不加,结果就出了类似于如下的问题:
#define NUM_A 100#define NUM_B 25 * 2#define int_div(a, b) a / bfloat c;c = int_div(NUM_B, NUM_A); //作者原意是 50/100,实际结果是 25 * 2 / 100, 结果没错c = int_div(NUM_A, NUM_B); //作者原意是 100/50,实际结果是 100 / 25 * 2,结果错了。试想,如果我们就按照口诀来操作:#define NUM_A (100) #define NUM_B (25 * 2)#define int_div(a, b) ( (a) / (b) )又怎么会出错呢?再举个例子,比如有个口诀叫做“头文件里面只声明不定义”。如果不照这个口诀操作,也会出问题。比如:
//a.hint max(int a, int b){ return a>b?a:b;}//main.c#include "a.h"#include "a.h" //include 两遍后就会重复定义max(),结果出重复定义的错。int main(){return 0;}你肯能会说,我在.h里面加点料儿,保证它不重复定义,比如:
//a.h#ifndef _A_H_#define _A_H_int max(int a, int b){ return a>b?a:b;}#endif //_A_H_Okey,现在上面那个case确实搞定了(注2)。但是下面这个就又不行了:
//a.h#ifndef _A_H_#define _A_H_int max(int a, int b){ return a>b?a:b;}#endif //_A_H_//b.h#ifndef _B_H_#define _B_H_void foo();#endif //_B_H_//b.c#include "a.h"void foo(){ max(100, 200);}//c.h#ifndef _C_H_#define _C_H_void bar();#endif //_C_H_//c.c#include "a.h"void bar (){ max(300, 400);}//main.c#include "b.h"#include "c.h"int main(){ foo(); bar();return 0;}分开编译b.c、c.c和main.c都还可以通过,但是最后一link就玩儿完,因为max()被定义了两遍。所以如果max()的定义放在a.c文件里,而在a.h中只写max()的声明就不会有这个问题了。(注3)
综上所述,我想说的是:如果能通透理解口诀的含义那是最好(达到了心中有剑、见招拆招的境界,每招虽无口诀的形但是却暗含了口诀的神),如果不能通透理解,不妨先照着口诀做,而不是总跟前人总结口诀对着干,真是“不听老人言,吃亏在眼前”。做的多了,也就慢慢悟了,可以细细琢磨口诀的真正含义,总结口诀应用的场景,从而达到避开“听了老人言,吃亏在后面”的境界了!:p 这就是否定之否定么?我瞎说的。^_^注1:后来我想到:英国的车是靠左边开的,会不会他们教小孩子的口诀是:
when going across the road, look right then left! :p 注2:这里用了“头文件里面要加guard宏”的口诀,所以避免了一个问题!:p注3:后来释雪提出来,可以在.h中定义的函数加个inline来搞定。这个例子举的不好,我只是觉得函数定义和声明的