实参和形参位于不同的内存区域,彼此独立
形参变量只有在函数被调用的时候,才会分配内存,在函数调用结束的时候,形参就会自动释放,所有的形参在函数体内有效的,不能在函数体外使用
实参可以是变量、常量、表达式、函数调用,但是,如果是函数调用,要求在函数调用结束的时候,要有确定的值,以便于将这些值传递给函数做形参初始化, 实现给形参赋值。
int max(int x, int y) //函数定义, x,y叫做形参
{
return (x>y)?x:y;
}
int main(void)
{
int x, y;
scanf("%d%d", &x, &y);
int m = max(x, y); //调用函数,x,y叫做实参
// int m = max(3,8);
// int m = max(2, 4+8);
// int m = max(x,func());//func函数要有确定的值
printf("m = %d\n", m);
return 0;
}
实参和形参在数量上,类型上,顺序上必须要保持一致
函数调用的时候,数据传输是单向的,不可逆
函数调用的时候,多个形参在做初始化的时候,是按照从右往左的顺序初始化
函数调用的内存逻辑 函数调用时,进程的上下文会切换到被调函数,当被调函数执行完之后,在切换回去
int main(void)
{
int x, y;
scanf("%d%d", &x, &y);
int m = max(x, y); //调用函数,x,y叫做实参
printf("m = %d\n", m);
return 0;
}
int max(int x, int y)//函数定义, x,y叫做形参
{
return (x>y)?x:y;
}
局部变量与栈内存
局部变量:定义在函数体内的变量(函数的形参也属于局部变量),就叫做局部变量
全局变量:定义在函数体外部的变量,全局变量在程序退出之前都是有效的。
局部概念:只要是通过大括号括起来的变量,也称为局部变量
{
int b = 2;
}
printf("b = %d\n", b);
这里不能打印b的值,b是属于上一个大括号里面的局部变量,出了这个大括号之后,b就被释放掉,变成无效的
局部变量的特点:
某一函数内部的局部变量,存储在该函数的特定的栈内存中
局部变量只能在该函数内可见,在该函数外部不可见
当该函数退出后,局部变量所占的内存立即被系统回收,因此局部变量也被称为临时变量
函数的形参虽然不被花括号包含,但依然属于该函数的局部变量
栈内存的特点: 每当一个函数被调用时,系统将自动分配一段栈内存给该函数,用于存放其局部变量
每当一个函数退出时,系统将自动回收其栈内存
系统为函数分配栈内存的时候,是遵循从上(高地址)往下(低地址)的分配原则
技术要点: 栈内存相对而言比较小的,不适合用来分配尺寸太大的变量
return之后不可再访问函数的局部变量,因此返回一个局部变量的地址通常是错误的
static关键字和静态函数 静态变量: 用static关键字修饰的变量就叫做静态变量,比如 static int a;
static关键字修饰局部变量,这个变量从定义位置开始被分配到数据段里面,直接程序退出才会释放空间,并且这个变量只会初始化一次。
static关键字修饰全局变量,这个全局变量只在当前文件有效
static int m; //让全局变量只在当前文件有效
int m; //让全局变量被其他文件做外部声明
void func(void)
{
static int a = 0; //a只会被初始化一次,程序退出a才会被释放
printf("a = %d\n", a++);
return ;
}
int main(int argc, char const *argv[])
{
func();//a = 0
func();//a = 1
func();//a = 2
return 0;
}
静态函数:
背景知识:普通函数都是跨文件使用的,即在a.c里面写的函数可以在b.c里面使用
静态函数:用static修饰的函数,只能在定义的文件内可见的函数,称为静态函数
static void d_func(void)
{
printf("这是个外部函数\n");
}
要点:
静态函数主要是为了缩小函数的可见范围,减少与其他文件中重名函数冲突的概率
静态函数一般定义在头文件中,然后被各个源文件包含
使用递归的条件 子问题的逻辑与原问题一样,并且更为简单
不能无限制重复调用本身,必须有一个出口,化简为非递归状态出来
设计一个递归算法 确定问题变量
确定递归公式(化简过程,比如n-1)
确定边界条件
注意:递归是一个函数嵌套调用的过程,递归次数越多,运行时间会大幅度增加,内存空间也会大量占用,所以,一般能用循环解决的,我们就不考虑递归 缺点:效率低,还比较占内存 递归算法的一般应用 数据的结构形式按照递归定义的(比如:二叉树)
执行过程按照递归定义的(比如:函数的嵌套调用)
问题的解决办法按照递归算法实现(比如:年龄问题,汉诺塔)
递归调用时,函数的栈内存会随着层层深入,栈空间就往下增长,如果递归的层次太深,很容易将栈内存耗光。
层层递进时,问题的规模会随之减小,减小到可直接退出的条件时,函数开始层层回归
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)