第三十一节 指针参数和数组参数的分析
1、C语言会以值拷贝的方式传递参数;
2、当向函数传递数组时,将数组名看做常量指针传递数组首元素的地址;
注:C语言以高效作为最初设计目标
① 参数传递的时候如果拷贝整个数组执行效率会大大下降;
② 参数位于栈上,太大的数组拷贝会导致栈溢出;
3、二维数组参数中第一维长度可以省略;
4、参数退化的关系:
① float a[5] --> float *a
② float a[5] -->float **a
③ int a[4][5] --> int ()[5]
5、C语言中的数组参数必然退化为指针;
第三十二节 函数与指针分析
1、函数指针用于指向一个函数;
2、函数名就是函数的入口地址;
3、可以通过函数类型定义函数指针:functype *pointer,也可以直接定义 type (*func)(parameter list);
注: pointer为函数指针变量名,type为所指函数的返回值类型,parameterlist为所指函数的参数类型列表
4、如何使用C语言跳转到某个固定地址开始执行?
分析:
通过函数指针可以在C程序中实现固定地址跳转,函数指针是实现回调机制的关键技术,回调机制中的调用者和被调用函数互不依赖。
5、回调函数原理:
① 调用者不知道具体事件发生时所调用的具体函数;
② 被调用函数不知道何时被调用,只知道需要完成的任务;
③ 当具体事件发生时,调用者通过函数指针调用具体函数;
第三十三节 指针的阅读技巧
1、左右法则
① 从最里层的圆括号中未定义的标识符看起;
② 首先往右看,再往左看;
③ 通过圆括号或方括号时可以确定部分类型,并调转方向;
④ 重复2,3步骤,直到阅读结束;
2、可通过typedef简化复杂指针的定义;
第三十四节 动态内存分配
1、malloc和free是库函数而不是系统调用,但是实现是需要操作系统支持的;
2、malloc实际分配的内存可能会比请求的多,malloc(0)合法,返回一个地址,并且需要释放;
3、当请求的动态内存无法满足时,malloc返回NULL;
4、当free的参数为NULL时,函数直接返回;
5、malloc只负责申请空间,不负责初始化;
6、realloc会重置内存大小,但是新申请的部分内存中的值为随机值;
7、calloc不仅会申请内存还会将这一片内存初始化为0,且calloc是以类型大小申请内存;
第三十五节 程序中的三国分析
1、栈(先进后出)
① 栈在程序中用于维护函数调用上下文;
② 函数中的参数和局部变量存储在栈上;
③ 栈保存了一个函数调用所需的维护信息(返回地址、参数、局部变量、调用上下文、临时变量等);
④ 每次函数调用都对应着一个栈上的活动记录(ebp、esp指针)
i. 调用函数的活动记录位于栈的中部;
ii.被调用函数的活动记录位于栈的顶部;
2、堆
① 堆是程序中一块预留的内存空间,可由程序自由使用;
② 堆中被程序申请使用的内存在被主动释放前一直有效;
3、静态存储区
① 在程序的编译期静态存储区的大小就被确定了,随着程序的运行而分配空间;
② 静态存储区主要用于保存全局变量和静态局部变量;
③ 静态存储区的信息最终会保存到可执行程序中;
第三十六节 程序的内存布局
1、程序是静态的概念,表现形式为一个可执行文件;
2、进程是动态的概念,程序由操作系统加载运行后得到进程;
3、每个程序可以对应多个进程,一个进程只能对应一个程序;
注:
运行脚本文件–>操作系统加载–>脚本解释程序–>进程–>读取并解释执行脚本
运行可执行程序–>操作系统加载–>进程
4、各个段的作用
一个堆栈段在程序运行后才正式存在,是程序运行的基础。
① 静态存储区通常指程序中的.bss和.data段;
② 只读存储区通常指程序中的.rodata段;
③ 局部变量所占空间为栈上的空间;
④ 动态空间为堆中的空间;
⑤ 程序可执行代码存放于.text段