一.编译
写在前面
编译这整个过程都只是在编译你自己写的代码,直到链接才让你的代码和库的代码关联起来,最终形成可执行程序
源程序到可执行程序的整个过程: ESc-iso
1.预处理
预处理四大任务:
头文件展开
,去注释
,宏替换
,条件编译
gcc test.c -E -o test.i
-E:开始翻译,并且在预处理后停下来
-o:指明形成临时文件的名称
通过这里我们可以看到预处理后还是C语言代码,预处理完成的只是文本操作!
ps:这里不带-o是不行的,程序停下来后会将预处理后的文件内容直接打印到终端
通过-o生成的.i文件我们可以清晰的看到头文件展开后的结果是一堆函数和变量的声明,并没有函数的具体实现!
.h(头文件)中只包含函数的声明,函数的具体实现在标准库里
头文件存在的最大意义:
1.提供函数的声明
2.自动补全代码
2.编译
编译是将C语言代码翻译成汇编代码
gcc -S test.c -o test.s
3.汇编
汇编是将汇编代码翻译成二进制代码
gcc -c test.c -o test.o
汇编完成后得到二进制代码,但是这并不能被执行,因为编译这整个过程都只是在编译你自己写的代码,直到链接才让你的代码和库的代码关联起来,最终形成可执行程序.
二.(动静态)链接
链接的目的:把自己写的并且编译好的二进制代码和库里的二进制代码关联起来,形成可执行程序!
1.动态链接
动态链接方式:在运行时需要去标准库里找函数的实现
优点:形成的可执行程序体积小
缺点:依赖动态库,易收到动态库丢失等原因出现运行时错误!
gcc test.c -o test//Linux-默认是动态链接的链接方式 file 可执行程序 ldd 可执行程序 //在linux中, ldd是list dynamic dependencies的缩写, 意思: 列出动态库依赖关系
dynamically linked (uses shared libs)//动态链接方式(共享库) libc.so.6 => /lib64/libc.so.6 (0x00007f86cd306000)//动态库->位置(代码地址)
2.静态链接
静态链接方式:在链接时直接将函数的实现拷贝一份到我的程序中,运行时不用找!
优点:不依赖第三方库
缺点:形成的可执行程序体积大
gcc test.c -o test -static//指明采用静态链接的链接方式 file test
statically linked//静态链接方式
3.静态链接库的下载安装
动态库一般系统自带,因为系统运行时需要用到动态库
静态库在Linux中一般要自行安装
sudo yum install glibc-static//安装C静态库 sudo yum install libstdc++-static//安装c++静态库 gcc test.c -o test -static//生成静态程序test
4.windows下动静态库的后缀
windows下动静态库的后缀: 动态库:.dll 静态库:.lib