C语言函数

当程序功能比较多,规模比较大时,会使得主函数变得庞杂、冗长,难以阅读、维护,并且功能代码不能复用。为了解决这种问题,C 语言引入了模块化程序设计的思想,类似于搭积木,事先将各个功能代码拆分为单独的程序模块,需要时,直接在 main 函数中进行“组装”即可。

函数,就是实现特定功能的程序模块,是 C 程序实现模块化思想的关键。在 C 语言中,函数分为以下 2 种:
(1)库函数。由系统、或第三方库提供,直接调用即可,无需关心函数内部实现,例如:printf、getchar……等函数。

(2)用户自定义函数。由程序员自己手动封装,需要了解函数内部实现。

如果系统库已经提供了实现某个功能的函数,直接调用系统库函数即可,否则需要用户自己编写代码实现。

函数由“名字、参数、返回值”组成,名字是调用函数的时候通过哪个名字,参数指的是传递什么数据,返回值是执行的结果。

“调用发射火箭的指令,1 号火箭放到 3 号发射架上,发射结果【成功】”:int i=fire(1,3);。函数可以没有参数,也可以没有返回值。

(一) 函数基础

1. 定义函数

在 C 语言中,函数既可以有参数,也可以没有参数。
定义无参函数的一般形式为:

类型名 函数名()
{
    语句;
}
或
类型名 函数名(void)
{
    语句;
}

其中,类型名用来指定函数返回值类型。如果函数没有返回值,可以将类型名写为 void。函数名后面小括号中,如果没有参数,可以不写或写为 void,表示调用该函数时无需传入数据,例如:getchar 函数。

无参函数:


void show(void) 		  //无参函数 show
{ 						//{ 函数开始标志
    printf("hello world"); 		//函数体
} 						//} 函数结束标志

定义有参函数的一般形式为:

类型名 函数名(形参列表)
{
    语句;
}

有参函数与无参函数唯一的不同,就是函数名后面多了参数列表,表示调用该函数时需要传入数据,例如:printf 函数。

有参函数:

void show(int num)				 //有参函数 show
{
    printf("num=%d\n",num);
}

【注意】
函数名后面小括号中的参数,本质上就是局部变量,在该函数被调用时,由外部为该参数变量进行赋值。

2. 调用函数

定义函数的目的就是为了调用函数,函数类型不同,调用方式也不相同。函数调用的一般形式为:
函数名 (参数列表);

如果要调用的函数没有参数,则不用传递参数列表;如果有参数,就要按照顺序和类型传递参数,参数之间用逗号分隔。

下面通过例子来了解函数调用。

#include<stdio.h>
void show() 			//定义 show 函数
{
    printf("hello world"); 		//输出“hello world”
}
int main(void)
{
    show(); 			//调用 show 函数
    getchar();
    return 0;
}

调用有参函数:

#include<stdio.h>
void show(int num) //定义 show 函数,形参为 num
{
    printf("num=%d",num); //输出形参 num 数值
}
int main(void)
{
    show(100); //调用 show 函数,传入 100
    getchar();
    return 0;
}

3. 实参与形参

提到参数的时候有“形参”、“实参”两个概念,全程是“形式参数”、“实际参数”。
函数形参,就是函数定义时函数名后面小括号中的变量。需要注意的是,形参只能是变量。
函数实参,就是调用函数时传入的数据。实参可以是字面量、变量、表达式……等。
通俗理解:形参是定义函数时候用的;实参是调用函数时候“实际”传递的数据。

#include<stdio.h>
void show(int num) //num 是形参
{
    printf("num=%d\n",num);
}
int main(void)
{
    int a=5;
    show(100); //100 是实参
    show(a);
    show(a+3);
    getchar();
    return 0;
}

4. 实参、形参的误解

在 C 程序中,函数实参无论是字面量、变量、表达式……最终都会将结果值赋给形参变量,赋值的顺序只与形参的顺序有关,与变量名无关。

示例代码如下:

#include<stdio.h>
void show(int a,int b) //形参 a、b
{
    printf("a=%d b=%d\n",a,b);
}
int main(void)
{
    int a=10,b=20;
    show(b,a); //实参 a、b
    getchar();
    return 0;
}

//运行结果
//a=20
//b=10

上述程序中,由于实参变量与形参变量名称相同,有的人误以为函数传参是根据变量名进行匹配,就会认为实参 a 赋值给形参 a、实参 b 赋值给形参 b,其实这是一种错误理解。
在 C 语言中,实参、形参赋值只与参数顺序有关,与参数名无关:第 1 个实参赋给第 1 个形参、第 2 个实参赋给第 2 个形参、依次类推……第 n 个实参赋给第 n 个形参。

5. 注意事项

(1)同一个.c 文件中,函数名之间不能重名。
(2)用户自定义函数一般需要放置在调用它的函数之前,如果放置在调用它的函数之后,就需要添加函数声明,把函数的声明放到调用之前,函数的实现可以写到后面。

void f2(int i1,int i2);//函数的声明、函数的定义
int main()
{
    f2(i2,i1);
    getchar();
    return 0;
}
void f2(int i1,int i2)//函数的实现
{
    printf("f2,i1=%d,i2=%d\n",i1,i2);
}

