函数的参数
在函数声明中,形参名可以省略,而只写形参的类型。 因为编译系统只关心和检查参数个数和参数类型,而不检查参数名,在调用函数时只要求保证实参类型与形参类型一致,而不必考虑形参名是什么。
函数的实参可以是常量、变量或表达式,但要求它们有确定的值。 例如max(3, a+b); 在调用时将实参的值赋给形参(值传递,而且是单向传递,实参和形参在内存中占有不同的存储单元),实参与形参的数据类型
应相同或赋值兼容
。
当使用数组名
做函数实参时,不是把数组元素的值传递给形参,而是把实参数组的首元素的地址
传递给形参数组,这样两个数组就共占
同一段内存单元。 这种情况下如果形参数组中元素的值发生了变化,也会使实参数组元素的值同时发生变化。
当使用多维数组名做函数参数时, 函数中对形参数组的定义可以指定每一维的大小,也可以省略第一维的大小说明,但不能把第二维以及其他高维的大小说明省略。
void(int array[2][2]){} //合法
void(int array[][2]){} //合法,且等价于第一种
void(int array[][]){} //不合法
函数与全局变量
在一个函数中既可以使用本函数中的局部变量,也可以使用有效的全局变量。
由于同一文件中的所有函数
都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值,就会影响
到其他使用了此全局变量的函数。也改变了全局变量的值。由于函数调用只能带回一个函数返回值,因此有时可以利用全局变量来增加函数间的联系渠道,通过函数调用能得到一个以上的值。
#include <stdio.h>
float Max = 0, Min = 0; //全局变量
float average(float array[], int n)
{
float aver;
float sum = array[0];
Max = Min = array[0];
for (int i = 0; i < n; i++)
{
if (array[i] > Max)
{
Max = array[i]; //修改全局变量
}
if (array[i] < Min)
{
Min = array[i]; //修改全局变量
}
sum = sum + array[i];
}
aver = sum / n;
return aver;
}
int main(void)
{
float score[10] = { 88,87,89,91,93,86,90,81,83,85 };
float ave;
ave = average(score, 10);
printf("max = %4.2f min = %4.2f average = %4.2f", Max, Min, ave);
}
如果在同一个源文件中,全局变量与局部变量同名,此时在局部变量的作用范围内,局部变量有效,全局变量则被“屏蔽”,不起作用。
程序设计的原则要求各模块具有“强内聚性”,和与其他模块的“低耦合性”。全局变量是不符合这一规则的,所以应该避免使用全局变量。
内部函数和外部函数
函数本质上是全局的, 我们定义一个函数就是为了在别的函数中调用它。如果不加声明,一个源文件中的函数既可以被本文件
中其他函数调用,也可以被其他文件
中的函数调用。但是,也可以指定
某些函数不能被其他文件调用。
根据函数能否被其他源文件调用,将函数区分为内部函数
和外部函数
。
外部函数
如果在定义函数
时,在函数的首部最左端加上关键字 extern,则此函数为外部函数,可供其他文件调用
。
但我们知道,函数本来就是可以被外部文件调用的,是因为在我们定义函数时,如果不指定
函数是内部函数还是外部函数,系统自动默认
函数为外部函数
。
//file1.c文件
#include <stdio.h>
void fun()
{
printf("我是fun函数,来自file1.c\n");
}
//main.c文件
#include <stdio.h>
extern void fun(); //对函数进行声明,等价于void fun();
int main()
{
fun(); //我是fun函数,来自file1.c
return 0;
}
根据上面的例子就可以看出,使用 extern 声明就能够在本文件中调用在其他文件中定义的函数,或者说把该函数的作用域
扩展到本文件。
由于函数本身默认就是外部的,所以声明函数时可以省略extern。
内部函数
如果一个函数只能被本文件
中的其他函数调用,它称为内部函数
。在定义内部函数时,在函数名和函数类型前要加上 static 关键字,即:
static void fun()
{}
内部函数又称静态函数
,静态函数的作用域
只局限于所在文件,且优先级
高于同名外部函数。这样,程序不同的源文件中即使有同名的内部函数,也互不干扰。
例:
//file1.c文件
#include <stdio.h>
void fun()
{
printf("我是fun函数,来自file1.c\n");
}
//main.c文件
#include <stdio.h>
static void fun()
{
printf("我是正主");
}
extern void fun(); //声明了外部函数,但没有效果,可以认为static把它屏蔽了。
int main()
{
fun(); //我是正主
return 0;
}
函数声明的作用
由外部函数和内部函数就可以理解函数声明的作用了。
使用函数声明
能够把函数的作用域
扩展到当前文件全部范围(就是被调用函数定义位置在调用它的那个函数下面的情况),或者扩展到定义该函数的文件之外,只需要在使用该函数的每一个文件中包含该函数的声明即可。
函数声明通知编译系统:该函数在本文件中稍后定义,或在另一文件中定义。