| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> 预处理、动态库、静态库(基于linux内核的ubuntu操作系统) -> 正文阅读 |
|
[系统运维]预处理、动态库、静态库(基于linux内核的ubuntu操作系统) |
一、c语言编译过程1:预编译 ???将.c中的头文件展开、宏展开 2:编译 ???将预处理之后的.i文件生成.s汇编文件 3:汇编 ???将.s汇编文件生成.o目标文件 4:链接 ???将.o链接成可执行文件 Linux下GCC编译过程 gcc -E hello.c -o hello.i ??(1.预处理-->语法有错,不报错) gcc -S hello.i -o hello.s ??(2.编译) gcc -c hello.s -o hello.o ??(3.汇编) gcc hello.o -o hello ?????(4.链接) 二、include#include<>//用尖括号包含头文件,在系统指定的路径下找头文件 #include””//用双引号包含头文件,先在当前目录下找头文件,找不到,再到系统指定的路径下找 注意事项1:include经常用来包含头文件,可以包含.c文件,但是不要包含.c,因为include包含的文件会在预编译时展开,如果一个.c被包含多次,展开多次,会导致函数重复定义。 即不要包含.c ???注意事项2:预处理只是对include等预处理操作进行处理并不会进行语法检查 这个阶段有错也不会报错,第二个阶段即编译阶段才会进行语法检查 三、define定义宏用define去定义 宏是在预编译的时候进行替换 ? ? ? ? 1.不带参的宏 ????????#define PI 3.14 ????????在预编译的时候如果代码中出现了PI就用3.14去替换。 ????????宏的好处:只要修改宏定义,其他地方在预编译的时候就会重新替换 注意:宏定义后面没有分号 宏定义的作用范围:从定义的地方到本文件末尾 如果想在中间终止宏的定义范围 #undef PI //终止PI的作用 ????????2.带参宏 ????????#define S(a,b) a*b ????????注意带参宏的形参a和b没有类型名,S(5,6)将来在预处理的时候替换成实参替代字符串的形参,其他字符保留,5*6 例1: 例2:? ?例3:(解决例2出现的问题) ? ? ? ? ?3.带参宏和带参函数的区别 ????????带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用过程,不需要压栈出栈。所以带参宏,是浪费了空间,因为被展开多次,节省时间 ????????带参函数,代码只有一份,存在代码段,调用的时候去代码段去指令,调用的时候压栈出栈,有个调用过程,所以它是浪费了时间,节省了空间 ????????带参函数是有类型的,带参宏是没有类型名 四、选择性编译
??????????代码段1 #else ??????代码段2 #endif 如果在当前.c文件中ifdef代码段的上面有定义AAA,就编译代码段1,否则编译代码段2 注意和if else语句的区别,if else语句都会被编译,通过条件选择性执行代码而选择性编译,只有一块代码被编译 例子1: ? ??????例子2: ????????2.(注意) ????????#ifndef AAA ???????????????????--->if no define ????????????代码段1 ????????#else ????????????代码段2 ????????#endif ????????????????和第一种互补 ????????????????这种方法,经常用在防止头文件重复包含 例1: ? ????????3.#if 表达式 ????????程序段1 ????????#else ????????程序段2 ????????#endif ????????如果表达式为真,编译第一段代码,否则编译第二段代码 ????????选择性编译都是在预编译阶段干的事情 ????????例1: ? 五、静态库? ? ? ? 1.动态编译 ?????动态编译使用的是动态库文件进行编译 ?????gcc hello.c -o hello ?????默认是使用的动态编译方法 ? ? ? ? 2.静态编译 ?????静态编译使用的静态库文件进行编译 ??????gcc ?-static hello.c -o hello ? ? ? ? 3.静态编译与动态编译的区别 ? ? ? ? 1)使用的库文件的格式不一样 ????????????????动态编译使用动态库,静态编译使用静态库 ????????????????注意:静态编译要把静态库文件打包编译到可执行文件中 ????????????????动态编译不会把动态库文件打包编译到可执行程序中,它只是编译链接关系 制作静态库: gcc -c mylib.c -o mylib.o ar rc libtestlib.a mylib.o 注意:静态库起名的时候必须以lib开头,以.a结尾 编译程序: 方法(1) gcc -static mytest.c libtestlib.a -o mytest 方法(2) ?????可以指定头文件及库文件的路径 ?????比如把libtestlib.a ?mylib.h ?移到/home/edu ?????mv libtestlib.a ?mylib.h ?/home/edu ??? ????编译命令: ????gcc -static ?mytest.c -o mytest ?-L/home/edu -ltestlib -I/home/edu 注意:-L是指定库文件的路径 ??????-l(小写的L)指定找哪个库,指定的只要库文件名lib后面和.a前面 ??????-I (大写的i)指定头文件的路径 ??方法(3) ???????可以将库文件及头文件存放到系统指定的路径下 ????????库文件默认的路径是/lib 或者是/usr/lib ????????头文件默认路径/usr/include ????????mv libtestlib.a /usr/lib ????????mv mylib.h /usr/include 编译命令: ???gcc -static mytest.c -o mytest -ltestlib 六、动态库制作动态链接库 gcc -shared mylib.c -o libtestlib.so//使用gcc编译、制作动态链接库 动态库链接的使用 方法1:库函数、头文件均在当前目录下 ????????gcc mytest.c libtestlib.so -o mytest ? 找不到动态库文件修改环境变量 ???? export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH 方法2:库函数与头文件假设都在/home/edu目录 ???????gcc mytest.c -o mytest -L/home/edu -ltestlib -I/home/edu ???????编译通过,运行时出错,编译时找到了库函数,但是链接时找不到库,执行以下操作,修改环境变量: ???????export LD_LIBRARY_PATH=/home/edu:$LD_LIBRARY_PATH 方法3:库函数、头文件均在系统路径下 ???????cp libtestlib.so /usr/lib ???????cp mylib.h /usr/include ???????gcc mytest.c -o mytest -ltestlib ???????./mytest |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 9:42:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |