C语言-第五章-函数
一段功能代码,被称之为函数。
1. 为了避免代码的重复。 复用性。 开发不用从头开始(库函数)。
2. 模块化的思想 。 大问题,分解成小问题,逐个解决。
函数的特性:高内聚,低耦合(高内聚指函数内部各元素紧密相关,共同完成单一明确的任务。低耦合指函数间依赖关系尽可能弱化,通过清晰接口交互而非内部细节依赖)
功能越单一越好 ,对外部依赖越少越好。
函数在使用前需要声明。
函数的定义
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;
}
函数的调用
oid 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) ,函数的原型,函数头。 包含,函数名,参数列表(参数的个数,每个参数的数据
类型) ,返回值的数据类型。
变量的作用域和生命周期
作用域:变量定义后,可以被访问的区域。
全局作用域: 全局变量在所有的源文件( 同一个工程中 所有.c) , 在任意位置都可以直接使用的区域。变量的定义,放在所有函数的外面。 就是全局变量
局部作用域:只在某个{ }内有作用。
生命周期
变量从开辟内存空间开始 到 变量的内存空间的回收 结束 ,的这个时间段,被称为生命周期
局部变量:
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 , 外部变量。 声明。 导出,目的是为了让其他的源文件,可以使用.
extern
在h1.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();
}
在h2.c中:
int a =10;// 定义,开辟内存空间
int b =20;
void fun()
{
}
最后用gcc h1.c h2.c编译
static
可以修饰变量,或函数。 用static 修改的变量,内存的数据区。
static 修改局部变量
如果局部变量前加 static ,变量的生命周期是整个程序运行的周期。
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 的作用 限制作用域。 避免函数重名。
a.out 运行起来后的内存分布图


1,代码段, 存储的是编写的代码,二进制形式。只读。
2.数据段,全局变量,静态变量。没有给初值,系统全部初始化为0 。可读可写
3. 堆区,动态内存区。程序员手动申请和释放空间。最灵活
4.共享区, 库函数的实现。printf函数的定义。
5 栈区, 局部变量。函数的参数。 返回地址。内存自动申请,自动释放。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)