C语言 六
目录
函数
函数的基本概念
函数基本语法
主函数
函数原型
作用域
static 和 extern 关键字
常用系统函数(标准库函数)
递归函数 
11 函数
11.1 函数的基本概念
① 什么是函数
1  | 函数是一种可重复使用的代码块,用于执行特定的任务或操作。  | 
② 函数的分类
1  | 1. 库函数(标准函数)  | 
③ 函数四要素
1  | 1. 函数名  | 
11.2 函数基本语法
① 声明函数(定义函数)
1  | 返回类型 函数名(参数列表)  | 
注意:
① 定义函数的时候,只有函数名和函数体是必须的,参数和返回值可以没有的。
② 如果函数没有返回值,函数类型使用 void
③ 如果没有参数小括号空着,多个参数使用逗号分隔。
② 调用函数
1  | 函数名();  | 
注意:
① 函数不调用不执行,调用几次就执行几次。
② 函数名+小括号是个表达式,称为函数调用表达式,表达式的值是函数的返回值。
③ 返回值
1  | 1. 使用 return 语句设置返回值,return 右边表达式的值就是该函数的返回值。  | 
④ 参数
1  | 形参:  | 
11.3 主函数
① 主函数返回值
1  | C语言约定,主函数返回值0表示运行成功,如果返回其它非零整数,就表示运行失败。  | 
② 主函数参数(了解)
1  | int main(int argc, char *argv[])  | 
参数一: 命令选项的数量
参数二: 由所有命令选项组成的数组(每个元素是字符串)
注意: 程序启动的时候,系统会自动调用主函数,并向主函数传递两个实参,不论我们是否为主函数写形参,系统都会向主函数传递实参。
11.4 函数原型
1  | 1. 函数原型表示对函数的声明,可以实现在函数定义语句的前面调用该函数。  | 
11.5 作用域
① 作用域的概念
作用域用于确定在代码中某个标识符(如变量、标识符常量、数组等)的可见性和访问范围,它决定了在程序的哪些部分可以引用或访问该标识符。
作用域可以分为全局作用域、局部作用域、块级作用域。
同一个作用域中不能声明同名的标识符。
② 全局作用域
- 在函数和代码块(分支语句、循环语句等)以外定义的变量、标识符常量、数组等具有全局作用域,在程序的任何地方都可以被访问,通常称它们为全局变量、全局常量、全局数组等。
 - 对于全局变量,如果没有显式指定初始值,它们将自动初始化为零值。对于全局数组,如果没有显式初始化它们,它们的元素将自动初始化为零值,字符数组,将初始化为空字符 
\0。 
③ 局部作用域
- 在函数内定义的变量、标识符常量、数组等具有局部作用域,只有在该函数内部才能被访问,通常称它们为局部变量、局部常量、局部数组等。
 - 函数的形参也是局部变量。
 - 与全局变量和全局数组不同,局部变量和局部数组如果没有显式初始化,它们的初始值是机器垃圾值,即系统之前分配给这块空间的值 。
 - 如果局部作用域中定义了与全局作用域中同名的标识符,优先使用本作用域中定义的数据。
 
