速通C语言函数

目录

目录

函数的定义

函数概述

函数定义

函数参数和返回值

形式参数和实际参数

函数返回值

函数的调用

函数调用的三种方式

函数声明

函数的嵌套调用和递归调用

嵌套调用

递归调用

变量的作用域

变量

变量的存储类别

内存空间

存储类别

习题巩固

习题作用

习题答案


函数的定义

函数概述

(1)函数定义角度:

库函数 由系统提供,无需定义,可直接使用,但需要在程序开头包含原型声明的头文件。如printf

用户自定义函数 :根据自己的需求编写,自定义函数不仅要在程序中定义函数本身,必须还要在主函数中调用该函数

(2)函数形式:

无参函数 在函数的声明、定义和调用中均不带参数

有参函数 在函数的定义、声明中都有参数

(3)函数兼有其他语言中函数和过程两种功能角度:

有返回值函数 函数被调用执行完毕,向调用者返回一个执行结果

无返回值函数 无返回值函数不需要向主调函数提供返回值

4.总结:

一个C语言程序是由一个多个函数组成,只有一个主函数(main函数)

一个C语言程序由一个多个源程序文件组成

一个C语言程序只有一个main函数main函数可以调用其他函数,其他函数不可调用main函数,其他函数可以相互调用,以main函数开头,main函数结尾

函数定义

一般形式:

类型标识符 函数名(类型 形式参数,...)

{

        声明部分

        执行部分

}

//例
long jiecheng(int k)   //类型标识符 函数名(类型 形式参数,...)
{
    long p=1;
    int i;    //声明部分
    for(i=1;i<=k;i++)
        p*=i;
    return p;   //执行部分
}

空函数定义格式:

类型说明符 函数名()

{

}

//例
void dummy()
{
}

函数参数和返回值

形式参数和实际参数

形式参数:形参,在定义函数时函数名后面括号中变量名称为形式参数

实际参数:实参,在主调函数中调用一个函数时,函数名后面括号中的参数称为实际参数

有参函数调用时,需要由实参向形参传递参数。当函数未被调用时,函数的形参并不占据实际的存储单元,也没有实际值;只有当函数被调用时,系统才为形参分配存储单元,并完成实参与形参的数据传递。

//例
#include<stdio.h>
int main()    //主函数
{
    int max(int x,int y);   //x,y为形参
    int a=2,b=3,c;
    c=max(a,b);     //a,b为实参
    printf("%d",c);
    return 0;
}
int max(int x,int y)   //子函数
{
    int z;
    x=3*x,y=3*y;
    z=x>y?x:y;
    return z;
}

函数调用的整个执行过程可分成四个步骤:
(1)创建形参变量,为每个形参变量建立相应的存储空间。
(2)值传递(传递数值,传递地址),即将实参的值传递给对应的形参变量。
(3)执行函数体,即执行函数体中的语句。
(4)函数返回(带回函数值、返回调用点、撤销形参变量)。

函数返回值

函数返回值:通过函数调用使主调函数能得到一个确定的值, 通常用return语句获得。

如果需要从被调用函数带回一个函数值供主函数使用,那么被调用函数必须含有return语句;反之,则不需要。

如果函数中没有 return语句,不代表函数没有返回值,只能说明函数返回值是一个不确定的数。
对于不带回值的函数,应当用 void 定义函数为“无类型”(或称“空类型”)。这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用被调用函数的返回值。此时,在函数体中不得出现 return 语句。

函数的调用

函数调用:程序中使用已经定义好的函数。除了主函数外,其他函数都需要通过函数调用来执行。

调用有参函数:函数名(实参列表)
调用无参函数:函数名()括号不能省略

函数调用的三种方式

1.表达式 函数调用出现在一个表达式中 要返回值 例 c=2*max(a,b)

2.参数 函数调用作为另一个函数调用的实参 要返回值 例 d=max(a,max(b,c))

3.语句 函数调用作为一个独立语句 不要求返回值 例 scanf函数的调用

函数声明

调用其他函数时,在调用前,要对其进行声明

函数声明一般形式:

类型标识符 函数名(类型 参数名,...)

类型标识符 函数名(类型,...)

函数原型:通过函数声明语句,向编译系统提供的被调函数信息(函数返回值类型,函数名,参数个数,各参数类型)

函数的嵌套调用和递归调用

嵌套调用

函数不允许嵌套定义,但是允许嵌套调用。嵌套调用,就是函数在被调用过程中又去调用其他函数

递归调用

将要解决的问题分解成比原问题规模小的子问题,当解决这个子问题时,又可以用到原问题的解决方法,并按照这一原则
逐步递推,最终将原问题转化成较小且有已知解的子问题

适用于:分解后的子问题必须与原问题相似

经典例题:汉诺塔问题

用递归求解问题的过程分为递推回归两个阶段。
递推阶段是将原问题不断地转化成子问题,逐渐从未知向已知推进,最终到送已知解的问题,即递推阶段结束。
回归阶段是从已知解的问题出发,按照递推的逆过程,逐一求值回归,最后到达递归的开始处,即结束回归阶段,获得问题的解。


 

