C语言-函数
目录
一. 函数
一段功能代码,被称为函数。
1. 为了避免代码的重复。复用性。开发不用从头开始(库函数)。
2. 模块化的思想。大问题,分解成小问题,逐个解决。
3. 设计函数,高内聚,低耦合。功能越单一越好,对外部依赖越少越好。
1.1 函数定义
函数返回值 函数名(参数列表)
{
函数体;
}
参数列表:
参数列表:(数据类型 形式参数1,数据类型 形式参数2...)
eg:
#include<stdio.h>
int add()
{
int a = 10, b = 20;
int ret = a + b;
return ret;//返回至函数调用的地方
}
//加
int Add2(int arg1, int arg2)
{
int ret = arg1 + arg2;
return ret;
}
//减
int Sub(int arg1, int arg2)
{
int ret = arg1 - arg2;
return ret;
}
//乘
int Mul(int arg1, int arg2)
{
int ret = arg1 * arg2;
return ret;
}
//除
int Div(int arg1, int arg2)//arg1,arg2是形参,形式参数
{
int ret = arg1 / arg2;
return ret;
}
int main()
{
int result = add();//()表示函数调用
printf("result is %d\n",result);
int a, b;
printf("input 2 number:");
scanf("%d %d",&a,&b);
int add = Add2(a,b);//直接传递参数,不需要类型,a,b都是实参,实际参数
//int add = Add2(int a, int b) 不需要传递类型
int sub = Sub(a,b);
int mul = Mul(a,b);
int div = Div(a,b);
printf("add=%d,sub=%d,mul=%d,div=%d\n",add,sub,mul,div);
return 0;
}
注意:
1、函数传参时直接传递参数,不需要类型
2、如果设计函数的时候,没有给定函数返回值的 ,默认是int 。如果确实没有什么需要返回的,可以是void 。
3、如果函数的执行流程运行到return 处,则返回到函数的调用处。 return后的代码,将不会被执行。
4、参数在传递的过程中,需要保证,参数的个数一致,类型匹配(类型一致或可以隐式类型转换)。
1.2 函数声明
声明放在头文件之后,主函数之前。
在实际代码编写过程。没有办法保证函数的定义一定在函数的调用前出现 (多文件编程)。编译器在
编译的过程中,就会出现未登记函数,就会警告。为了避免这种情况, 就要对函数进行声明。
int Add(int arg1, int arg2);
int Sub(int arg1, int arg2);
int Mul(int arg1, int arg2);
int Div(int arg1, int arg2);
二. 变量的作用域与生命周期
2.1 变量的作用域
作用域: 变量定义后,可以被访问的区域。
局部作用域: 局部变量作用域在离定义该变量最近的大括号内。当发生函数调用后,作用域发生了变化,在被调函数内部,在主调函数内部定义的变量,都不能使用。
int add()
{
return a + b;//被调函数内部访问不到主调函数里面的局部变量
}
int main()
{
int a = 10, b = 20;//局部作用域
int ret = add();
return 0;
}
全局作用域: 全局变量在所有的源文件( 同一个工程中 所有.c) , 在任意位置都可以直接使用的区域。
变量的定义,放在所有函数的外面。 就是全局变量,
int a = 10, b = 20;//全局作用域,在整个工程内都可以被访问到
int add()
{
return a + b;
}
int main()
{
int ret = add();
printf("ret is %d\n",ret);
return 0;
}
2.2 变量的生命周期
变量从开辟内存空间开始到变量的内存空间的回收结束的这个时间段,被称为生命周期。
局部变量:
1.函数内部定义的变量
2. 函数的参数
3. 函数内部定义的变量,一定要给初值。局部变量如果没有给初值,就是随机值
在定义开始的地方申请内存。 执行到函数结束,空间回收。
全局变量:
1.在所有函数之外定义的变量。
2. 可以给初值。如果不给初值 ,全局变量由系统负责初始化为0
全局变量,在a.out 正式运行起来前,就要把空间开辟好,在程序结束后,空间释放 。全局变量有全局生命周期。
注意:当全局变量与局部变量同名时,优先使用局部变量,全局变量被隐藏。
三. 存储类型
3.1 auto
auto int a = 10;
auto修饰的局部变量,可省略,等同于: int a = 10;
auto , 自动存储类型 。 只可修饰局部变量。 这个关键字 ,可以省略 。定义变量时,内存空间自动开辟,
离开作用域是自动释放。存储在内存的栈区(stack)。
eg:函数内部定义的变量,函数的参数。
3.2 register
register int b = 10;
register修饰的局部变量,建议编译器将变量存储在CPU的寄存器中。
目的:为了提高访问速度。
3.3 extern
extern , 外部变量。 声明。 导出,目的是为了让其他的源文件,可以使用外部的变量或者函数。

3.4 static
3.4.1 static修饰局部变量
1、static修饰局部变量时,变量的生命周期是整个程序的运行周期,但是变量的作用域不变,依旧在所处的函数(模块)内部。
2、static int i = 0;这条语句只在第一次执行一次,对i分配空间加初始化,以后不会再执行。
3、static修饰的变量是在全局 / 静态数据区(.data/.bss):.data:存放已初始化的全局/静态,
.bss:存放未初始化的全局/静态。
4、未初始化的全局变量和静态变量,全部自动初始化为0。
#include<stdio.h>
int fun()
{
static int i = 0;//局部变量加static,变量的生命周期是整个程序的运行周期
//第一次运行这句话分配空间加初始化,以后不会运行这句话
i++;
return i;
}
int main()
{
int num, j, count;
printf("input:");
scanf("%d",&num);
for(j = 0; j < num; j++)
{
count = fun();
}
// i = 20;虽然i被static修饰,但是没在i的作用域内
printf("count is %d\n",count);
return 0;
}
3.4.2 static修饰全局变量
static 修饰全局变量:表示这个变量只能在本模块(本源文件中)当作全局变量使用。其他的源文
件不可以使用。
static的作用限制作用域。
3.4.3 static修饰函数
static 修饰函数的话。 static 的作用是限制作用域。 避免函数重名
取消了函数的外部链接属性。
四. 程序运行后的内存分布图

1.代码段, 存储的是编写的代码,二进制形式。
2.数据段,全局变量,静态变量,只读数据。没有给初值,系统全部初始化为0 。可读可写
3. 堆区,动态内存区。程序员手动申请和释放空间。最灵活
4.共享区, 库函数的实现。printf函数的定义。
5 .栈区, 局部变量。函数的参数。 返回地址。内存自动申请,自动释放。

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)