C语言-函数
Posted 霏ིྀ宇ིྀ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言-函数相关的知识,希望对你有一定的参考价值。
函数
定义
若干相关的函数可以合并成一个“模块”
一个C程序由一个或多个源程序文件组成
一个源程序文件由一个或多个函数组成
说明:
一个源程序文件由一个或多个函数组成。
一个C程序由一个或多个源程序文件组成。
C程序的执行从main函数开始,调用其他函数后流程回到main函数,在main函数中结束整个程序运行。
所有函数都是平行的,即函数定义时是互相独立的,一个函数并不从属于另一个函数。
函数的分类:
1.从函数的定义角度分类
- 标准函数,即库函数
目前为止,我们所学习的printf()、scanf()等都是ANSI C标准定义的库函数。任意符合ANSI C的编译器,不管它支持什么平台,都必须提供这些函数供用户使用。
main()稍微特殊一点点C程序的执行从main函数开始调用其他函数后流程回到main函数在main函数中结束整个程序运行
- 用户自定义函数
用户按自己的意愿编写自己的函数,完成人员功能。
简单的用户自定义函数
#include <stdio.h>
void pstar();
main()
pstar();
void pstar()
printf("*******************\\n");
#include "stdio.h"
int f(int x)
x += 10;
return x;
int main()
int y = 0, x = 10;
y = f(x);
printf("%d,%d\\n", y, x);
2.从有无参数的定义角度分类
(1)无参函数。无参函数是指不带任何参数的函数。在调用一个无参函数时,主调函数与被调函数之间不进行参数传递。上图1
(2)有参函数。有参函数是指在函数定义和函数调用时带有参数的函数。函数定义时的参数称为形式参数(简称形参),函数调用时的参数称为实际参数(简称实参)在调用一个有参函数时,主调函数将实际参数的值传递给形式参数,供被调函数使用。
3.从有无返回值的角度分类
(1)有返回值函数。有返回值函数在被调用执行完后会:向主调函数返回一个执行结果,这个结果就称为函数的返回值。如数学函数就属于有返回值函数。在定义-一个有返回值函数时,应该对其返回值作类型说明。
(2)无返回值函数。无返回值函数用于完成某项特定的处理任务,执行完后不向主调函数返回一个函数值。如,前面例1中的pstar函数就是-一个无返回值函数。通常,定义一一个无返回值函数时,可说明其返回值类型为空类型,即void类型
4.从函数作用域的角度分类
(1)内部函数。内部函数是指只能被本程序文件中的其他函数调用的函数。
(2)外部函数。外部函数是指除了能被本程序文件中的其他函数调用之外,还可以被其他文件中的函数调用的函数。
模块化程序设计思想
函数特点
●C函数是一种独立性很强的程序模块,所有的函数都处于平等地位,不存在从属关系。
●一 个C程序的各个函数可以放在一一个程序文件内,也可以分散放在几个不同的程序文件中。
●通过函数调用可以实现不同函数之间的逻辑联系。
●一个C程序 总是从main函数开始执行,由main函数调用其他函数,而其他函数之间又可以相互调用。
函数定义的一般形式
定义函数的一般形式
类型标识符 函数名(形式参数表)
函数体
函数的定义方法
C语言规定,函数、变量等,都应该遵循原则:先定义、后使用。如果想要
使用函数,就必须在使用前进行定义。
定义函数应包括以下几个内容:
(1)指定函数的名字,以便以后按名调用;
(2)指定函数的类型,即函数的返回值类型.
(3)指定函数的参数,包括参数的类型、个数、名称、顺序
(4)指定函数的功能,这是最重要的,一个函数应该能够完成一个或若干个功能,不能完成功能的函数没有存在的意义。
定义无参函数
一般形式
类型名 函数名()
函数体
或
类型名 函数名(void)
函数体
函数名后面括号内的void表示为空,即函数没有参数。
函数体包括声明部分和语句部分
定义有参函数
例子
int f(int x)
x += 10;
return x;
一般形式
类型名 函数名(形式参数表列)
函数体
函数体包括声明部分和语句部分
定义空函数
类型名 函数名()
例如
void dummy()
函数的调用、参数和返回值
函数调用的一般形式为:
函数名();
函数名(实参表);
变量名=函数表达式(实参表);
函数的语句调用
一般形式为:
函数名(实参表);
说明:
这种调用方式用于调用不带有返回值的函数。
如果调用的函数无形式参数,则实参表可以没有,但函数名后面的小括号不能省略
例子
#include <stdio.h>
void sum(int a, int b, int c);
main()
int num1, num2, num3;
printf("num1=");
scanf("%d", &num1);
printf("num2=");
scanf("%d", &num2);
printf("num3=");
scanf("%d", &num3);
sum(num1, num2, num3);
void sum(int a, int b, int c)
int s;
s = a + b + c;
printf("%d+%d+%d=%d", a, b, c, s);
函数表达式调用
一般形式为:
变量名=函数表达式(实参表)
说明:
这种调用方式用于调用带有返回值的函数,函数的返回值将参加表达式的运算
例子
//表达式
int sum(int a, int b, int c);
main()
int num1, num2, num3, s;
printf("num1=");
scanf("%d", &num1);
printf("num2=");
scanf("%d", &num2);
printf("num3=");
scanf("%d", &num3);
s = sum(num1, num2, num3);
printf("%d+%d+%d=%d", num1, num2, num3, s);
int sum(int a, int b, int c)
int s;
s = a + b + c;
return s;
函数的调用几种形式:
- 无参数,无返回值时的调用
pstar ()
- 有参数,无返回值时的调用
min(a, b) ;
- 有参数,有返回值时的调用
c = min(a,b) ;
- 函数调用作为算术表达式的一部分
sum=f (num1) +f (num2) ;
- 函数调用作为另外-一个函数调用的参数
minnum = min(min(a,b), c) ;
函数的参数用于建立函数之间的数据联系。当一个函数调用另一个函数时,实际参数的值会传递给形式参数,以实现主调函数与被调函数之间的数据通信。同时,函数参数的运用还可提高一个函数的灵活性和通用性。
用函数的方法求1+2+100
#include <stdio.h>
void fun1();
main()
fun1();
void fun1()
int i, s = 0;
for (i = 1; i <= 100; i++)
s += i;
printf("%d", s);
函数的嵌套调用
使用函数嵌套调用,求三个数的最小值
#include <stdio.h>
int min_3(int, int, int);
int min_2(int, int);
main()
int a, b, c, minnum;
printf("a=");
scanf("%d", &a);
printf("b=");
scanf("%d", &b);
printf("c=");
scanf("%d", &c);
minnum = min_3(a, b, c);
printf("min is %d\\n", minnum);
int min_3(int x, int y, int z)
int minnum;
minnum = min_2(min_2(x, y), z);
return minnum;
int min_2(int x, int y)
if (x < y)
return x;
else
return y;
函数的递归调用
形式参数和实际参数:
形式参数(简称“形参”)是指定义函数时,跟在函数名后的小括号内的变量名。实际参数(简称“实参”)则是指调用函数时,跟在函数名后的小括号内的表达式。
实际参数与形式参数的关系如下:
(1)实参的数量应该与形参相同。如果一一个函数在定义时没有形参,则调用该函数时就不应有实参。
(2)实参的类型必须与形参一一致。
(3)定义函数时的形参只能是变量名,而调用函数时的实参则可以是变量名,也可以是常量或表达式。
(4)当简单变量作函数参数时,参数的传递是“值传递”,这是一种单向传递,即数据只能由实参传给形参,而不能由形参传回给实参。
函数的返回值
通常我们希望通过函数调用使主调函数能得到一个确定的值,这就是函数的返回值。
- 函数的返回值是通过函数中的 return 语句获得的。return语句将被调函数中的一个确定的值带回到主调函数中,供主调函数使用。
2.函数值的类型。既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型,例如下面是3个函数的首行;
int max(float x,float y) ; //函数值为整型
char letter(char c1 ,char c2); //函数值为字符型
double min (int x,int y) ; //函数值为双精度型
在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。函数类型决定返回值的类型
对于不带回值的函数,应当用定义函数为void类型
关于函数返回值的说明:
1.并不是每-一个自定义函数都必须有returm语句,如果–个函数不需要带回任何数据,那么这个函数可以没有returm语句。
2.函数中可以有多个returm语句,但这并不意味着一一个函数可以同时返回多个值。当执行到被调函数中的第-一个return语句时,就会立即返回到主调函数。也就是说,多个return语句中只有-一个return语句才有机会被执行。该函数时就不应有实参。
形式参数与实在参数的两种传递方式
形式参数就是在定义函数时,写在参数列表里面的内容。实际参数就是在调用函数时,传入的量。
-
形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。实参出现在主调函数中,进入被调函数后,实参变量不能使用。
-
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。而实参在主调函数中已分配内存单元。
-
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,都必须具有确定的值,以便把这些值传送给形参。
-
实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。
-
函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。
值传递方式:
#include<stdio.h>
void fun(int a, int b) // 此处a, b为形参
a++;
b++;
void mian()
int a=1, b=2;
fun(a, b); // 按传值方式调用函数fun,此处a,b为实参
printf("%d, %d\\n", a, b); // 输出a=1, b=2
地址传递方式:
#include<stdio.h>
void fun(int *a, int *b)
*a = 4;
*b = 5;
void mian()
int a=1, b=2;
fun(&a, &b); // 按传地址方式调用函数fun
printf("%d, %d\\n", a, b); // 输出a=4, b=5
变量的作用域(局部变量和全局变量)
变量按作用域分:
全局变量:在整个工程文件内都有效;“在函数外定义的变量”,即从定义变量的位置到本源文件结束都有效。由于同一文件中的所有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变量的值, 就能影响到其他函数中全局变量的值。
静态全局变量:只在定义它的文件内有效,效果和全局变量一样,不过就在本文件内部;
静态局部变量:只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;静态局部变量的生存期虽然为整个工程,但是其作用仍与局部变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
局部变量:在定义它的函数内有效,但是函数返回后失效。“在函数内定义的变量”,即在一个函数内部定义的变量,只在本函数范围内有效。
变量的存储类别(自动、静态、外部),变量的生存期
有4种存储类型,分别是auto(自动型)、static(静态型)、register(寄存器型)和extern(外部型)
register:
变量值存放在运算器的寄存器中
说明:
只有非静态局部变量和形参可定义为register变量,全局变量和静态局部变量不能定义为register变量。
一个系统中的寄存器数目是有限的,不能定义任意多个register变量。
在实践中很少使用register变量,因为目前很多编译器都具有优化选项,会自动把一些频繁使用的变量放在寄存器中以提高效率
auto
变量值存放在主存储器的动态存储区变量定义若缺省存储类型,则默认为“auto”。
说明:
动态存储方式,存储在动态存储区
变量定义中存储类别省略时,默认为auto型
auto型变量在函数/语句块被调用时分配内存,每次调用都重新分配,重新赋初值,调用结束则释放空间。
auto型变量如果不赋初值,则其值是一个不确定的值。
static
变量值存放在主存储器的静态存储区;程序执行开始至结束,始终占用该存储空间;
说明:
静态存储方式,在静态存储区分配单元,在程序运行期间都不释放。
静态局部变量具有可继承性,在整个程序运行期间只赋一次初值,以后调用不在重新赋初值,而只是保留上次调用后的值。
在定义时如果没有赋初值,则自动赋初值为该类型的零值。
静态局部变量具有全局的寿命和局部的可见性,作用域仍然是该函数/语句块内。。
extern
:声明可以多次,定义只能一次。
变量值存放在主存储器的静态存储区;程序执行开始至结束,始终占用该存储空间,其值可供其他源文件使用;
变量的生存期:变量从生成到被撤销的这段时间。实际上就是变量占用内存的时间。
按其生存期可分为 动态变量和静态变量
变量只能在其生存期内被引用,而变量的作用域直接影响变量的生存期
局部变量的作用域和生存期
在函数内部作定义说明的变量,也成内部变量,仅限于函数内。
生存期是从函数被调用的时刻到函数返回调用处的时刻(静态局部变量除外)。
内存中的用户存储区划分如下
程序 | 程序代码 |
---|---|
静态存储区 | 全局变量,静态局部变量 |
动态存储区 | 局部变量,形式参数等 |
##变量的生存期
所有变量都占着内存,变量什么时候占着内存,什么时候从内存消失,这叫做变量的生存周期。
总结:
对变量的定义,有两种属性:数据类型和存储类别,例如:
static int x;(定义静态局部变量或定义限于本文件使用的全局变量)
auto int y;(定义自动变量,即局部变量)
regiter int a;(定义寄存器变量,函数内部定义)
extern int b;(定义可被外文件引用的全局变量或声明已经定义的全局变量)
以上是关于C语言-函数的主要内容,如果未能解决你的问题,请参考以下文章