原标题:条件编译,头文件,静态库,共享库与多文件编程

本文转载自嵌入式Linux中文站条件编译

条件编译即满足某些条件的时候编译某部分代码,常用于开发多个版本的程序,当满足条件A时,编译出免费版本的软件,当满足条件B时,编译除vip版本的软件,可以提高代码的复用率。条件编译使用"预处理命令+宏定义"来实现,更多宏命令参见

$vi tutu.c

#ifdefVIP //也可以写成

#if defined (VIP)//把免费版改造成VIP版的代码

#elifdefined PRO//把免费版改造成PRO版代码

#endif//免费版本的代码

$gcc -DVIP tutu.c//将编译出VIP版的软件头文件header头文件的编写

C语言的标识符在使用之前一定要声明,把所有的标识符的声明都放在一个头文件中,在预处理阶段把这些声明一股脑的复制到源文件的开头,这样任何标识符在使用之前不就都被声明过了。但这个方案引起了一个问题,就是如果我调用了fcn.c的函数,包括了它的头文件fcn.h,我的同事也这么做,那么编译的文件中不就有了两份fcn.h,而一个项目数百的文件,每个文件都有自己的头文件,还会有相互调用的问题,这样编译器的压力就会很大,所以就有了"头文件卫士":

#ifndef__FCN_H

#define__FCN_H//fcn.c里标识符声明

#endif//__FCN_N

这三句话就保证了这个头文件在整个程序中只有一份,因为一旦第一次使用这个头文件的时候,__FCN_H还没有被定义,那么他就会被定义,里面的声明代码也会被使用,如果再由文件使用这个头文件,那么由于__FCN_H已经被定义了,条件编译的条件不满足,所以里面的声明代码也就不会再被使用,反正声明有一份就够了。

头文件的使用

头文件需要使用#include宏命令把头文件原封不动的复制到当前文件夹

#include //在默认头文件路径里查找头文件,如果找不到就报错

#include"头文件路径"//按照指定的路径查找头文件,找不到就到默认头文件路径查找,还是找不到就报错静态库

静态库:由若干个.o目标文件打包生成的.a文件叫静态库文件, 链接静态库就是将被调用的代码指令到调用模块中,并体现在最终的可执行文件中 ,静态库只能静态链接,

优势

不需跳转,执行效率较共享库高一些

使用静态库的代码在运行时不需要依赖静态库

劣势

静态库占用空间比较大,多次链接(多次复制)之后最终生成的可执行文件比较大

修改维护不方便,库文件改一点,链接它的文件就得从头复制一遍

生成静态库

编写.c文件 $vi add.c

生成.o文件 $cc -c add.c

生成静态库文件 $ar –r libadd.a add.o

链接静态库文件 $cc -o main main.o -static -ladd -L.

Note:

对于临时使用不在公用库目录的库,链接前可以把库的路径添加到LIBRARY_PATH,$export LIBRARY_PATH=$LIBRARY_PATH:`pwd`

或者使用直接链接$cc main.o ./libadd.a

或者使用编译选项链接$cc main.o -ladd –L.

和动态库不同,静态库不存在运行时找不到的问题,编译时就把所有库问题解决了。

add是库名,libadd不是,是文件名

共享库

共享库就是由若干个目标文件打包生成的xxx.so文件 ,链接共享库不是将被调用代码指令复制到调用模块中,而是将被调用代码指令在共享库中的相对地址复制到调用模块中, 体现在最终的可执行文件中,不论静态链接还是动态链接(共享库可以静态链接也可以动态链接)。 Linux下进行链接的缺省操作是先考虑动态链接库,即如果同时存在静态和共享库,不特别指定的话,将与共享库相连接

优势

共享库占用空间比较小, 生成的可执行文件比较小, 即使修改了库中的代码, 只要相对地址/接口保持不变, 则不需要重新链接.

劣势

使用共享库的代码在运行时需要依赖共享库, 并且执行效率较静态库低。

生成共享库

编写.c文件 $vi add.c

生成.o文件 $cc -c -fpic add.c

