C语言_函数

1. 函数概念

函数(子程序):C语言中的函数就是一个完成某项特定的任务的一段代码。
注:

  • 一个C语言程序中仅有一个主函数main
  • C语言程序中总是从main函数开始,调用完其他函数后总是会回到main函数,最后在main函数中结束整个程序
  • 一个C语言程序中可以包含多个头文件,包含形式一般为#include<标准库中的头文件名>#include“自定义头文件名”
  • 在C语言中,一个函数不能直接定义在另一个函数内部。所有的函数定义必须位于全局作用域

2. C语言中函数的分类

在C语言中我们一般会见到两类函数:

  • 库函数
  • 自定义函数

2.1 库函数

C语言标准中规定了C语言的各种语法规则,C语言并不提供库函数,C语言的国际标准ANSI C规定了一些常用函数标准,被称为标准库,那不同的编译器厂商根据ANSI提供的C语言标准就给出了一系列函数的实现,这些函数就被称为库函数(如printfscanf等)。
库函数是在标准库中对应的头文件中声明的,因此库函数的使用,务必包含对应的头文件,包含形式如下:

#include<标准库中的头文件名>

库函数的学习和查看工具:
C/C++官⽅的链接:https://zh.cppreference.com/w/c/header
cplusplus.com:https://legacy.cplusplus.com/reference/clibrary/

2.2 自定义函数

顾名思义,自定义函数就是我们自己定义的函数,定义形式如下:

ret_type fun_name(形式参数)
{
函数体
}

  • ret_type函数返回类型
  • fun_name函数名
  • ( )中放的是形式参数
  • { } 中放的是函数体

例:
写⼀个加法函数,完成2个整型变量的加法操作。

#include<stdio.h>
int Add(int x, int y){
	int r = x + y;
	return r;
}
int main(){
	int a = 0;
	int b = 0;
	scanf("%d %d",&a,&b);
	int ret=Add(a,b);//将实参a,b传给形参x,y,运算后将返回值赋给ret。
	printf("add=%d",ret);
	return 0;
}

3. 函数的参数和return语句

函数的参数分为形式参数(形参)实际参数(实参),为了我们可以更好的理解,我们需要借用一下上方的代码:

#include<stdio.h>
int Add(int x, int y){
	int r = x + y;
	return r;
}
int main(){
	int a = 0;
	int b = 0;
	scanf("%d %d",&a,&b);
	int ret=Add(a,b);//将实参a,b传给形参x,y,运算后将返回值赋给ret。
	printf("add=%d",ret);
	return 0;
}

3.1 形参

在上方代码中,第2行定义函数时,函数名Add后面括号中的xy,称为形式参数,简称形参
你可能会问:为什么会叫形式参数呢?
答:

  • 实际上,如果只是定义了Add函数,而不去调用的话,Add函数的参数xy只是形式上存在的,不会向内存申请空间,不是真实存在的,所以叫形式参数。
  • 形式参数只有在函数被调用的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形参的实例化。

3.2 实参

在上方代码中,第10行调用函数时,传递给函数的参数ab,称为实际参数,简称实参。
实际参数就是真实传递给函数的参数。

3.3 形参和实参的联系

当我们在调用函数时,实参会传递给形参,形参再向内存申请一个空间然后进行运算,所以形参和实参各自是独立的内存空间。
函数执行完毕后,形参的内存空间会被释放,我们可以理解为形参是实参的一份临时拷贝。

3.4 return语句

函数定义中,经常会出现return语句,我们在使用return语句时要注意以下几点:

  • return语句后面可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果。
  • return后面也可以什么都没有,直接写return,这种写法适合函数返回类型是void的情况。
  • return返回的值和函数返回类型不一致时,系统会自动将返回的值隐式转换为函数的返回类型。
  • return语句执行后,函数就彻底返回,后面的代码不再执行。
  • 如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误。

4. 函数调用

4.1 传值调用

传值调用指的是函数调用时实际参数的值被赋值给形式参数。这意味着函数内部对于形参的修改并不会影响实参本身。

4.2 传址调用

  • 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
  • 传址调用可以让函数和函数外边的变量建立真正的联系,也就是函数内部可以直接操作函数外部的变量。

例:
交换两个数的值

void Swap(int *p1,int *p2){
	int tmp = 0;
	tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
int main(){
	int a = 0;
	int b = 0;
	scanf("%d %d",&a,&b);
	printf("交换前:a = %d,b = %d",a,b);
	Swap(&a,&b);
	printf("交换前:a = %d,b = %d",a,b);
	return 0;
}

5. 函数的嵌套调用和链式访问

5.1 嵌套调用

嵌套调用就是函数之间的互相调用。举例形式如下:

void i( ){

}
void j( ){
	i( )
}
int main(){
	j( );
	return 0;
}

上方代码只是嵌套调用的简约形式,旨在让各位感受一下嵌套调用的形式,并非程序全貌。不要模仿!!!

5.2 链式访问

链式访问就是将一个函数的返回值作为另一个函数的参数,像链条一样将函数串起来。
关于链式访问,这里有一个很有趣的例子:

#include <stdio.h>
int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
 	return 0;
}

在这里插入图片描述

在这里插入图片描述
printf函数返回的是打印在屏幕上的字符的个数。
上方的例子中,第一个printf打印的是第二个printf的返回值,第二个printf打印的是第三个printf的返回值。
第三个printf打印43,在屏幕上打印两个字符,返回2;
第二个printf打印2,在屏幕上打印一个字符,再返回1;
第一个printf打印1。
所以屏幕上最终打印4321。

6. 函数的声明和定义

6.1 函数声明

函数声明是在告诉编译器有一个函数叫什么,参数是什么,返回类型是什么,但是具体存在与否,函数声明决定不了。
注:
函数的声明一般是在函数使用之前的,先声明后使用
例:

#include<stdio.h>
int Add(int x,int y);
int main(){
	int a = 0;
	int b = 0;
	printf("%d"Add(a,b));
	return 0;
}

6.2 函数定义

函数定义是指函数的具体实现,交代函数的功能实现。
函数定义隐含了函数声明。
例:

int Add(int x,int y){
	return x + y;
}
int main(){
	int a = 0;
	int b = 0;
	printf("%d"Add(a,b));
	return 0;
}

到这里,各位会产生一个疑问,既然函数定义隐含了函数声明,那函数声明存在的意义是什么?
在未来的工程中,代码是比较多的,没有函数声明的话,假设我们需要在多个文件中调用同一个函数,就得多次在各个文件中定义这个函数,而函数声明的存在大大缩减了代码量,我给大家演示一下吧!
一般的,函数在.h文件中声明,在.c文件中定义。

add.c

 //函数的定义
 int Add(int x,int y){
	return x + y; 
}

add.h

//函数的声明
int Add(int x, int y);

test.c

#include <stdio.h>
#include "add.h"
int main()
{
 	int a = 10;
 	int b = 20;
 	//函数调⽤
	int c = Add(a, b);
 	printf("%d\n", c);
 	return 0;
}

这样的话,要是想调用函数,只需要在文件开头加上#include"Add.h"即可

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值