第 11 章 函数
11.1 函数的基本概念
1. 什么是函数?
函数是具有特定功能的代码块
2. 函数的分类
库函数
自定义函数
11.2 函数基本语法
① 声明函数(定义函数)
函数四要素:
① 函数名,是标识符,需要满足标识符规范
② 函数体,该函数的代码块,写在 {} 中
③ 返回值和返回类型,返回值作为函数的计算结果
③ 参数,分为形参和实参
注意:强烈不建议函数嵌套声明,C语言也不允许函数嵌套!
② 调用函数
1. 函数名加小括号表示函数的调用,函数只有调用 函数体语句才执行,且每调用一次,函数体都执行一遍
2. 函数调用表达式的值是函数的返回值
③ 返回值
1. 有返回值: 返回类型与return右边表达式的值的类型一致;如果不一致会发生数据类型转换
2. 没有返回值: ①函数体中没有return语句; ②return的右边是空的;没有返回值的函数需要指定返回类型为 void*
3. return 除了能够设置函数返回值,还可以结束所在的函数
④ 参数
1. 形参
声明函数时所设置的参数,需要指定数据类型和形参名。形参的本质就是一个函数,只能在函数内部使用。
2. 实参
调用函数时所给的参数,用于给形参赋值,数量要与形参一致。
eg:形参
// 定义函数
void func(int x) // x表示的是形参
{
int num =100;
const double PI =3.14;
char msg[]="Hello";
printf("PI=%.2lf \n", PI);
printf("msg= %s \n",msg);
}
————————————————————————————————————————————
写法:函数外可以声明定义语句,但不能随便写其他语句
11.3 主函数
① 主函数返回值
C语言约定,主函数返回值0表示运行成功,如果返回其它非零整数,就表示运行失败。
一般主函数会在结尾写:return 0; // 表示运行成功
② 主函数参数(了解)
——main主函数,由系统调用
参数一: 命令选项的数量
参数二: 由所有命令选项组成的数组
eg:
// 定义(声明)主函数, 由系统调用主函数
int main(int argc, char *args[])
{
printf("Main Function: \n");
printf("argc=%d \n", argc);
// 遍历所有的选项
for (int i = 0; i < argc; i ++)
{
printf("%s \n", args[i]);
}
11.4 函数原型
作用:为了让主函数位置靠前一点,方便读代码
1. C语言中,【函数定义的语句】必须写在【函数调用语句】的前面,否则就用函数原型
2. 如果想把函数定义语句写在调用语句后面,可以在调用语句的前面使用【函数原型】提前声明函数
3. 函数原型需要指定函数的返回类型、函数名、参数类型,不需要设置函数体和参数名字。
eg:int arr(int);
11.5 作用域
① 作用域的概念
1. 作用域用于确定在代码中某个标识符(如变量、标识符常量、数组等)的可见性和访问范围,它决定了在程序的哪些部分可以引用或访问该标识符。
2. 作用域可以分为全局作用域、局部作用域、块级作用域。
3. 同一个作用域中 不能声明同名 的标识符。
② 全局作用域
1. 在函数和代码块(分支、循环)以外声明的变量、标识符常量、数组等,具有全局作用域,在程序的任何位置都可以被访问
2. 全局的变量、标识符产量、数组,【如果没有初始化赋值】,可以被【自动初始化为0】
③ 局部作用域
1. 在【函数内】定义的变量、标识符常量、数组等,具有局部作用域,作用范围仅限于该函数。
2. 局部的变量、标识符常量、数组,【如果没有初始化赋值】,会得到【垃圾值】,【不会被自动初始化】
——对于浮点数未被初始化,会得到垃圾值。由于浮点数与整数的存储方式不同,就不能识别01010,所以是0.000 000
3. 当使用某个变量(标识符常量、数组等)的时候,先从所在的作用域中查找,如果没有再去上层作用域查找。
4. 函数的上层作用域由【定义函数的位置】决定,与调用函数的位置无关
C语言标准不建议在函数内嵌套定义函数,函数的上层作用域就是全局。
5. 函数的形参也是局部变量,仅能在所在的函数内使用
④ 块级作用域
1. 在代码块【一个大括号 就是一个代码块】内(分支结构、循环结构、直接写大括号)定义的变量、标识符常量、数组等,具有块级作用域,作用范围仅限于所在的代码块。
2. 具有块级作用域的变量、常量、数组的特性与局部的变量、常量、数组一致,也可以称为局部变量、局部常量、局部数组
// 循环结构
for(int i=1; i < 3; i++)
{
int age = 100; // 每次循环都会新建一个age,i还是i
age ++;
printf("i=%d,age=%d ",i, age); // age都=101
}
⑤ 作用域和内存
内存区域 | 存放数据 |
---|---|
栈区(Stack) | 局部变量、局部标识符常量、局部数组等 |
全局静态区 | 全局变量、全局标识符常量、全局数组等 |
堆区 | ... |
代码区 | ... |
变量(标识符常量、数组)的生命周期:
局部变量: 函数调用结束就销毁;函数再次调用重新创建。
全局变量: 程序执行结束销毁。
注:只有自行创建的值才需要手动自行销毁
11.6 static 和 extern 关键字
① 静态局部变量
static
eg: static int num; // 没有初始化自动初始化为0
1. 存储在内存的【全局静态区】
2. 函数调用结束,静态局部变量不销毁,生命周期延长至[程序执行结束]
3. 没有初始化自动初始化为0
注:静态局部变量仍然是局部变量,作用域仍然是所在的函数!!!!
——除了作用域范围没变,其他都和全局变量一致
② 静态全局变量
注: 多文件编译,主函数只能有一个
1. 某个源文件中使用 extern 关键字声明外部链接之后,可以使用其他源文件中定义的全局【变量、标识符常量、数组】
eg:extern int num; //声明外部文件的标识符
2. 静态的【全局变量、标识符常量、数组】作用范围仅限于所在的源文件,其他源文件即使使用 extern 声明外部链接也无法使用。
③ 静态函数
同静态全局变量
标签:函数,作用域,C语言,int,数组,标识符,常量
From: https://www.cnblogs.com/petard/p/18122424