`
liuye066
  • 浏览: 264112 次
  • 性别: Icon_minigender_2
  • 来自: 青岛
社区版块
存档分类
最新评论

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. }  
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
        printf("Hello world!\n");
        exit(0);
}




使用如下命令编译并测试这个代码:

引用
# 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. }  
#include <stdio.h>

void goodbye_world(void)
{
        printf("Goodbye, world!\n");
}



使用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. }  
#include <stdlib.h>

void goodbye_world(void):

int main(int argc, char **argv)
{
        goodbye_world();
        exit(0);
}



使用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;   
  21. }  
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX_INPUT 25

int main(int agrc, char **argv)
{
        char input[MAX_INPUT];
        double angle;

        printf("Give me an angle (in radians) ==>");
        if(!fgets(input, MAX_INPUT, stdin)){
                perror("an error occurred.\n");
        }
        angle = strtod(input, NULL);

        printf("sin(%e) = %e\n", angle, sin(angle));

        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!
分享到:
评论

相关推荐

    linux下GCC编译C程序

    GCC已不再是主要针对GNU项目自身的软件的小型C语言编译器了。如今,它已支持了许多不同的语言,包括C、C++、Ada、Fortran、Objective C,甚至还有Java。事实上,现代Linux系统除了可以自豪地炫耀那些由GNU工具直接...

    如何在Linux下用gcc编译c程序

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

    Linux下的简单C程序gcc编译、gdb调试。

    Linux下的简单C程序gcc编译、gdb调试。

    linux下gcc编译器的使用

    在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一 位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中...

    linux操作系统下C语言编程入门 gcc编译

    linux操作系统下C语言编程入门 gcc编译 gdb调试技术 实例演示

    Linux下GCC的使用

    在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一 位Linux程序员面临的首要问题都是如何灵活运用C编译器。GCC是在Linux下开发程序时必须掌握的工具之一。本文对GCC做了一个简要的介绍,主要...

    Visual Studio 2010 编译C及一个完整的c程序(可在windows与linux(用gcc编译)平台下使用)

    NULL 博文链接:https://sealbird.iteye.com/blog/894953

    UbuntuLinux下建立GCC环境

     在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器. 下面 我们以一个实例来说明如何使用gcc编译器. 假设我们有下面一个非常简单的源程序(hello.c): int main(int argc,char **argv...

    Makefile文件arm-none-linux-gnueabi-gcc编译文件

    Makefile文件arm-none-linux-gnueabi-gcc编译文件,linux下多个.C文件统一使用make文件进行编译

    内网环境下Linux环境gcc gcc-c++编译器安装所需依赖

    包含gcc gcc-c++ 编译器安装所需依赖包,用于C语言编写的程序在linux安装时的编译如nginx 执行rpm -Uvh *.rpm --nodeps --force 一键安装

    linux使用gcc编译c语言共享库步骤

    对任何程序员来说库都是必不可少的。所谓的库是指已经编译好...除此之外,你还可以保证你的程序各模块隔离,这样你修改其中一个模块时也不会影响到其他的模块。一旦你写好一个模块并且通过测试,你就可以无限次地安全地

    Linux下编译与调试((gcc、gdb)

    里面包含了如何在linux在编译调试C、C++程序的方法文档,详细介绍了gcc、g++、gdb命令。

    Linux操作系统上安装GCC编译器过程

    目前,GCC可以用来编译 C/C++、FORTRAN、JAVA、OBJC、ADA 等语言的程序,可根据需要选择安装支持的语言。GCC 3.4.0比以前版本更好地支持了C++标准。本文以在Redhat Linux上安装GCC3.4.0为例,介绍了GCC的安装过程。...

    arm-linux-gcc-3.4.5

    构建的交叉编译环境适用于s3c2440,最开始是从网上下载的arm-linux-gcc 4.6.4 添加完环境变量后可以查利用arm-linux-gcc -v查看到版本号,也可以正常编译程序。但是在打补丁之后的最后一步make时出现错误。后来用的...

    Linux环境编程 实验3.doc

    根据实验指导书的要求和步骤,完成相应的程序开发及多模块软件编译与链接过程,并在Linux环境下,完成程序开发及软件剖析。 一、实验目的: 1)掌握MYSQL数据库命令与应用编程。 2)了解Linux多模块软件编译与链接...

    西南科技大学+Linux实验报告+Linux环境下C语言编程

    1.熟悉字符模式下的C程序编译和调试环境 2.基本掌握Linux字符模式下的编译工具和调试工具的使用 3.掌握自动编译工具make的使用和Makefile的编写方法 二、实验设计 1.GCC使用方法 2.调试器GDB使用方法(选做) 3....

    Linux下编译C程序的过程

    学习一门语言程序,本人觉得还是得学习它的编译规则,现在,通过小例子小结下自己对C编译的认识。 /*test.c 了解C程序的编译*/ #include int main(void) { printf(Hello World!\n); return 0; } 对于test.c,...

    mingw32_gcc441 编译ffmpeg

    mingw,在windows下建立linux的gcc环境,用于编译那些在linux下开发的、只支持gcc编译的程序。

    grpc-1.30.2 Linux 编译静动态库

    在 centos 7 下使用 gcc 4.8.5 + cmake 3.16.9 编译,包含 bin, include, lib, lib64, share 五个目录,可以直接在 linux C++ 程序中引用。 因为 grpc 编译比较麻烦,且依赖项较多,故而分享一下编译后的版本,本人...

Global site tag (gtag.js) - Google Analytics