目录

函数
函数的基本概念
函数基本语法
主函数
函数原型
作用域
static 和 extern 关键字
常用系统函数(标准库函数)
递归函数


11 函数

11.1 函数的基本概念

① 什么是函数

1
函数是一种可重复使用的代码块,用于执行特定的任务或操作。

② 函数的分类

1
2
1. 库函数(标准函数)
2. 自定义函数

③ 函数四要素

1
2
3
4
5
6
7
8
9
10
11
1. 函数名
函数名也是标识符,需符合标识符规范。

2. 函数体
函数中的代码块。

3. 参数
分为形参和实参

4. 返回值
表示函数的计算结果,定义函数的时候需要在函数名前面指定返回值的类型

11.2 函数基本语法

① 声明函数(定义函数)

1
2
3
4
5
返回类型 函数名(参数列表)
{
函数体语句;
....
}

注意:

① 定义函数的时候,只有函数名和函数体是必须的,参数和返回值可以没有的。

② 如果函数没有返回值,函数类型使用 void

③ 如果没有参数小括号空着,多个参数使用逗号分隔。

② 调用函数

1
2
函数名();
函数名(参数列表);

注意:

① 函数不调用不执行,调用几次就执行几次。

② 函数名+小括号是个表达式,称为函数调用表达式,表达式的值是函数的返回值。

③ 返回值

1
2
3
4
1. 使用 return 语句设置返回值,return 右边表达式的值就是该函数的返回值。
2. 没有 return 语句或 return 语句的右边是空着,本函数没有返回值。
3. 返回类型需要与 return 右边表达式的值一致,如果不一致,发生数据类型转换。
4. 函数体中一旦执行到 return 语句,该函数结束,后面语句不再执行。

④ 参数

1
2
3
4
5
形参:
定义函数时,所设置的参数; 是个变量,需要指定类型,命名需符合标识符规范,只能在函数体中使用。

实参:
调用函数时所给的参数,用于给形参赋值(按顺序赋值),数量需要与形参一致,实参的形式是表达式(常量、变量、表达式等)

11.3 主函数

① 主函数返回值

1
C语言约定,主函数返回值0表示运行成功,如果返回其它非零整数,就表示运行失败。

② 主函数参数(了解)

1
2
3
4
int main(int argc, char *argv[])
{
// 函数体
}

参数一: 命令选项的数量
参数二: 由所有命令选项组成的数组(每个元素是字符串)

注意: 程序启动的时候,系统会自动调用主函数,并向主函数传递两个实参,不论我们是否为主函数写形参,系统都会向主函数传递实参。

11.4 函数原型

1
2
1. 函数原型表示对函数的声明,可以实现在函数定义语句的前面调用该函数。
2. 函数原型需要指定返回类型、函数名、形参, 形参可以只保留类型省略名字。

11.5 作用域

① 作用域的概念

  • 作用域用于确定在代码中某个标识符(如变量、标识符常量、数组等)的可见性和访问范围,它决定了在程序的哪些部分可以引用或访问该标识符。

  • 作用域可以分为全局作用域、局部作用域、块级作用域。

  • 同一个作用域中不能声明同名的标识符。

② 全局作用域

  • 在函数和代码块(分支语句、循环语句等)以外定义的变量、标识符常量、数组等具有全局作用域,在程序的任何地方都可以被访问,通常称它们为全局变量、全局常量、全局数组等。
  • 对于全局变量,如果没有显式指定初始值,它们将自动初始化为零值。对于全局数组,如果没有显式初始化它们,它们的元素将自动初始化为零值,字符数组,将初始化为空字符 \0

③ 局部作用域

  • 在函数内定义的变量、标识符常量、数组等具有局部作用域,只有在该函数内部才能被访问,通常称它们为局部变量、局部常量、局部数组等。
  • 函数的形参也是局部变量。
  • 与全局变量和全局数组不同,局部变量和局部数组如果没有显式初始化,它们的初始值是机器垃圾值,即系统之前分配给这块空间的值 。
  • 如果局部作用域中定义了与全局作用域中同名的标识符,优先使用本作用域中定义的数据。

④ 块级作用域

C99 标准增加的特性!

  • 在代码块(分支语句、循环语句等)中定义的变量、标识符常量、数组等具有块级作用域,只有在该代码块内部才能被访问,代码块通常具有花括号 {} 结构。

  • 这些被称为块级变量、块级常量、块级数组等,同时也可以被称为局部变量、局部常量、局部数组,且与函数中的局部变量、局部常量、局部数组具有相同的特性。

⑤ 标识符的查找过程

1
2
3
4
1. 当使用标识符的时候,先找所在的作用域,如果找到就使用,停止查找。
2. 如果所在作用域未定义,找上层作用域,如果找到就使用,停止查找。
3. 如果上层作用域未定义,一直向上查找,一直到全局。
4. 全局也未定义,报错!

注意: C 语言中,函数的上层作用域就是全局! 与该函数在哪里调用无关!

⑤ 作用域和内存

变量(标识符常量、数组)的内存存储区域:

内存区域 存放数据
栈区(Stack) 局部变量
静态区 全局变量
堆区
代码区 函数体代码

标识符(变量、标识符常量、数组名等)的生命周期:

1
2
3
全局: 程序执行结束才销毁。
局部: 函数开始调用的时候创建,函数调用结束销毁; 每调用一次就创建一次。
块级: 代码块执行完毕即销毁。

11.6 static 和 extern 关键字

① 静态局部变量(标识符常量、数组)

1
2
3
4
1. 作用域范围仍然是所在的函数
2. 存储在内存的静态区
3. 生命周期延长至程序执行完毕(函数调用结束不释放,下一次调用函数不需要重新创建变量)
4. 如果不显示初始化,系统能够自动初始化为 0。

除了作用域范围,其他特性同全局变量一致!

② extern 声明其他源文件中的全局标识符

1
2
3
1. C 编译器可以将多个源文件编译成一个可执行文件, 这多个源文件属于同一个工程。
2. C 中的全局变量(全局标识符)的作用域范围是整个工程,对整个工程可见。
3. 在某个源文件中如果需要使用其他源文件中定义的全局变量(全局标识符),要使用 extern 声明一下

extern 关键字的作用: 用于声明外部全局变量(全局标识符)。

③ 静态全局变量(静态全局标识符)

1
2
3
1、 使用 static 关键字修饰的全局变量称为静态全局变量。
2、 普通全局变量对整个工程可见,其他文件中,使用extern外部声明后,可以直接使用。静态全局变量仅对当前文件可见,其他文件不可访问,其他文件中可以定义与其同名的变量,两者互不影响。
3. 静态全局变量对于需要编译多个源代码文件的程序,能够有效地降低源文件之间的耦合,避免不同文件同名变量的冲突。

④ 静态函数

1
特点同静态全局变量

总结

可作用范围 是否自动初始化 内存存储区域 生命周期
局部变量 所在的函数 函数调用结束
静态局部变量 所在的函数 静态区 程序执行结束
全局变量 全局(整个工程) 静态区 程序执行结束
静态全局变量 全局(所在源文件) 静态区 程序执行结束

11.7 递归函数

递归函数的概念

1
一个函数在函数体内又调用了本身,我们称为递归调用,这样的函数就是递归函数。

递归函数成功执行需满足以下两个条件:

1
2
(1)必须有一个明显的结束条件。
(2)必须有一个趋近于结束条件的趋势。

11.8 常用系统函数(标准库函数)

在线手册地址: https://zh.cppreference.com/w/c/header

① 字符串函数

标准库头文件 <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 类型