第三章-函数

一、函数的概念

函数是 c 语言的功能单位,实现一个功能可以封装一个函数来实现。

定义函数的时候一切以功能为目的,根据功能去定函数的参数和返回值。

二、函数的分类

1、定义角度分类

1、库函数 2、自定义函数 3、系统调用

2、参数角度分类

1、有参函数

​ 函数有形参,可以是一个,也可以是多个,类型随便

例如:

1
2
3
4
5
6
int fun(int a.float b.double c){

}
int max(int x,int y){

}

2、无参函数

函数没有参数,在形参列表的位置写 void 或者不写

1
2
3
4
5
6
int fun(void){

}
int fun(){

}

3、返回值角度分类

(1)带返回值的函数

在定义函数的时候,必须带有返回值类型,在函数题,必须有 return,没有返回值类型,默认返回值整形

例如:

1
2
3
4
5
char fun() //定义一个返回字符数据的函数
{
char b = 'a';
return b;
}
1
2
3
fun(){
return 1;
}

(2)没有返回值的函数

在定义函数的时候,函数名字前面加个 void

1
2
3
4
5
6
void fun(形参表){
;
;
return ;
;
}

在函数中不需要 return,如果想结束函数,返回到被调用的地方,return ;什么都不返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stido.h>
int main(int x,int y){
int z;
if(x>y)
z=x;
else
z=y;
return z;
}
void help(void){
printf("*********************\n");
printf("********帮助信息*****\n");
printf("*********************\n");
}
int main(){
int num;
help();
num = max(10,10+5);
printf("num=%d\n",num);
return 0;
}

三、函数的定义

1、定义方法

