当前位置:嗨网首页>书籍在线阅读

25-带参数的函数

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

5.6 带参数的函数

现在,相信读者已经熟悉了带参数的函数。要掌握函数,还要学习如何编写自己的函数(在此之前,读者可能要复习一下程序清单2.3中的 butler() 函数,该函数不带任何参数)。程序清单5.15中有一个 pound() 函数,打印指定数量的#号(该符号也叫作编号符号或井号)。该程序还演示了类型转换的应用。

程序清单5.15  pound.c 程序

/* pound.c -- 定义一个带一个参数的函数   */
#include <stdio.h>
void pound(int n);    // ANSI函数原型声明
int main(void)
{
     int times = 5;
     char ch = '!';      // ASCII码是33
     float f = 6.0;
     pound(times);        // int类型的参数
     pound(ch);           // 和pound((int)ch);相同
     pound(f);            // 和pound((int)f);相同
     return 0;
}
void pound(int n)        // ANSI风格函数头
{                        // 表明该函数接受一个int类型的参数
     while (n-- > 0)
          printf("#");
     printf("\n");
}

运行该程序后,输出如下:

#####
#################################
######

首先,看程序的函数头:

void pound(int n)

如果函数不接受任何参数,函数头的圆括号中应该写上关键字 void 。由于该函数接受一个 int 类型的参数,所以圆括号中包含一个 int 类型变量 n 的声明。参数名应遵循C语言的命名规则。

声明参数就创建了被称为形式参数(formal argument或formal parameter,简称形参)的变量。该例中,形式参数是 int 类型的变量 n 。像 pound(10) 这样的函数调用会把 10 赋给 n 。在该程序中,调用 pound(times) 就是把 times 的值( 5 )赋给 n 。我们称函数调用传递的值为实际参数(actual argument或actual parameter),简称实参。所以,函数调用 pound(10) 把实际参数 10 传递给函数,然后该函数把 10 赋给形式参数(变量 n )。也就是说, main() 中的变量 times 的值被拷贝给 pound() 中的新变量 n

注意 实参和形参 在英文中,argument和parameter经常可以互换使用,但是C99标准规定了:对于actual argument或actual parameter使用术语argument(译为实参);对于formal argument或formal parameter使用术语parameter(译为形参)。为遵循这一规定,我们可以说形参是变量,实参是函数调用提供的值,实参被赋给相应的形参。因此,在程序清单5.15中, timespound() 的实参, npound() 的形参。类似地,在函数调用 pound(times + 4) 中,表达式 times + 4 的值是该函数的实参。

变量名是函数私有的,即在函数中定义的变量名不会和别处的相同名称发生冲突。如果在 pound() 中用 times 代替 n ,那么这个 timesmain() 中的 times 不同。也就是说,程序中出现了两个同名的变量,但是程序可以区分它们。

现在,我们来学习函数调用。第1个函数调用是 pound(times)times 的值 5 被赋给 n 。因此, printf() 函数打印了5个井号和1个换行符。第2个函数调用是 pound(ch) 。这里, chchar 类型,被初始化为 ! 字符,在ASCII中 ch 的数值是 33 。但是 pound() 函数的参数类型是 int ,与 char 不匹配。程序开头的函数原型在这里发挥了作用。原型(prototype)即是函数的声明,描述了函数的返回值和参数。 pound() 函数的原型说明了两点:

  • 该函数没有返回值(函数名前面有 void 关键字);
  • 该函数有一个 int 类型的参数。

该例中,函数原型告诉编译器 pound() 需要一个 int 类型的参数。相应地,当编译器执行到 pound(ch) 表达式时,会把参数 ch 自动转换成 int 类型。在我们的系统中,该参数从 1 字节的 33 变成 4 字节的 33 ,所以现在 33 的类型满足函数的要求。与此类似,最后一次调用是 pound(f) ,使得 float 类型的变量被转换成合适的类型。

在ANSI C之前,C使用的是函数声明,而不是函数原型。函数声明只指明了函数名和返回类型,没有指明参数类型。为了向下兼容,C现在仍然允许这样的形式:

void pound(); /* ANSI C之前的函数声明 */

如果用这条函数声明代替 pound.c 程序中的函数原型会怎样?第1次函数调用, pound(times) 没问题,因为 timesint 类型。第2次函数调用, pound(ch) 也没问题,因为即使缺少函数原型,C也会把 charshort 类型自动升级为 int 类型。第3次函数调用, pound(f) 会失败,因为缺少函数原型, float 会被自动升级为 double ,这没什么用。虽然程序仍然能运行,但是输出的内容不正确。在函数调用中显式使用强制类型转换,可以修复这个问题:

pound ((int)f); // 把f强制类型转换为正确的类型

注意,如果 f 的值太大,超过了 int 类型表示的范围,这样做也不行。