生成共享库文件 $cc -shared -o libadd.so add.o

链接共享库 $cc -o main main.o -ladd -L.

Q:如果本文件夹有了libdl.a或者libdl.so会链接本文件夹的还是系统默认的???

A:如果使用$gcc main.o -L. -ldl当然会链接本文件夹的, 你当-L.是空气啊

Note:

-fpic是生成位置无关码的选项, 即生成相对地址

$ldd a.out#查看a.out所依赖的共享库信息

对于临时使用的不在公用库目录的共享库,链接后可以把库的路径添加到LD_LIBRARY_PATH:$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`

如要永久更改动态库的搜索目录,可以创建文件/etc/ld.so.conf.d/my.config并将路径写入其中,再使用$ldconfig /etc/ld.so.conf.d/my.config配置链接选项

与静态库不同,修改环境变量和配置文件都是用来解决运行时找不到库的问题,并不针对编译时链接的问题,编译时还是要使用-L.

静态链接

静态链接,即编译时链接,使用-static可以强制链接静态库

Q:静态链接时调用函数需要包含相应库的头文件吗?

A:需要. 链接我们熟知的#include...对应的libc.so时就是使用的静态链接, 默认都是静态链接共享库,也可以使用$gcc –static强制链接静态库libc.a,任何一个库都有两个版本:.a版本和.so版本

静态链接:

编写.c文件 $vi main.c

生成.o文件 $cc -c main.c

链接库文件 $cc main.o –ladd

Note:

开发时,使用静态链接,以便gcc能够找到编译时需要的共享库。

发布时,使用动态链接,以便程序加载运行时能够自动找到需要的共享库。

动态链接

动态链接:运行时链接,建立在静态链接libdl.so(a)库的基础上, 程序在运行过程中动态地链接共享库,所以需要在源代码中写链接代码,编译器是无能为力了,只能帮到dl库了

Q:动态链接时调用函数需要包含相应库的头文件吗?

A:动态链接libadd.so是建立在静态链接 libdl.so的基础上的, 既然后者是静态链接, 当然还需要包含相应的,但libadd.so里的函数在调用时就不需要相应的头文件了

Q:-ldl是不是因为使用的???

A:是,man dlopen,这个库包含实现动态链接的代码

ATENTION:动态链接和静态链接不是并列关系,是依存关系, 没有静态链接的libdl.so(a), 动态链接就是个屁

Q: 为什么共享库要有执行权限, 静态库不需要

A:因为共享库在运行时使用,静态库在编译时里面的代码已经链接到程序里了,运行时和静态库就没关系了

动态连续需要静态链接dl.so库:

编写.c文件 $vi main.c

生成.o文件 $cc -c main.c

链接库文件 $cc main.o –ldl

动态链接的源文件

#include

#include

#include

int main(){

void *handle=dlopen("../libfcn.so",RTLD_NOW);

if(NULL==handle)

printf("%s",dlerror()), exit(-1); int (*pAdd)(int,int)=(int (*)(int,int))dlsym(handle, "add");

if(NULL==pAdd) printf("%s",dlerror()),exit(-1); printf("%dn",pAdd(1,2)); int res=dlclose(handle);

if(0!=res)

printf("%s",dlerror()),exit(-1); return 0;}

Note:

-l是静态链接库名选项, dl是共享库名(libdl.so), 用来实现我们程序中的动态加载卸载libadd.so返回搜狐,查看更多

责任编辑:

linux 头文件卫士,条件编译,头文件,静态库,共享库与多文件编程相关推荐

  1. Linux中静态库和动态库(共享库)的区别

    1. 静态库和动态库的制作过程区别 1.1 静态库的制作过程 详见博客:Linux中静态库的制作与使用 1.2 动态库的制作过程 详见博客:Linux中动态库(共享库)的制作与使用 2. 静态库和动态 ...

  2. Linux中动态库(共享库)的制作与使用

    0. 库的基本概念 见博客:Linux中静态库的制作与使用 0.1 动态库的工作原理 首先回忆一下静态库,使用静态库,在GCC进行链接时,会把静态库中代码打包到可执行程序中. 但是使用动态库,在GCC ...

  3. LINUX之静态库共享库

    linux下文件的类型是不依赖于其后缀名的,但一般来讲: .o,是目标文件,相当于windows中的.obj文件 .so 为共享库,是shared object,用于动态连接的,和dll差不多 .a为 ...

  4. matlab运行mex文件出错“mtimesx.mexw64无效: 缺少依赖共享库VCOMP100.DLL”

    最近重新安装系统后运行目标跟踪代码,意外发现出错,显示如下: 百度看了一下,VCOMP100.DLL好像是window安装缺少的共享库,和matlab没关系,所以就尝试解决,主要有两种方法: 方法一: ...

  5. 静态库与动态库(共享库)的联系与区别

    提要: 1.静态库                 静态库,也称作归档库(archive),按惯例它们的文件名都以.a结尾.比如,标准C语言函数库/usr/lib/libc.a和X11函数库/usr/ ...

  6. Linux 下编译安装软件,找不到共享库 xx.so 的解决办法

    编译memcached时,报错没有libevent,于是下载libevent,configure , make && make install ,然后在重新安装memcache成功之后 ...

  7. linux 如何查看一个进程空间所装载的共享库

    linux中每个进程空间都为共享库划分了专门区域,如下所图 查看一个进程所有已被映射的区域可以使用/proc/PID/maps看到 例如

  8. linux运行库,Linux C 静态库 共享库 运行库

    1 静态库 main.c #include #include #include "add.h" int main(int argc, char **argv) { int a = ...

  9. linux编译静态库的头文件,条件编译,头文件,静态库,共享库与多文件编程

    条件编译 条件编译即满足某些条件的时候编译某部分代码,常用于开发多个版本的程序,当满足条件A时,编译出免费版本的软件,当满足条件B时,编译除vip版本的软件,可以提高代码的复用率.条件编译使用&quo ...

最新文章

  1. 发现一款3D 打印的pcDuino外壳
  2. 怎么改掉科学计数法_马拉松猝死频发为哪般——听听冠军们怎么说
  3. ML之kNN(两种):基于两种kNN(平均回归、加权回归)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能
  4. QML WebEngineView简单用法和常用接口
  5. ALVのイベントを取得する方法
  6. Java反射-继承关系
  7. P4178 Tree
  8. arduino无源蜂鸣器歌曲编码_Arduino加无源蜂鸣器,播放音乐《葫芦娃》
  9. 27岁到来之际,我在大厂实现了年薪40W+的小目标
  10. JAVA Swing GUI设计 WindowBuilder Pro Container使用大全7——JDesktopPane使用
  11. CCF201409-3 字符串匹配(解法二)(100分)(废除!!!)
  12. 计算机科学与技术和软件工程区别
  13. 《麻辣江湖》即将上线!
  14. Linux文件与管理(还是多记)
  15. Android中免Root实现Hook的Dexposed框架实现原理解析以及如何实现应用的热修复
  16. abp The value could not be converted to a GUID:
  17. 五年级春期计算机教案,五年级下册信息技术教案
  18. 基于VUE+H5PLUS 实现app交互蓝牙打印机得功能
  19. 硬盘数据丢失怎么恢复?分享固态硬盘恢复数据的4个方法
  20. 我的世界Mods/制作(1)

热门文章

  1. android ppt素材,史上最全的PPT素材大合集,670页全动画演示!
  2. 兰卡斯特大学计算机专业世界排名,2019上海软科世界一流学科排名计算机科学与工程专业排名兰卡斯特大学排名第101-150...
  3. 七牛CDN云存储优惠码充值 adbcf415 长期有效
  4. 局域网联机一起过关的游戏
  5. 专转本计算机题型英语,2006江苏专转本计算机 2006-2011江苏专转本英语真题及答案.doc...
  6. CSS设置盒子容器(div)高度(height)始终为100%
  7. 用python检查班上同学交作业的情况
  8. 【错误提示】未定义标志符的几种情况
  9. 同态加密Paillier
  10. HTTP 缓存详细说明