变量的作用域

变量

全局变量函数外面定义的变量 作用域 全部函数

局部变量函数内部定义的变量 作用域 本函数

 注:在同一个函数中不能定义具有相同名字的变量,但是在同一个文件中全局变量和局部变量可以同名。当它们同名时,在局部变量作用范围,全局变量不起作用

//例
#include<stdio.h>
int a=10;    //a全局变量
int main()
{
    int max(int a,int b);
    int b,c,d;       //b,c局部变量
    scanf_s("请输入两个与10比较的数:%d%d",&b,&c);
    d=max(a,max(b,c));
    printf("最大的数为%d",d);
    return 0;
}
int max(int a,int b)    //在局部变量作用范围,全局变量不起作用
{
    int z;
    z=a>b?a:b;
    return z;
}

变量的存储类别

内存空间

(1)程序存储区 存储代码

(2)静态存储区 存放全局变量

(3)动态存储区 存放函数形参,自动变量及函数调用时的现场保护和返回地址

存储类别

静态存储方式和动态存储方式

(1)auto 自动型 定义自动变量时,前面可以加auto或不加,一般在函数内部复合语句内部使用。函数中的形参和在函数中定义的变量(包括在符合语句中定义的变量)都属于。系统在每次进入函数复合语句时,为定义的自动变量分配存储空间,并分配在动态存储区

(2)static 静态型

静态局部变量 定义静态局部变量时,前面加 statice 存储类型标识符。静态局部变量属于静态存储类别,在静态存储区内分配存储单元,在程序运行期间都不释放。静态局部变量是在编译时赋初值的,若没有显式赋初值,则系统自动赋初值 0(对数值型变量)或空字符(对字符变量)。以后,每次调用函数时不再重新赋初值,都是保留上一次函数调用结束时的

静态全局变量 如果在程序设计时希望某些全局变量只限于被本文件中的函数引用,而不能被其他文件中的函数引用,就应该在定义全局变量时加上 static 进行声明

(3)register 寄存器型 对寄存器变量的访问要比对内存变量访问速度快得多。如果将使用频率较高的数据存放在所定义的 register 变量中,可以提高运算速度

(4)extern 外部型 全局变量定义位置之前的函数需要引用该全局变量,应该在引用之前用关键字 extern 对该变量进行声明,表示把该变量的作用域扩展到这个位置。

#include<stdio.h>
int a=5,b=4;
int main()
{
    int c;     //正确,但是未使用extern
    c=a*b;
    printf("%d",c);
    return 0;
}

#include<stdio.h>
int main()
{
    int c;       //错误
    c=a*b;
    printf("%d",c);
    return 0;
}
int a=5,b=4;

#include<stdio.h>
int main()
{
	extern a,b;    //使用extern
    int c;
    c=a*b;
    printf("%d",c);
    return 0;
}
int a=5,b=4;

习题巩固

(1)写出pow()函数原理

提示:pow用power代替,用for语句,pow(2,3)=8

(2)计算 a^b!+b^a! 的值(以 2^3!+3^2! 为例)
提示:看成两步,一步是pow()函数,一步是求阶乘

(3)输入一个含10个元素的数组,求其中的平均值

(4)打印1!,2!,3!,4!,5!

提示:使用static静态局部变量

习题作用

(1)了解函数调用

(2)锻炼函数调用能力

(3)了解函数名作函数参数

(4)了解static静态局部变量的作用

习题答案

(1)

#include<stdio.h>
int main()
{
	int power(int x,int y);
	int a,b,c;
	scanf_s("%d%d",&a,&b);
	c=power(a,b);
   	printf("%d的%d次方=%d",a,b,c);
   	return 0;
}
int power(int x,int y)
{
	int i,z=1;
	for(i=1;i<=y;i++)
		z=z*x;
	return z;
}

(2)

#include<stdio.h>
#include<math.h>
int main()
{
	int jiecheng(int x);    //jiecheng=阶乘
	int a,b,sum;
	a=pow(2,3),b=pow(3,2);   //pow()函数内的值可以换
	sum=jiecheng(a)+jiecheng(b);
	printf("总和=%d",sum);
	return 0;
}
int jiecheng(int x)
{
	int i,y=1;
	for(i=1;i<=x;i++)
		y*=i;
	return y;
}

(3)

#include<stdio.h>
double average(double array[10]);
int main()
{
	double result,score[10]={60,95,85.5,45,86.5,98,36,54,68,87};
	result=average(score);
	printf("平均数=%lf",result);
	return 0;
}
double average(double array[10])
{
	double result=0;
	int i;
	for(i=0;i<10;i++)
	{
		result+=array[i];
	}
	return (result/10);
}

(4)

#include<stdio.h>
int main()
{
	int jiecheng(int i);   //jiecheng=阶乘
	int n;
	for(n=1;n<=5;n++)
		{
			printf("%d!=%d\n",n,jiecheng(n));
		}
} 
int jiecheng(int i)
{
	static int x=1;   //通过此例题,明白static的作用 
	x=x*i;
	return x;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值