一、函数嵌套?
1、 什么是函数嵌套?
函数嵌套就是调用某个函数内部再调用另外一个函数。
2、 有函数嵌套程序在内存有什么特点?
如果嵌套的函数很多,就会在栈区累积非常多空间没有被释放。
3、 函数嵌套与递归函数有什么区别?
函数嵌套:自己调用别人的函数。
例子:
void fun()
{
my_fun();
}
递归函数:自己调用自己的函数。
例子:
void fun()
{
fun();
}
二、递归函数?
1、 特点?
递归函数特点自身调用自身,无限递归,没有终止的时刻。
例子:
void fun()
{
int a;
-> 导致栈空间溢出!
return;
}
int main()
{
fun();
return 0;
}
结论: 为了防止栈空间溢出,所以递归函数一般都会携带终止条件,也就是说到达某个条件时,函数返回!
2、题型1: 给程序,求结果。
例题,求出下面程序的结果?
void fun(int n)
{
if(n > 1)
{
fun(n-1);
}
printf("n = %d\n",n);
return;
}
int main()
{
fun(100);
return 0;
}
答案:1~100
思路: 找出终止条件,列出几项,找规律,再画图分析!
3、 题型2: 给规则,写程序。
例题:写出下列程序。
有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生多少岁,他说比第3个学生大2岁。问第3个学生多少岁,他说比第2个学生大2岁。问第2个学生多少岁,他说比第1个学生大2岁。最后问第1个学生多少岁,他说他是10岁,请问第5个同学多少岁?使用递归函数来完成。
#include <stdio.h>
int get_child_age(int n)
{
int age;
if(n <= 0) // -> 搞事情
return -1;
if(n == 1) // -> 终止条件
age = 10;
if(n > 1) // -> 正常
age = get_child_age(n-1) + 2;
return age;
}
int main(int argc,char *argv[])
{
int ret;
ret = get_child_age(5);
printf("ret = %d\n",ret);
return 0;
}
思路: 写框架,分析情况 -> 最终目标与终止条件之间的关系。
1: 画出以上例子的内存图。
2: 有以下程序,求出结果?
int fun(int n) 10 9
{
if(n==1) return 1;
else return (n+fun(n-1)); 10+9+8+7+6+5+4+3+2+1
}
int main()
{
int x;
10。
x = fun(x); 10
printf("%d\n",x); //55
}
3:第1天存100块,后面每一天都比昨天多存10块,第312天存了多少?
#include <stdio.h>
int get_money(int n)
{
int money;
if(n <= 0)
return -1;
if(n == 1)
money = 100;
if(n > 1)
money = 10 + get_money(n-1);
return money;
}
int main()
{
int ret;
ret = get_money(10);
printf("ret = %d\n",ret);
return 0;
}
4: 使用循环方式完成练习3,画内存图分析两种方式差别。
循环 -> 多次使用一个变量
递归 --> 容易造成栈空间溢出!
三、回调函数
1、 什么是回调函数?
先定义好函数A(喝水),再将这个函数A作为另外一个函数B(爬山)的参数,在函数B(爬山)可以回过头调用这个参数(喝水),这个函数A就称之为回调函数。
2、 基本框架?
void funB(funA)
{
B中调用函数A
}
void funA() -> 回调函数
{
}
int main()
{
funB(funA);
}
例题: 从键盘中获取两个数值,求出两个值的和,要求使用回调函数完成。
int get_result(int a,int b,int(*p)(int,int)) -> 就把这个p当成函数名字
{
int ret;
ret = p(a,b);
return ret;
}
int add_fun(int x,int y)
{
int z;
z = x + y;
return z;
}
int main()
{
int a,b,ret;
scanf("%d %d",&a,&b);
ret = get_result(a,b,add_fun); -> 函数名字作为参数,其实是传递了函数的地址过来。
printf("ret = %d\n",ret);
}
补充:
函数指针参数怎么写?
1)先写一个 *
2)在*后面写一个变量名,使用圆括号括住 (*p)
3)确定函数是哪个? int add_fun(int x,int y)
4)把第3步函数名与形参的变量名都去掉 int (int,int)
5)把第2步结果写在第4步结果的返回值类型与形式参数列表之间 int(*p)(int,int
3、 回调函数使用场景?
在数据库、系统编程信号通信中常常看到回调函数。
4: 连续从键盘中获取4个数字,求出其中的最大值,要求回调函数来完成。
int max4(int a,int b,int c,int d,int(*p)(int,int))
{
int m;
m = p(a,b);
m = p(m,c);
m = p(m,d);
return m;
}
int max2(int x,int y)
{
int z;
z = (x > y ? x : y);
return z;
}
int main()
{
int a,b,c,d,ret;
ret = max4(a,b,c,d,max2);
return 0;
}
四、变参函数
1、 什么是变参函数?
变参函数是指该函数的参数不固定,例如:printf()函数。
1
2
3
"1+x"
2、如何判断一个函数是不是变参函数?
#include <stdio.h>
int printf(const char *format, ...);
const char *format: 输出字符串格式
... : 参数不定
3、 类似的变参函数有很多: printf() scanf() ioctl() fcntl()
五、内联函数?
1、 什么是内联函数?
在程序中调用函数时,需要花费一定的时间进行保护现场与恢复现场,但是使用了内联函数,就既可以使用函数,又不需要花费时间来进行保护现场与恢复现场。
封装:test.c
#include <stdio.h>
void fun()
{
printf("hello!\n");
}
int main()
{
fun();
fun();
fun();
return 0;
}
不封装:test.c
#include <stdio.h>
int main()
{
printf("hello!\n");
printf("hello!\n");
printf("hello!\n");
return 0;
}
2、 如何实现内联函数?
test.c
int main()
{
fun();
fun();
fun();
return 0;
}
head.h
#include <stdio.h>
inline void fun()
{
printf("hello!\n");
}
3、如何解决保护恢复现场问题?
1)使用内联函数 -> inline
2)不要过多封装成函数,当某些表达式组成一个功能时,才封装为一个函数。
4、在嵌入式中哪里看到内联函数?
在内核链表时看到内联函数。
六、数组的概念?
1、 什么是数组?数组与普通变量有什么关系?
数组其实是集合来的,它是由多个相同类型的普通变量组合而成。当用户需要同时定义多个相同变量时,就可以使用数组。
2、 定义数组时,需要交代什么东西?
1)数组元素的个数?
2)数组中每一个元素的数据类型? -> char short int long float double
定义公式:
数据类型 数组名字[元素的个数]
例子:定义一个具有100个int类型变量的数组
int A[100];
3、从内存空间分析数组特点:
int main()
{
4个字节,使用变量a间接访问这片空间。
400个字节,使用变量A间接访问这片空间。
printf("sizeof(a) = %d\n",sizeof(a));//4
printf("sizeof(a) = %d\n",sizeof(A));//400
return 0;
}
4、定义了数组,编译器如何处理数组?
例如: int A[100]
其实分开两个部分进行处理, "A[100]"作为第一部分。
第一部分 -> 决定内存空间中元素的个数。
第二部分 -> 决定每一个元素的数据类型
七、数组的赋值
1、 定义同时初始化
[元素的个数] = {初始化列表,每一个成员的值需要使用","分开}。
int A[3] = {100,200,300}; //编译通过
int A[3] = {100,200}; //编译通过
#include <stdio.h>
int main()
{
int A[3] = {100,200};
printf("A[0] = %d\n",A[0]); //100
printf("A[1] = %d\n",A[1]); //200
printf("A[2] = %d\n",A[2]); //0
return 0;
}
0。
warning: excess elements in array initializer
warning: (near initialization for ‘A’)
编译警告warning: 在内存空间中,可能有问题,但是还是可以生成可执行文件。
编译出错error: C语言语法有误,不能生成可执行文件。