C语言(8) 函数
2026/5/13 9:51:47 网站建设 项目流程

第五章 函数

一段功能代码,被称为函数

1. 为了避免代码的重复。 复用性。 开发不用从头开始(库函数)。
2. 模块化的思想 。 大问题,分解成小问题,逐个解决。
设计函数 ,高内聚,低耦合。 功能越单一越好 ,对外部依赖越少越好。
函数在使用前,需要先定义(告诉编译器有这个功能),再使用。 定义时包含(声明)

函数的定义

函数返回值 函数名(参数类表)
{
函数体;
return x;
}
参数列表 (数据类型 形式参数1,数据类型 形式参数2,数据类型 形式参数3...)
函数返回值 数据类型 ,函数在调用完毕后,一般情况都是有结果值。 这个值就有数据的类型 。 如果函数
的返回值 设计为void ,那么函数调用(使用)后,没有结果,也就没有数据

1. 如果设计函数的时候,没有给定函数返回值的 ,默认是int 。如果确实没有什么需要返回的,可以是
void 。
2. 如果函数的执行流程,运行到,return 是返回到,函数的调用处。 return后的代码,将不会被执
行。
3. 参数在传递的过程中,需要保证,参数的个数一致,类型 匹配(类型一致或可以隐式类型转换

//函数的定义,实现具体
int add()
{
int a =20;
int b =10;
int ret = a+b;
return ret; // 返回结果,返回函数调用的地方。
}
int main()
{
int result = add(); // 函数的使用,() 表示调用函数, int result = ret; int
result =30;
printf("result is %d\n",result);
return 0;
}

函数的调用

void fun1()
{}
void fun2(int arg1,int arg2) 形参,形式参数
{}
函数后面的圆括号,不可以省略。
函数名(); // fun1();
int a=0, int b=20 ;
// 参数个数一致, 数据类型也一致。
函数名(arg1,arg2); // fun2(a,b); 实参,实际参数

//函数的定义 ,实现具体
int add()
{
int a =20;
int b =10;
int ret = a+b;
return ret; // 返回结果,返回函数调用的地方。
}
int main()
{
int result = add(); // 函数的使用,() 表示调用函数, int result = ret; int
result =30;
printf("result is %d\n",result);
return 0;
}
主调函数,在这个示例中,main 是主调函数。调用功能的发起者。
被调函数 ,在main中使用add的功能,add 就是被动调用的函数。

函数的声明

在实际代码编写过程。没有办法保证, 函数的定义,一定在函数的调用前出现 (多文件编程)。编译器在编译的过程中,就会出现未登记函数,就会警告。为了避免这种情况, 就要对函数进行声明

int add(int a,int b); //声明
int main()
{
....
add(1+2,4*5); // 函数的调用,但是函数的定义在后面定义的,这时 会出现警告。
....

}
int add(int a,int b)
{
return a+b;
}
int add(int a,int b) ,函数的原型,函数头。 包含,函数名,参数列表(参数的个数,每个参数的数据类型) ,返回值的数据类型。

变量的作用域和生命周期

作用域:

变量定义后,可以被访问的区域。

局部作用域: 局部变量

变量作用域在离定义该变量最近的大括号内。当发生函数调用后,作用域发生了变化,在被调函数内部,在主调函数内部定义的变量,都不能使用。

#include <stdio.h>
int add()
{
return a+b; // 不能访问到主调的 a,b 变量 。
}
int main()
{
int a = 10; //局部作用域
int b =20;//局部作用域
int c = add();
return 0;
}

全局作用域: 全局变量

在所有的源文件( 同一个工程中 所有.c) , 在任意位置都可以直接使用的区域。
变量的定义,放在所有函数的外面。 就是全局变量

int a = 10; // 全局变量, 整个工程中,任意位置都可以被访问。
int b =20;
int add()
{
return a+b;
}
int main()
{
int c = add();
printf("c is %d\n",c);
return 0;
}

生命周期

定义:

变量从开辟内存空间开始 到 变量的内存空间的回收 结束 ,的这个时间段,被称为生命周期。

局部变量的生命周期

1. 函数内部定义的变量
2. 函数的参数
3. 函数内部定义的变量,一定要给初值。如果没有给,就是随机值

在定义开始的地方,申请内存。 执行到函数结束,空间回收。

全局变量的生命周期

1.在所有函数之外定义的变量。
2. 可以给初值。如果不给初值 ,由系统负责初始化为0 ;

全局变量,在a.out 正式运行起来前,就要把空间开辟好,在程序结束后,空间释放 。全局变量有全局生命周期。

  • 在同一个作用域中,标识符(变量名,数组名,函数名) ,不能同名。
  • 如果一个作用域大,一个作用域小,出现同名标识符。 出现隐藏。

变量的隐藏

int a = 10;
int b =20;
int add()
{
return a+b;
}
int main()
{
int a =1;
int b =3;
int c = add();
int d = a+b; // 这个地方使用的是,局部变量。全局变量被隐藏。
printf("c is %d\n",c);

return 0;
}

变量的存储类型

存储类型 数据类型 变量名;
1. auto int a; 用的相对少
2. register int b; 用的相对少
3.extern int c;
4.static int d;

1. auto,

自动存储类型 。 局部变量。 这个关键字 ,可以省略 。定义变量时,内存空间自动开辟,离开作用域时自动释放。内存的栈区(stack)。 函数内部定义的变量,函数的参数。

2. register

寄存器 . 建议编译器把某个变量存储在cpu的寄存器中。

register int c;

3. extern

外部变量。 声明。 导出,目的是为了让其他的源文件,可以使用

1.c
#include <stdio.h>
extern int a; // 声明,表示有这个变量,在其他的.c 中
extern int b;
extern void fun();
int main()
{
int c = a+b;
printf("a+b %d\n",c);
fun();
}
2.c
int a =10;// 定义,开辟内存空间
int b =20;
void fun()
{
}
gcc 1.c 2.c

4.static 静态的

可以修饰变量,或函数。 用static 修改的变量,内存的数据区

static 修改局部变量
如果局部变量前加 static ,变量的生命周期是整个程序运行的周期,但作用域不变。

第一运行fun函数时, i, 分配空间+初始化。 如果不是第一次运行,这个变量 ,就不会在分配空间,和初始化。相当于 static int i = 0,这段没有 了。


int fun()
{
static int i = 0 ;// 全局生命周期
i++;
return i;
}
int main()
{
int num = 0;
printf("input num");
scanf("%d",&num);
int j = 0 ;
int count = 0 ;
for(j=0;j<num;j++)
{
count = fun();
}
// i = 20; //errror ,不能访问i。 i本身是存在,但是没在i的作用域范围内
printf("count is %d\n",count);
return 0;
}

static 修饰全局变量

表示 这个变量只能在本模块(本源文件中 依然全局变量)中使用。其他的源文件 不可以使用。 static 的作用 限制作用域。

static 修饰函数

static 的作用 限制作用域。 避免函数重名

5. a.out 运行起来后的内存分布图

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询