C语言函数
函数的概念
C语言中的函数就是一个完成某项特定的任务的一段代码,有时候被翻译成子程
序。这段代码是有特殊的写法和调用方法的。使用函数可以实现代码复用,提升
开发效率。
在C语言中一般会遇到两种函数:
- 库函数
- 自定义函数
库函数
标准库和头文件
C语言并不提供库函数。
ANSI C 规定了一些常用的函数标准,被称为标准库。
不同的编译器厂商根据标准库给出一系列函数实现。这些函数被称为库函数。
比如 printf() scanf()
各种编译器的标准库中提供了一系列的库函数,这些库函数根据功能的划分,都
在不同的头文件中进行了声明。
头文件包含
库函数是在标准库中对应的头文件中声明的,所以库函数的使用必须包含对应的
头文件。
自定义函数
语法形式
1 | ret_type fun_name(形式参数) |
ret_type 是函数返回值的类型,酌情设置,没有返回值就是 void 。
fun_name 是函数名,方便使用。
括号中放的是形式参数,不需要参数也可以用 void 。 如果有参数需要指
明参数类型和参数个数。
{}中是函数体,完成函数的计算过程。

自定义函数示例
假如现在自定义一个简单的函数 Add() , 传入两个整型参数,计算出这两个整型参
数的和并返回。
1 | int Add(int a, int b) |

函数的参数部分需要交代清楚:参数个数,参数类型,形参名称。
形参和实参
在函数使用过程中,把函数的参数分为实参和形参。
实参
在上述代码中,调用 Add 函数时将变量 x 和 y 的值传过去了,x 和 y 就是实参。
实参就是传递给函数的参数。
形参
在上述代码中, Add 函数定义时括号中的参数 a 和 b 就是形参。
不去调用 Add 的时候, a 和 b 只是形式上存在,并没有向内存申请空间,没有
实际存在,所以称作形参。
实参和形参的关系
通过监视来看一下实参和形参。
1 |
|

可以看到,形参取得了实参的值,但是形参和实参的地址不同,可以理解成形参
是实参的临时拷贝。
实参传值,对形参的操作不会影响实参。
实参传地址,对形参的操作会影响实参。
具体的会在后文介绍。
return 语句
在函数设计中经常会出现 return 语句。
return 后可以是值也可以是表达式。表达式会先执行再返回。
返回值与函数返回类型不一致,系统会自动将返回值隐式转换为函数返回
类型。
return 语句执行后,函数将立刻结束。
如果函数中存在分支语句,则需保证任意情况下都有 return 返回。
1 | void test1(void) |

数组做函数参数
1 | void set_arr(int arr1[10],int sz) |

函数的形参个数和实参个数要匹配
实参是数组,形参也可以是数组形式
形参如果是一维数组,数组大小可以不写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18void print_arr_2(int arr2[], int sz)
{
// 如果参数是一维数组,数组大小可以省略,编译器会根据传入的数组自动推断出数组大小。
// 这是一个简单的测试函数,演示了数组作为参数传递,并打印数组元素的值。
for (int i = 0; i < sz; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
}
int main()
{
int arr[10] = { 0 };
int sz1 = sizeof(arr) / sizeof(arr[0]);
print_arr_2(arr, sz1);
return 0;
}
形参如果是二位数组,行可忽略列不可忽略
1
2
3
4
5void print_arr_3(int arr2[][], int sz)
{
// 形参如果是二位数组,行可忽略列不可忽略
}
数组传参,形参不会创建新的数组
形参操作的数组和实参的数组实际上是同一个数组

通过监视窗口可以看到实际上用的就是同一个数组。
这里因为传数组名是传的地址,所以对形参的操作影响到了实参。
函数的嵌套调用
就是指函数之间的互相调用。
1 | void test4(void) |

注:函数不能嵌套定义
函数的链式访问
指将一个函数的返回值作为另外一个函数的参数传入。
1 | int a = 0; |

函数的声明和定义
函数的调用一定要满足先声明后使用。
1 | nt main() |

如果非要把函数的定义放在主程序后,那就在主程序执行前进行声明。
1 | void exp(void); // 函数声明 |

多个文件
当代码比较多时就不宜将代码放在同一个文件中,此时可以将函数的声明和定义
放在头文件中。再在源文件中包含这个头文件。
1 |
|
1 |
|

static 和 extern
static 和 extern 都是C语言中的关键字。
static 可以用来:
- 修饰局部变量
- 修饰全局变量
- 修饰函数
extern 是用来声明外部符号的
作用域
- 局部变量的作用域是变量所在的局部范围
- 全局变量的作用域是整个工程
生命周期
- 局部变量的生命周期是进入作用域变量创建,出作用域生命周期结束。
- 全局变量的生命周期是整个程序的生命周期。
static 修饰局部变量
1 | void exp2() |

这段代码中局部变量j是每次进入test函数先创建变量(生命周期开始)并赋值为
0,然后
++,再打印,出函数的时候变量生命周期将要结束
1 | void exp3() |

这段代码中 j 创建好后,出函数的时候是
不会销毁的,重新进入函数也就不会重
新创建变量,直接上次累积的数值继续计算。
static修饰局部变量改变了变量的生命周期。
static 修饰全局变量
extern 来声明外部符号的,如果一个全局的符号在A文件中定义的,在B文件中想
使用,就可以使用 extern 进行声明然后使用。
1 |
|
1 | extern int g_num1; // 声明外部全局变量 |

一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其
他源文件内使用。
1 |
|
1 | extern int g_num1; // 声明外部全局变量 |

全局变量默认具有外部链接属性,但在被 static 修饰后,就变为了内部链接属
性,只能在变量本身所在的源文件内使用。
static 修饰函数
1 |
|
1 | extern void ceshi(void); // 声明外部静态函数 |

用 static 修饰函数与修饰全局变量是类似的。只能在本源文件中使用。
函数默认具有外部链接属性,但在被 static 修饰后,就变为了内部链接属
性,只能在函数本身所在的源文件内使用。