项目比较大的时候,一般统一把所有自定义函数的声明写到 main 之前,实现写到 main之后。

(3)调用函数的时候参数的个数和类型要匹配。
(4)不能在函数中定义函数。

6. 局部变量

前面讲过定义在函数内部的变量被称为局部变量。局部变量只能在当前函数中访问,不能跨函数访问。

//【错误的代码】
#include<stdio.h>
void show()
{
    int a=10; //局部变量 a
}
int main(void)
{
    show();
    printf("%d",a); //出错代码
    getchar();
    return 0;
}

(1) 函数内部的局部变量不能被其他参数操作;

(2) 函数的形参在函数内部可以当成普通变量看待,还是局部变量。

(3) 普通参数,进行函数调用的时候传递的是数据的“副本”,在函数内部对形参的赋值,不会影响外部的实参变量

void test(int i)//函数的形参在函数内部可以当成普通变量看待,还是局部变量
{
    printf("test 开始%d\n",i);
    i=9;//在函数内部对形参的赋值,不会影响外部的实参变量
    printf("test 最后%d\n",i);
}
int main()
{
    int a=5;
    test(a);//普通参数,进行函数调用的时候传递的是数据的“副本”
    printf("%d\n",a);
    getchar();
    return 0;
}

7. 函数返回值

按照有无返回值,函数可以分为无返回值函数和有返回值函数。对于无返回值函数的返回值类型为 void。对于有返回值函数,需要显示指定返回值类型,这类函数的返回值通过return 语句得到。

return 是 C 语言中的关键字,后面可以跟字面量、变量、表达式……等。例如:
return 100; //返回字面量 100
return a; //返回变量 a 的值
return a+b; //返回表达式 a+b 的运行结果

return 语句的作用主要有 2 个:
(1)当函数执行到 return 语句时,会将 return 后面的结果值返回给主调函数,也就是说,在主函数中可以得到被调函数中的数据。
(2)return 语句被执行时,含中 return 下面的语句将不再执行。因此,return 语句可以看作是函数执行结束的标志。

函数返回值类型指的是函数返回数据的类型。例如:
char getChar();
int getInt();

#include<stdio.h>
int getInt()
{
    int a=10;
    return a; //返回变量值
}
int main(void)
{
    int result=0;
    result=getInt(); //接收返回值
    printf("result=%d",result);
    getchar();
    return 0;
}

return 会终止函数的执行。

#include<stdio.h>
int getInt() //定义 getInt 函数
{
    printf("return 前\n");
    return 10; //执行 return 语句
    printf("return 后\n");
}
int main(void)
{
    int result=0;
    result=getInt(); //调用 getInt 函数
    printf("result=%d",result);
    getchar();
    return 0;
}

(二) 函数深入

1. 函数参数的传递方式:值传递

在 C 语言中,实参向形参传递数据方式是“值传递”。并且是单向的,只能实参向形参赋值,反之不行。当函数被调用时,系统会为形参变量分配内存空间,然后将实参的值复制到形参对应的内存空间中。因此,实参与形参对应的内存空间是不同的,但是内存空间中的数据是相同,形参相当于实参的一个副本。
由于形参只是实参的一个副本,那么修改实参将不会影响形参。

#include<stdio.h>
void show(int num)
{
    num++; //形参自加 1
    printf("形参 num=%d\n",num); //输出形参
}
int main(void)
{
    int num=20;
    show(num); //调用 show 函数,传入实参 num
    printf("实参 num=%d",num); //输出实参
    getchar();
    return 0;
}

2. 无返回值函数中的 return 语句

return 语句使用在无返回值函数中,后面直接加分号即可。表示只终止函数执行,不返回数据。

#include<stdio.h>
void show()
{
    printf("return 前\n");
    return; //执行 return 语句,终止函数执行
    printf("return 后\n");
}
nt main(void)
{
    show(); //调用 show 函数
    getchar();
    return 0;
}

3. 函数调用的其他形式

在 C 程序中,根据函数调用出现位置的不同,可以将其分为 3 种:

第 1 种 函数调用语句。

函数调用后面加上英文分号就是函数调用语句,大多数情况下用于无返回值函数,有时也会用于有返回值函数。例如:
show();
printf(“hello world”);
show 是用户自定义函数,实现向屏幕打印“hello world”的功能,该函数无返回值。
printf 是系统库函数,也实现了向屏幕打印“hello world”的功能,但是该函数是有返回值的,不过程序中一般使用不到。

第 2 种 函数调用表达式。

函数调用作为表达式的其中一项,出现表达式中。例如:

result=getInt();
result=100+getInt();
上面第 1 行语句,先调用 getInt 函数,然后将函数返回值赋值给变量 result。
第 2 行语句,先调用 getInt 函数,然后将函数返回值和 100 做加法运算,最后将运算结果赋值给变量 result。
当函数调用作为表达式时,要求该函数必须有返回值,也就是说必须是有返回值函数。

posted @ 2021-03-15 19:22  与鹿逐秋  阅读(718)  评论(0编辑  收藏  举报