④ 块级作用域
C99 标准增加的特性!
在代码块(分支语句、循环语句等)中定义的变量、标识符常量、数组等具有块级作用域,只有在该代码块内部才能被访问,代码块通常具有花括号
{}结构。这些被称为块级变量、块级常量、块级数组等,同时也可以被称为局部变量、局部常量、局部数组,且与函数中的局部变量、局部常量、局部数组具有相同的特性。
⑤ 标识符的查找过程
1  | 1. 当使用标识符的时候,先找所在的作用域,如果找到就使用,停止查找。  | 
注意: C 语言中,函数的上层作用域就是全局! 与该函数在哪里调用无关!
⑤ 作用域和内存
变量(标识符常量、数组)的内存存储区域:
| 内存区域 | 存放数据 | 
|---|---|
| 栈区(Stack) | 局部变量 | 
| 静态区 | 全局变量 | 
| 堆区 | … | 
| 代码区 | 函数体代码 | 
标识符(变量、标识符常量、数组名等)的生命周期:
1  | 全局: 程序执行结束才销毁。  | 
11.6 static 和 extern 关键字
① 静态局部变量(标识符常量、数组)
1  | 1. 作用域范围仍然是所在的函数  | 
除了作用域范围,其他特性同全局变量一致!
② extern 声明其他源文件中的全局标识符
1  | 1. C 编译器可以将多个源文件编译成一个可执行文件, 这多个源文件属于同一个工程。  | 
extern 关键字的作用: 用于声明外部全局变量(全局标识符)。
③ 静态全局变量(静态全局标识符)
1  | 1、 使用 static 关键字修饰的全局变量称为静态全局变量。  | 
④ 静态函数
1  | 特点同静态全局变量  | 
总结
| 可作用范围 | 是否自动初始化 | 内存存储区域 | 生命周期 | |
|---|---|---|---|---|
| 局部变量 | 所在的函数 | 否 | 栈 | 函数调用结束 | 
| 静态局部变量 | 所在的函数 | 是 | 静态区 | 程序执行结束 | 
| 全局变量 | 全局(整个工程) | 是 | 静态区 | 程序执行结束 | 
| 静态全局变量 | 全局(所在源文件) | 是 | 静态区 | 程序执行结束 | 
11.7 递归函数
递归函数的概念
1  | 一个函数在函数体内又调用了本身,我们称为递归调用,这样的函数就是递归函数。  | 
递归函数成功执行需满足以下两个条件:
1  | (1)必须有一个明显的结束条件。  | 
11.8 常用系统函数(标准库函数)
① 字符串函数
标准库头文件 <string.h>
| 函数 | 说明 | 
|---|---|
| strlen(str) | 返回str的长度(size_t类型) | 
| strcpy(str1,str2) | 将str2中的字符串复制到str1中(给str1重新赋值) | 
| strcat(str1,str2) | 将 str2 中的字符串追加到 str1 后面 | 
标准库头文件 <stdio.h>
| 函数 | 说明 | 
|---|---|
| sprintf() | 用于将格式化数据写入字符串。相比于 printf(),多了一个参数,第一个参数是要写入的字符串,后面参数与 printf() 一致。简单地讲,sprintf() 是将内容写入字符串而不是输出。 | 
| sscanf() | 用于从一个字符串中按照指定的格式提取数据。相比于 scanf(),多了一个参数,第一个参数是要提取数据的字符串,后面参数与 scanf() 一致。简单地讲,sscanf() 是从字符串中提取数据而不是从用户输入提取数据。 | 
② 日期时间函数
标准库头文件 <time.h>
| 函数 | 说明 | 
|---|---|
| time(&变量) | 获取当前日期赋值到变量中,该变量需是 time_t 类型 | 
| ctime(&时间值) | 将时间戳转为字符串并返回,时间值需是 time_t 类型 | 
| difftime(时间值1,时间值2) | 返回两个时间值的差,返回值是 double 类型,时间值需是 time_t 类型 | 
time_t是C语言中用于表示时间值的数据类型,它通常是一个整数类型(int ``或 long 或 long long),用于存储时间戳。时间戳是指从1970年1月1日(通常称为UNIX纪元)零时零分零秒(UTC时间)起至某一特定时刻所经过的秒数。
③ 数学计算函数
标准库头文件 <stdio.h>
| 函数 | 说明 | 
|---|---|
| sqrt(x) | 计算平方根 | 
| cbrt(x) | 计算立方根 | 
| pow(x,y) | 计算x的y次方 | 
| fabs(x) | 计算x的绝对值 | 
| ceil(x) | 向上取整 | 
| floor(x) | 向下取整 | 
| round(x) | 四舍五入取整 | 
| trunc(c) | 截断小数部分 | 
以上函数返回的都是 double 类型
.png)
.png)
.png)
.png)
.png)

.png)
.png)
.png)