• Linux编程简介——gcc


    在Linux环境下,我们通常用gcc将C代码编译成可执行文件,如下就是一个简单的例子:

    代码文件:hello.c

        #include <stdlib.h>
        #include <stdio.h>

        void main(void)
        {
            printf("hello world!\r\n");
        }

    可以通过如下指令来编译出一个可执行文件:

        gcc hello.c

    执行完该命令后,就会得到一个a.out的可执行文件。

    编译的过程

    前面的例子只是简单的介绍了一下gcc的使用方法,熟悉c编程的朋友就会知道,该步骤其实包含了预处理-->编译-->汇编-->链接四步,这四步分别实现的功能如下:

    1. 预处理阶段:主要处理源文件中的#ifdef、 #include和#define命令,展开宏、读取定义的符号等。
    2. 编译阶段:检查代码的规范性,把代码翻译成汇编语言
    3. 汇编阶段:是把编译阶段生成的".s"文件转成二进制目标代码
    4. 链接阶段:将汇编阶段生成的机器码汇集成一个可执行的二进制代码文件

    由此可以看出,每一个阶段的输出其实就是下一个阶段的输入,用gcc是可以单独执行这四步的:

        gcc -E hello.c -o hello.i
        gcc -S hello.i -o hello.s
        gcc -c hello.s -o hello.o
        gcc hello.o -o hello.exe

    实际上,由于这四个步骤太过于复杂,往往可以像我上面那样全部集中到一个命令中来执行:

        gcc hello.c -o hello.exe

    这里我加了一个-o参数来指定输出名称,而不是默认的a.out。

    如果有多个文件,则可以通过如下方式全部集中起来。

        gcc -o test first.c second.c third.c

    这个全生成的方式虽然非常简单,但是存在的一个问题就是:当项目较大时,如果只改了一个文件,仍需要重新编译索引文件。

    为了解决这个问题,我们往往把这个编译过程拆分成两步:

    1. 将各个.c文件分别编译成.o文件
    2. 将所有.o文件链接成执行文件

        gcc –c first.c
        gcc –c second.c
        gcc –c third.c
        gcc -o test first.o second.o third.o

    这样,当third.c文件发生改变时,只需要重新编译third.c和链接即可,这样就省去了未变化文件的编译时间,也就是我们通常所说的增量编译。

        gcc –c third.c
        gcc -o test first.o second.o third.o

    从上面的使用方法中我们也可以看到:

    • 当使用-c参数时,若输入文件时.c则会同时执行执行了预处理、编译、汇编三个阶段,直接生成.o文件。
    • 输入文件为.o时,可以直接执行链接操作

    由于程序员往往并不关心前面两个几个阶段生成的输出文件,通常我们也把预处理、编译、汇编三个阶段合并在一起,统称为编译,输入.c,生成.o。

    常用参数:

    前面其实已经演示过-E、–S、–c、–o等几个参数的用法,其中-E及-S很少会用到,-c用于编译生成.o文件,-o用于指定输出文件名称。除了这几个生成控制的参数外,还有许多参数设置,这里主要介绍一下几个常用的:

    包含头文件和库:

    • -Idir: 指定编译查找头文件的目录,常用于查找第三方的库的头文件,例:gcc test.c –I../inc -o test。
    • -Ldir : 指定链接时查找lib的目录,常用于查找第三方库。
    • -llibrary :    指定额外链接的lib库

    宏定义:

    • -DMACRO                         以字符串"1"(默认值)定义 MACRO 宏。
    • -DMACRO=DEFN              以字符串"DEFN"定义MACRO 宏,注意中间不能有空格。
    • -UMACRO                         取消对 MACRO 宏的定义。

    调试和可执行文件形式:

    • -g 指示编译器,在编译的时产生调试信息。
    • -ggdb 尽可能的生成gdb的可以使用的调试信息(比-g生成的信息更多些)。
    • -static 禁止使用动态库,编译得到的程序会比较大,但可以自由运行。
    • -share 尽量使用动态库,所以生成文件比较小,但是需要系统由动态库。

    告警选项:

    • -Wall   产生尽可能多的警告信息,建议始终带上
    • -Werror  将所有的警告当成错误进行处理

    gcc和g++

    除了gcc编译器外,还有另外一个编译器g++,很多人往往搞不清楚这两个编译器的区别,很多人望文生义的认为gcc只能编c代码,g++只能编c++代码。实际上这两个编译器的主要区别如下:

    • 后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序来编译
    • 链接的时候gcc不会默认加上-lstdc++选项(g++会),而我们往往又没有手动加这个选项的习惯,则导致gcc编c++代码时,用到了stl库时会出现链接失败。

    关于它们的区别的更多信息,可以参考这个文章:http://ldzyz007.iteye.com/blog/865080

    为了使用简单,可以制定如下规则:对c项目使用gcc,对c++项目使用g++。估计当时设计这个名字的意图也是如此吧。

  • 相关阅读:
    js冒泡排序
    HTML5 canvas 计时器
    centos 6.4安装杀毒软件clamAV 0.98[转]
    PHP大文件下载
    如何在 Eclipse 中使用插件构建 PHP 开发环境[转]
    CentOS 单用户模式:修改Root密码和grub加密[转]
    CentOS 6.0 VNC远程桌面配置[转]
    gprof使用介绍 (gcc -pg) [转]
    VMware NAT端口映射外网访问虚拟机linux
    shell判断文件是否存在[转]
  • 原文地址:https://www.cnblogs.com/TianFang/p/2865974.html
Copyright © 2020-2023  润新知