linux下GCC编译C程序

GNU编译器集
    GNU编译器集(其前身为GNU C编译器)诞生于1987年。当时Richard Stallman(GNU项目的创办人)想要创建一个编译器,它可以满足他定义的“自由软件”概念,并可用来编译GNU项目发布的其他软件。GNU C编译器迅速在自由软件社区中流行开来,而且以其健壮性和可移植性而闻名。它已成为许多集成开发工具的基础,被世界各地的发行商应用在Linux和其他操 作系统之上。
    GCC已不再是主要针对GNU项目自身的软件的小型C语言编译器了。如今,它已支持了许多不同的语言,包括C、C++、Ada、Fortran、 Objective C,甚至还有Java。事实上,现代Linux系统除了可以自豪地炫耀那些由GNU工具直接支持的语言以外,它还支持大量其他语言。日益流行的脚本语言 Perl、Python和Ruby,以及正在不断发展的mono 可移植C#实现的确有助于冲淡人们对Linux编程的传统看法,但这完全是另外一个问题了。

Linux内核和许多其他自由软件以及开放源码应用程序都是用C语言编写并使用GCC编译的。

1. 编译单个源文件

为了进行测试,你可以创建“Hello World”程序:

C代码
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3.   
  4. int  main( int  argc,  char  **argv)  
  5. {  
  6.         printf("Hello world!/n" );  
  7.         exit(0);  
  8. }  


使用如下命令编译并测试这个代码:
引用
# gcc -o hello hello.c
# ./hello
Hello wordl!


在默认情况下产生的可执行程序名为a.out,但你通常可以通过gcc的“-o”选项来指定自己的可执行程序名称。

2. 编译多个源文件

源文件message.c包含一个简单的消息打印函数:
C代码
  1. #include <stdio.h>   
  2.   
  3. void  goodbye_world( void )  
  4. {  
  5.         printf("Goodbye, world!/n" );  
  6. }  


使用gcc的“-c”标记来编译支持库代码:
引用
# gcc -c message.c


这一过程的输出结果是一个名为message.o的文件,它包含适合连接到一个较大程序的已编译目标代码。

创建一个简单的示例程序,它包含一个调用goodbye_world的main函数

C代码
  1. #include <stdlib.h>   
  2.   
  3. void  goodbye_world( void ):  
  4.   
  5. int  main( int  argc,  char  **argv)  
  6. {  
  7.         goodbye_world();  
  8.         exit(0);  
  9. }  


使用GCC编译这个程序:
引用
# gcc -c main.c



现在有了两个目标文件:message.o和main.o。它们包含能够被Linux执行的目标代码。要从这个目标代码创建Linux可执行程序,需要再一次调用GCC来执行连接阶段的工作:
引用
# gcc -o goodbye message.o main.o



运行编译结果:
引用
# ./goodbye
Goodbye, world!



前面这些单独的步骤也可以简化为一个命令,这是因为GCC对如何将多个源文件编译为一个可执行程序有内置的规则。
引用
# gcc -o goodbye message.c main.c
# ./goodbye
Goodbye, world!



3. 使用外部函数库
GCC常常与包含标准例程的外部软件库结合使用,几乎每一个Linux应用程序都依赖于由GNU C函数库GLIBC。
应用外部函数库的例子:
C代码
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <math.h>   
  4.   
  5. #define MAX_INPUT 25   
  6.   
  7. int  main( int  agrc,  char  **argv)  
  8. {  
  9.         char  input[MAX_INPUT];  
  10.         double  angle;  
  11.   
  12.         printf("Give me an angle (in radians) ==>" );  
  13.         if (!fgets(input, MAX_INPUT, stdin)){  
  14.                 perror("an error occurred./n" );  
  15.         }  
  16.         angle = strtod(input, NULL);  
  17.   
  18.         printf("sin(%e) = %e/n" , angle, sin(angle));  
  19.   
  20.         return  0;  


编译命令:
引用
# gcc -o trig -lm trig.c


GCC的"-lm"选项,它告诉GCC查看系统提供的数学库(libm)。因为Linux和UNIX的系统函数库通常以"lib"为前缀,所以我 们假设它存在。真正的函数库位置随系统的不同而不同,但它一般会位于目录/lib或/usr/lib中,在这些目录中还有数以百计的其他必需的系统函数 库。

4. 共享函数库与静态函数库

Linux系统上的函数库分为两种不同的类型:共享的和静态的

静态函数库:每次当应用程序和静态连接的函数库一起编译时,任何引用的库函数中的代码都会被直接包含进最终的二进制程序。

共享函数库:包含每个库函数的单一全局版本,它在所有应用程序之间共享。这一过程背后所涉及的机制相当复杂,但主要依靠的是现代计算机的虚拟内存能力,它允许包含库函数的物理内存安全地在多个独立用户程序之间共享。

使用共享函数库不仅减少了文件的容量和Linux应用程序在内存中覆盖的区域,而且它还提高了系统的安全性。一个被许多不同程序同时调用的共享函 数库很可能会驻留在内存中,以在需要使用它时被立即使用,而不是位于磁盘的交换分区中。这有助于进一步减少一些大型Linux应用程序的装载时间。

将上面的message.c作为共享库函数使用的例子:

引用
# gcc -fPIC -c message.c


“PIC”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接 到哪一段内存地址空间。这样编译输出的文件message.o可以被用于建立共享函数库,我们只需使用gcc的“-shared”标记即可:
引用
# gcc -shared -o libmessage.so message.o



将上面的mian.c使用共享库函数ligmessage.so编译:
引用
# gcc -o goodbye -lmessage -L. message.o

“-lmessage”标记来告诉GCC在连接阶段引用共享函数库libmessage.so。“-L.”标记告诉GCC函数库可能位于当前目录中,否则GNU的连接器会查找标准系统函数库目录,在本例的情况下,就找不到可用的函数库了。

此时运行编译好的goodbye会提示找不到共享函数库:
引用
#./goodbye
./goodbye: error while loading shared libraries: libmessage.so: cannot open shared object file: No such file or directory


可以使用命令ldd来发现一个特定应用程序需要使用的函数库。ldd搜索标准系统函数库路径并显示一个特定程序使用的函数库版本。
引用
#ldd goodbye
        linux-gate.so.1 =>  (0x00493000)
        libmessage.so => not found
        libc.so.6 => /lib/libc.so.6 (0x0097c000)
        /lib/ld-linux.so.2 (0x0095a000)


库文件libmessage.so不能在任何一个标准搜索路径中找到,而且系统提供的配置文件/etc/ld.so.conf也没有包含一个额外的条目来指定包含该库文件的目录。

需要设置一个环境变量LD_LIBRARY_PATH来制定额外的共享函数库搜索路径,
引用
# export LD_LIBRARY_PATH=`pwd`
# ldd goodbye
        linux-gate.so.1 =>  (0x002ce000)
        libmessage.so => /tmp/cpro/libmessage.so (0x00b0f000)
        libc.so.6 => /lib/libc.so.6 (0x0097c000)
        /lib/ld-linux.so.2 (0x0095a000)

运行程序
引用
# ./goodbye
Goodbye, world!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值