13-问题所在
9.2.1 问题所在
我们看看与 imax()
函数相关的一些示例,该函数与 imin()
函数关系密切。程序清单9.4演示了一个程序,用过去声明函数的方式声明了 imax()
函数,然后错误地使用该函数。
程序清单9.4 misuse.c
程序
/* misuse.c -- 错误地使用函数 */
#include <stdio.h>
int imax(); /* 旧式函数声明 */
int main(void)
{
printf("The maximum of %d and %d is %d.\n",3, 5, imax(3));
printf("The maximum of %d and %d is %d.\n",3, 5, imax(3.0, 5.0));
return 0;
}
int imax(n, m)
int n, m;
{
return (n > m ? n : m);
}
第1次调用 printf()
时省略了 imax()
的一个参数,第2次调用 printf()
时用两个浮点参数而不是整数参数。尽管有些问题,但程序可以编译和运行。
下面是使用Xcode 4.6运行的输出示例:
The maximum of 3 and 5 is 1606416656.
The maximum of 3 and 5 is 3886.
使用 gcc
运行该程序,输出的值是 1359379472
和 1359377160
。这两个编译器都运行正常,之所以输出错误的结果,是因为它们运行的程序没有使用函数原型。
到底是哪里出了问题?由于不同系统的内部机制不同,所以出现问题的具体情况也不同。下面介绍的是使用PC和VAX的情况。主调函数把它的参数存储在被称为栈(stack)的临时存储区,被调函数从栈中读取这些参数。对于该例,这两个过程并未相互协调。主调函数根据函数调用中的实际参数决定传递的类型,而被调函数根据它的形式参数读取值。因此,函数调用 imax(3)
把一个整数放在栈中。当 imax()
函数开始执行时,它从栈中读取两个整数。而实际上栈中只存放了一个待读取的整数,所以读取的第2个值是当时恰好在栈中的其他值。
第2次使用 imax()
函数时,它传递的是 float
类型的值。这次把两个 double
类型的值放在栈中(回忆一下,当 float
类型被作为参数传递时会被升级为 double
类型)。在我们的系统中,两个 double
类型的值就是两个64位的值,所以128位的数据被放在栈中。当 imax()
从栈中读取两个 int
类型的值时,它从栈中读取前64位。在我们的系统中,每个 int
类型的变量占用32位。这些数据对应两个整数,其中较大的是3886。