C语言常规优化策略
4 参数传递、宏定义、全局变量与汇编
按照结构化程序设计的原则,一种语言,如果具有赋值、选择与循环三种结构,并严格按照这三种结构
来组织程序,避免使用象goto语句这类使程序控制发生跳转的语言成分,在每一个程序块(如选择块、循
环块)中保持单向的输入流和输出流,写出的程序就算是结构化的程序,因此,前面三节有关赋值语句、
条件语句和循环语句的优化策略对于采用其它结构程序语言,如PASCAL,进行程序设计的程序员来说,
同样具有指导价值。
本节所讨论的话题比较杂乱,不过基本思想却是想将C语言中特有的,而在上面三节中没有介绍过的一些
程序优化的思想在这里集中讨论一下。这些话题包括参数传递的有效方式,宏定义与全局变量的使用,
以及使用汇编语言来优化代码等方面。其中,掌握C语言的参数传递的原理并加以正确使用,是每一个老
练的C程序员必须掌握的,其它三个话题多少都带有一定的争议性,因为这些程序设计技巧与软件工程的
某些原则是相违背的,但其中的奥秒却是:尽管违背原则,可总是有些程序员在使用。原因在于有些技
巧,如将简短的函数调用改为宏扩展往往可以大幅提高程序效率。正如结构化程序设计运动并没有从根
本上驱除goto语句一样,这些有争议的程序设计技巧可能还会长时间地在程序员中间流传下去。审慎的
做法是:继续使用它们,但不要过量。
4.1 C语言中函数的参数传递
C语言中函数的参数传递方式只有一种规则:传值规则。所谓传值,就是形参与实参之间只发生值的传递
。例如我们有一个计算绝对值的程序:
int MyAbs(int x)
{
if (x<0)
x=-x;
return x;
}
在函数的参数说明中出现的就是形参,如果我们要实际计算一些整数的绝对值时,就将这些整数(实参)
值代入函数的形参中,从而可以得到相应的返回绝对值,如MgAbs(-3)和MgAbs(0)等。
C编译器在处理函数调用时,通常是这样完成的:与函数的实际代码相关的有一片堆栈区域用来保存参数
值。如MyAbs(x)函数的代码必有一个整型栈单元用于保存整型变量x的值,当函数调用发生时,如调用
MyAbs(-3),将实参按次序和类型放入这一片堆栈单元,激活函数,函数执行过程中就会在取相应形参的
值时,从堆栈中指定的地方去取值,而取得的值就是传入的实参值。在这一过程中,实参本身将值传入
后不会受影响。例如,在下面的代码中:
y=-3;
z=MyAbs(-y);
y的值在MyAbs函数调用结束后仍为-3。
C语言的这种单一传值规则非常简单,相对于PASCAL语言中传值、传名等多种参数传递规则而言更统一,
更易理解。但这也在一些C的初学者中造成误会。例如,他们常问的一个问题是:如果函数要返回两个值
时怎么办呢?例如,若要求设计一个函数求一个数组中元素的最小值和最大值时怎么办呢?在前面已经给
出了这一问题的正确方法,为了给初学者一个好的答覆,我们这里再罗嗦几句。
因为函数的参数只能传值,而函数返回值只有一个,这时