返回值类型 函数名字(形参列表){

​ //函数体,函数的功能写在函数体实现

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//定义一个没有参数也没有返回值的函数
void myfun1(){
printf("hello world\n");
}
return ;
//定义一个有参数的函数
void myfun2(){
int sum;
sum = a + b;
printf("%d + %d = %d\n", a , b , sum);
}
//定义一个有返回值的函数
int myfun3(int a,int b){
int sum;
sum = a + b;
return sum;
}

四、函数的声明

1、概念

对已经定义的函数,进行声明,可以多次

2、为什么声明

编译器在编译 c 时,上到下编译

3、声明方法

(1)主调函数和被调函数在同一个.c 中

1
2
3
4
5
6
7
void fun(void){
printf("hello world\n");
}
int main(){
fun();
}
//不需要声明

(2)被调函数在下,主函数在上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int main(){
fun();
}

void fun(void){
printf("hello world\n");
}
//需要声明
//1.直接声明
#include <stdio.h>
void myfun1();
void myfun2(int a,int b);
int myfun3(int a,int b);
int main(){
myfun1();
return 0;
}
void myfun1(){
printf("hello world\n");
return ;
}
void myfun2(int a,int b){
int sum;
sum = a + b;
printf("%d + %d = %d\n",a,b,sum);
}
int myfun3(int a,int b){
int sum;
sum = a + b;
return sum;
}

//2.间接声明
//a.c文件
#include "a.h"
int main(){
fun();
}
void fun(void){
printf("hellow world");
}
//a.h文件
extern void fun(void);

(2)主调函数和被调函数不在同一个.c 文件

1.直接声明 2.间接声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//myfun.c
#include "myfun.h"

void myfun1(){
printf("hellow world\n");
return;
}

//myfun.h
#ifndef MYFUN_H
#define MYFUN_H

void myfun1();

#endif


//main.c
#include <stdio.h>
#include "myfun.h"

int main(){
muyfun1();
return 0;
}

五、函数调用

变量 = 函数名(实参列表);带返回值

函数名(实参列表);不带返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>

void myfun1();
void myfun2(int a,int b);
int myfun(int a,int b);

int main(){
//没有参数也没有返回值
myfun1();
printf("*******************\n");

//有参数,没有返回值,需要在函数名传入实参
myfun2(100,90);
int x = 10, y=10;

//x、y:实参,实际参数,本质就是在被调函数的时候将参数的值传递给形参
myfun2(x,y);
printf("*******************\n");

//有参数也有返回值,可以一个变量接收函数执行结果(返回值),或者直接输出
int n;
n = myfun3(100,90);

printf("n = %d\n",n);
printf("sum=&d\n",myfun3(90,66));
return 0;
}

void myfun1(){
printf("hello world\n");
return ;
}

//a、b形参,存在实参的值
void myfun2(int a,int b){
int sum;
sum = a + b;

printf("%d + %d = %d\n",a,b,sum);
}
int myfun3(int a,int b){
int sum;
sum = a + b;
return sum;
}

1691654665160

六、变量的存储类别

1、内存的分区

物理内存:存储在存储设备

虚拟内存:操作系统虚拟出来的内存

操作系统会在物理内存和虚拟内存之间叫映射

2、运行程序的时候,操作系统会将虚拟内存进行分区

(1)堆

在动态申请内存的时候,在堆里开辟内存

(2)栈

存放局部变量

(3)静态全局区

1:未初始化的静态全局区

​ 静态变量(就是在前面添加 statiic),或者全局变量,没有初始化,存储在这里

2:初始化的静态全局区

​ 全局变量,静态变量,赋值初始值的,存储在这里

4、代码区

​ 存储在程序代码

5、文字常量区

​ 存放常量的

3、普通全局变量

在函数外部定义的变量

1
2
3
4
5
int num =100;//全局变量,需要声明 extern int num;
int main(){
return 0;
}
//生命周期:程序运行,整个过程,一直存在,知道程序结束
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

//定义一个普通全局变量,在main函数外的变量就是全局变量
//没有赋值,系统将赋值初始化0
int num;

void myfun(){
num= 888;
}
int main()
{
printf("num=%d\n",num);

myfun();

printf("num=%d\n",num);
return 0;
}

1691658185939

4、静态全局变量

定义全局变量的时候,用 static

作用范围:限定了静态全局变量的作业范围

生命周期:在程序整个运行中,都一直存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

//定义一个静态全局变量
//静态全局变量只能在其定义的.c文件中任意位置使用,不能跨文件使用
static int num;

void myfun()
{
num++;
}

int main(int argc, char *argv[])
{
printf("num = %d\n", num);

myfun();

printf("num = %d\n", num);

return 0;
}

1691658406783

5、局部变量

在函数内部定义,或者复合语句定义的变量

1
2
3
4
5
6
int main(){
int num;//局部
{
int a;//局部
}
}

作用范围:

在函数中定义的变量,在函数中有效

在复合语句中定义的,在复合语句中有效。

生命周期:

在函数调用之前,局部变量不占用空间,调用函数的时候,

才为局部变量开辟空间,函数结束了,局部变量就释放了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

//定义一个局部变量
//在函数内部定义的,不加任何修饰的变量都是局部变量
void myfun()
{
int num = 100;
num++;

printf("num = %d\n", num);

return ;
}

int main(int argc, char *argv[])
{
//局部变量只能在定义的函数内部使用,声明周期相对较短,函数结束,局部变量就会释

//printf("num = %d\n", num);
myfun();
myfun();
myfun();

return 0;
}

1691658579818

6、静态的局部变量

定义局部变量的时候,前面加 static 修饰

作用范围:

在它定义的函数或复合语句中有效。

生命周期:

第一次调用函数的时候,开辟空间赋值,函数结束后,不释放, 以后再调用函数的时候,就不再为其开辟空间,也不赋初值, 用的是以前的那个变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>

//定义一个静态局部变量
//在函数内部定义的使用static修饰的变量就是静态局部变量

void myfun()
{
//如果普通局部变量不进行初始化,则默认是随机值
//如果静态局部变量不进行初始化,则默认是0
int a; //普通局部变量
static int num; //静态局部变量

printf("a = %d\n", a);
printf("num = %d\n", num);
}

void myfun1()
{
//静态局部变量不会随着当前函数执行结束而释放空间,下次使用的函数之前的空间
//静态局部变量只会初始化一次
static int num1 = 100;
num1++;

printf("num1 = %d\n", num1);
}

int main(int argc, char *argv[])
{
myfun();

myfun1();
myfun1();
myfun1();

return 0;
}

1691658688779

1:定义普通局部变量,如果不赋初值,它的值是随机的。

定义静态局部变量,如果不赋初值,它的值是 0

2:普通全局变量,和静态全局变量如果不赋初值,它的值为 0

7、外部函数

咱们定义的普通函数,都是外部函数。 即函数可以在程序的任何一个文件中调用。

在分文件编程中,只需要将函数的实现过程写在指定的.c 文件中,然后将其声明写在指定

的.h 文件中,其他文件只要包含了头文件,就可以使用外部函数

8、内部函数

内部函数也称之为静态函数,就是用 static 修饰的函数

在定义函数的时候,返回值类型前面加 static 修饰。这样的函数被称为内部函数。

static 限定了函数的作用范围,在定义的.c 中有效。

外部函数,在所有地方都可以调用,

内部函数,只能在所定义的.c 中的函数调用

扩展:

在同一作用范围内,不允许变量重名。

作用范围不同的可以重名。

局部范围内,重名的全局变量不起作用。(就近原则)

1
2
3
4
5
6
7
8
int num = 100; //全局变量
int main()
{
//如果出现可以重名的情况,使用的时候满足向上就近原则
int num = 999; //局部变量

return 0;
}