Linux下C编程基础之:gcc编译器
我们通常需要将一些常用的公共函数编译并集成到二进制文件(Linux的ELF格式文件),以便其他程序可重复地使用该文件中的函数,此时将这种文件叫做函数库,使用函数库不仅能够节省很多内存和存储器的空间资源,而且更重要的是大大降低开发难度和开销,提高开发效率并增强程序的结构性。实际上,在Linux中的每个程序都会链接到一个或者多个库。比如使用C函数的程序会链接到C运行时库,Qt应用程序会链接到Qt支持的相关图形库等。
函数库有静态库和动态库两种,静态库是一系列的目标文件(.o文件)的归档文件(文件名格式为libname.a),如果在编译某个程序时链接静态库,则链接器将会搜索静态库,从中提取出它所需要的目标文件并直接复制到该程序的可执行二进制文件(ELF格式文件)之中;动态库(文件名格式为libname.so[.主版本号.次版本号.发行号])在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入。
下面举一个简单的例子,讲解如何怎么创建和使用这两种函数库。
首先创建unsgn_pow.c文件,它包含unsgn_pow()函数的定义,具体代码如下所示。
/* unsgn_pow.c:库程序 */
unsigned long long unsgn_pow(unsigned int x, unsigned int y)
{
unsigned long long res = 1;
if (y == 0)
{
res = 1;
}
else if (y == 1)
{
res = x;
}
else
{
res = x * unsgn_pow(x, y - 1);
}
return res;
}
然后创建pow_test.c文件,它会调用unsgn_pow()函数。
/* pow_test.c */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
unsigned int x, y;
unsigned long long res;
if ((argc < 3) || (sscanf(argv[1], "%u", &x) != 1)
|| (sscanf(argv[2], "%u", &y)) != 1)
{
printf("Usage: pow base exponent\n");
exit(1);
}
res = unsgn_pow(x, y);
printf("%u ^ %u = %u\n", x, y, res);
exit(0);
}
我们用unsgn_pow.c文件可以制作一个函数库。下面分别讲解怎么生成静态库和动态库。
n 静态库的创建和使用。
创建静态库比较简单,使用归档工具ar将一些目标文件集成在一起。
[root@localhost lib]# gcc -c unsgn_pow.c
[root@localhost lib]# ar rcsv libpow.a unsgn_pow.o
a - unsgn_pow.o
下面编译主程序,它将会链接到刚生成的静态库libpow.a。具体运行结果如下所示。
[root@localhost lib]# gcc -o pow_test pow_test.c -L. –lpow
[root@localhost lib]# ./pow_test 2 10
2 ^ 10 = 1024
其中,选项"-L dir"的功能与"-I dir"类似,能够在库文件的搜索路径列表中添加dir目录,而"-lname"选项指示编译时链接到库文件libname.a或者libname.so。本实例中,程序pow_test.c需要使用当前目录下的一个静态库libpow.a。
n 动态库的创建和使用。
首先使用gcc的-fPIC选项为动态库构造一个目标文件
[root@localhost lib]# gcc -fPIC -Wall -c unsgn_pow.c
接下来,使用-shared选项和已创建的位置无关目标代码,生成一个动态库libpow.so。
[root@localhost lib]# gcc -shared -o libpow.so unsgn_pow.o
下面编译主程序,它将会链接到刚生成的动态库libpow.so。
[root@localhost lib]# gcc -o pow_test pow_test.c -L. –lpow
在运行可执行程序之前,需要注册动态库的路径名。其方法有几种:修改/etc/ld.so.conf文件,或者修改LD_LIBRARY_PATH环境变量,或者将库文件直接复制到/lib或者/usr/lib目录下(这两个目录为系统的默认的库路径名)。
[root@localhost lib]# cp libpow.so /lib
[root@localhost lib]# ./pow_test 2 10
2 ^ 10 = 1024
动态库只有当使用它的程序执行时才被链接使用,而不是将需要的部分直接编译入可执行文件中,并且一个动态库可以被多个程序使用故可称为共享库,而静态库将会整合到程序中,因此在程序执行时不用加载静态库。 从而可知,链接到静态库会使用户的程序臃肿,并且难以升级,但是可能会比较容易部署。而链接到动态库会使用户的程序轻便,并且易于升级,但是会难以部署。
(3)告警和出错选项。
gcc的告警和出错选项如表3.9所示。
表3.9 gcc警告和出错选项选项列表
选 项 | 含 义 |
-ansi | 支持符合ANSI标准的C程序 |
-pedantic |
- Linux下C编程基础之:常用编辑器(08-13)
- Linux下C编程基础之:gdb调试器(08-13)
- Linux下C编程基础之:make工程管理器(08-13)
- Linux下C编程基础之:使用autotools(08-13)
- Linux下C编程基础之:实验内容(08-13)
- Linux下C编程基础之:本章小结与思考与练习(08-13)