C基础复习纪要
基本概念
-
程序编译、链接过程:
- 编译器 -> 将各个源代码.c文件生成各个.o文件
- 链接器 -> 将各个.o文件进行链接,生成可执行文件;
-
执行:程序载入内存 -> rom:
- 运行时堆栈:保存函数的局部变量和返回地址
- 静态内存:保存程序整个运行过程中的静态(static)变量
-
static关键字:修饰链接属性为external的变量,改变其链接属性为internal;但是对属性不是external的变量无效
-
extern关键字:修饰链接属性为none的变量,使其链接属性为external;但是对已经修饰为static 的变量无效
-
变量存储类型:
- 静态变量:在任何代码块之外声明的变量,不属于堆栈内存,在程序整个运行过程中均存在;
- 自动变量:代码块内部声明的变量(特例:将代码块内部声明的变量声明为static,将转为静态变量);
- 寄存器变量:用register关键字声明的变量,提示用于访问硬件寄存器中的地址,而不是rom,建议不要自行命名register变量,现代编译器会替我们做此类工作,手动分配若超出硬件寄存器大小反而会降低程序执行的效率;
- 函数的形参不能转为静态变量:由于函数的传参在堆栈中进行,用于支持递归;
-
指针:
-
非初始化和非法指针:
/* 未初始化的指针,a的初始值不可预知,将造成段错误或者内存错误 */ int *a; *a = 10;
-
-
ADT和黑盒:抽象数据类型和函数接口 -> 用户只关心接口功能,不用关心具体实现
结构和联合
-
结构的自引用:
/* 非法自引用,_SELF_REF b成员是另一个完整结构,递归下去时编译器将无法知道结构体大小 */ struct _SELF_REF { int a; _SELF_REF b; }; /* 非法自引用,SELF_REF b直到 } 最后才被定义 */ typedef struct { int a; SELF_REF *b; } SELF_REF; /* 合法自引用,_SELF_REF *b成员是另一个完整结构的指针, 大小可被编译器获知 */ struct _SELF_REF { int a; _SELF_REF *b; };
-
联合:不同成员引用相同的***内存中的位置***,联合变量的初始化值,类型需与该联合的第一个成员变量的类型相匹配
动态内存的释放
- 常见内存释放的错误原因:
- 试图解构NULL指针;
- 试图释放非动态内存分配的内存;
- 试图释放动态分配的内存的一部分;
- 试图访问已经被释放的内存;
- 关于传递给其他函数的用于内存释放的形参,为什么需要传递指针的指针,原因是基于第3点,传递指针的指针,再进行解构时,位置将是动态内存分配的起点地址,而直接传递指针进行释放,有可能造成第3点错误,因为指针位置可能已经不位于先前进行动态内存分配的初始地址;
高级指针特性
-
函数指针
-
作用
-
可实现回调函数指针,作为形参传入其他模块调用,相当于copy了一份函数的地址给其他模块进行调用;
// main.c: typedef int (*work_status_change_handle)(status_e status); int work_status_change_handle(status_e status) { ret = ST_SUCCESS; ... ... return ret; } int main(void) { work_handler_regist(work_status_change_handle); } //----------------------------------------------------------------------------------------------------------------------------------------------// // work_handler.c: void work_handler_regist(work_status_change_handle status_change_callback_func) { ... ... return; }
-
可实现转移表,简化swtich语句走不同的函数处理逻辑,用一张转移表即可实现;
/* 不同网络类型的网络的状态查询实现,利用转移表代替繁琐的switch语句 */ network_state_e network_state_get(net_type_e net_type) { st_int32_t ret = NET_CONNECTED; network_state_e (*state_func_list[])(void) = { [NET_E1] lan_e1_state_get, [NET_LTE] lte_state_get, [NET_ETH] lan_eth_state_get, [NET_PON] lan_pon_state_get }; ret = state_func_list[net_type]; return ret; }
-
-