一、知识点梳理
1.函数库
- 静态库编译与加载
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。“空间换时间”
/*生成源文件的目标机器文件*/
gcc -c fun.1
gcc -c fun.2
gcc -c fun.3
/*对目标机器文件进行归档*/
ar rcs libfun.a fun1.o fun2.o fun3.o
/*编译可执行程序并加载静态库,执行main程序,看其效果静态库加载到可执行程序中,只需在编译的时候,跟上需要加载的库名即可*/
gcc main.c -o main ./libfun.a
/*执行结果*/
./main.c
- 动态库(共享库)编译与加载
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。 “时间换空间”
/*生成源文件的目标机器文件*/
gcc -c -fpic fun1.c
gcc -c -fpic fun1.c
gcc -c -fpic fun1.c
/*对目标机器文件进行处理,编译出动态库*/
gcc -fpic -shared -o libfun.so fun1.o fun2.o fun3.o
/*将libfun.so拷贝到默认的库目录中*/
cp libfun.so /usr/lib/
/*编译可执行程序并加载静态库,执行main程序,看其效果*/
gcc main.c -o main -lfun
/*执行结果*/
./mian
2.GDB调试
- 启动gdb
gcc -g .c文件
gdb a.out (可执行文件)
- 常用指令
list(简写 l): 查看源程序代码,默认显示10行,按回车键继续看余下的。
run(简写 r) :运行程序直到遇到 结束或者遇到断点等待下一个命令;
break(简写 b) :格式 b 行号,在某行设置断点;
info breakpoints :显示断点信息
Num: 断点编号
Disp:断点执行一次之后是否有效 kep:有效 dis:无效
Enb: 当前断点是否有效 y:有效 n:无效
Address:内存地址
What:位置
continue(简写 c): 继续执行程序,直到下一个断点或者结束;
next(简写 n ):单步执行程序,但是遇到函数时会直接跳过函数,不进入函数;
step(简写 s) :单步执行程序,但是遇到函数会进入函数;
print 表达式:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。
display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。
whatis :查询变量或函数
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息;
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55);
quit:简记为 q ,退出gdb;
3.C语言结构体
- 不要把结构体以按值的方式传入(节省内存,提高效率)
- 求结构体大小的方法:
看操作系统:32 64
对齐字节数: 4 8 有些题目会直接写死,如:# program 2 (对齐字节数为2)
(1)起始位置x%下一元素大小 == 0 || x%对齐字节数 == 0,不满足则补位
(2)结构体大小必须是最大元素大小的整数倍或者对齐字节数的整数倍,否则补位 - 空结构体大小gcc编译器为0,g++编译器为1
- 如果元素中有数组,元素大小,最大元素按数组的元素大小来,而不是按数组长度来。
二、今日心得
今天讲的东西有点杂,老师说比较简单,确实没有之前部分难,但是,有时候还是有些吃力的。还有就是可能心里素质比较差,老师让做题时,同学们嘟嘟嘟发答案自己就开始慌了,一慌,就各种出错,各种bug来了,所以除了学知识,各方面都应该锻炼一下的。而且之前动脑还是不够多,想问题不是那么灵活,学的知识不能灵活运用,还是得加强。