`

C++编译器—gcc的用法

 
阅读更多

原文:http://c.chinaitlab.com/system/784700.html

在 为Linux /Unix开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何灵活运用C编译器。目前Linux 下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大,结构也异常灵活。最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、 Fortran、Pascal、Modula-3和Ada等。

    开放、自由和灵活是Linux的魅力所在,而这一点在GCC上的体现就是程序员通过它能够更好地控制整个编译过程。在使用GCC编译程序时,编译过程可以被细分为四个阶段:

    ◆ 预处理(Pre-Processing)

    ◆ 编译(Compiling)

    ◆ 汇编(Assembling)

    ◆ 链接(Linking)

    Linux 程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不 同数量和种类的调试代码来为今后的调试做好准备。和其它常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码。

    GCC提供了30多条警告信息和三个警告级别,使用它们有助于增强程序的稳定性和可移植性。此外,GCC还对标准的C和C++语言进行了大量的扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。

    GCC起步

    在学习使用GCC之前,下面的这个例子能够帮助用户迅速理解GCC的工作原理,并将其立即运用到实际的项目开发中去。首先用熟悉的编辑器输入清单1所示的代码:

    清单1:hello.c

 #include
int main(void)
{
printf (”Hello world, Linux programming!\n”);
return 0;
}

 

    然后执行下面的命令编译和运行这段程序:
 # gcc hello.c -o hello
# ./hello
Hello world, Linux programming!

    用法: gcc [OPTION] file … 用–help可以得到更多帮助。

    常用选项:

    1) -o <FILE> 指定输出的文件,如果是一个文件的C程序不指定-o选项,则输出的文件是一个a.out的可执行文件,运行。/a.out可以运行,注意LINUX下当前目录默认不在搜索路径下,所以运行当前目录的程序也必须加。/ .

    2) -c 只编译不连接,这样生成的程序如果不指定-o是file.o形式的文件,基本名字和C 程序的相同。有些程序可能包括很多个文件,需要将每个文件先编译成。o的文件,然后再连接在一起。

    3) -I 指定include搜索的路径。如-I/home/lxq/include即指定include搜索路径中加上/home/lxq/include.

    4) -L 指定库的搜索路径。如-L/home/lxq/libs即指定库的搜索路径中加上/home/lxq/libs.

    5) -l 指定所用到的库。Linux下的库文件一般是这种格式:静态库libxxxx.a,动态库libxxx.so,这样如果用到了某个库只需在编译的时候加上-lxxx即可。比如-lm,即包含数学库。

    6) -g 加入调试信息。加了这个选项之后生成的程序可以进行调试,但是可能程序的执行速度会受到影响。可能用-gdb3来代替,-gdb3加入的调试信息最多。

    7) -On 优化生成的目标代码。n是一个具体的数,如3.这样生成的程序没有调试信息加入不能进行调试,但是程序的效率比较高,对有些程序的执行速度可能会影响很大。make及Makefile的用法:

    make是用来管理工程文件的,系统自动检测变化的部分,并为这种变化采取适当的 动作。make工作要有一个Makefile文件,下面介绍Makefile的文件格式及写法。

    例子:

    共有main.c func.c func.h 三个文件的程序其中main.c中有#i nclude<func.h>

    gcc -c main.c -o main.o

    gcc -c func.c -o func.o

    gcc main.o func.o -o main

    这样就生成了main的可执行程序,当然这些工作用make来做便不用每次都敲这些命令

    当在一个目录下运行make命令时,系统自动找Makefile或makefile,如果两者都没有,也可以用-f来指定。Makefile的基本规则是这样的:

    目标:依赖程序

    <TAB> 执行命令1

    <TAB> 执行命令2

    比如上面的例子可以写成Makefile如下:

 main:main.o func.o
     gcc main.o func.o -o main
       main.o:main.c
     gcc -c main.c -o main.o
       func.o:func.c func.h
                   gcc -c func.c -o func.o

 

    注意此处必须是TAB键而不能是空格。

    可以在Makefile里定义变量,变量的引用用$()来表示,可参考相关书籍介绍

    从 程序员的角度看,只需简单地执行一条GCC命令就可以了,但从编译器的角度来看,却需要完成一系列非常繁杂的工作。首先,GCC需要调用预处理程序 cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,GCC会调用ccl和as将处理后的源代码编译成目 标代码;最后,GCC会调用链接程序ld,把生成的目标代码链接成一个可执行程序。

    为了更好地理解GCC的工作过程,可以把上述编译过程分成几个步骤单独进行,并观察每步的运行结果。第一步是进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程:

    # gcc -E hello.c -o hello.i

    此时若查看hello.cpp文件中的内容,会发现stdio.h的内容确实都插到文件里去了,而其它应当被预处理的宏定义也都做了相应的处理。下一步是将hello.i编译为目标代码,这可以通过使用-c参数来完成:

    # gcc -c hello.i -o hello.o

    GCC默认将。i文件看成是预处理后的C语言源代码,因此上述命令将自动跳过预处理步骤而开始执行编译过程,也可以使用-x参数让GCC从指定的步骤开始编译。最后一步是将生成的目标文件链接成可执行文件:

    # gcc hello.o -o hello

    在 采用模块化的设计思想进行软件开发时,通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有 一个由foo1.c和foo2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序foo,可以使用下面这条命令:

    # gcc foo1.c foo2.c -o foo

    如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下三条命令:

    # gcc -c foo1.c -o foo1.o

    # gcc -c foo2.c -o foo2.o

    # gcc foo1.o foo2.o -o foo

    在 编译一个包含许多源文件的工程时,若只用一条GCC命令来完成编译是非常浪费时间的。假设项目中有100个源文件需要编译,并且每个源文件中都包含 10000行代码,如果像上面那样仅用一条GCC命令来完成编译工作,那么GCC需要将每个源文件都重新编译一遍,然后再全部连接起来。很显然,这样浪费 的时间相当多,尤其是当用户只是修改了其中某一个文件的时候,完全没有必要将每个文件都重新编译一遍,因为很多已经生成的目标文件是不会改变的。要解决这 个问题,关键是要灵活运用GCC,同时还要借助像Make这样的工具。

 

警告提示功能

    GCC包含完整的出错检查和警告提示功能,它们可以帮助Linux程序员写出更加专业和优美的代码。先来读读清单2所示的程序,这段代码写得很糟糕,仔细检查一下不难挑出很多毛病:

    ◆main函数的返回值被声明为void,但实际上应该是int;

    ◆使用了GNU语法扩展,即使用long long来声明64位整数,不符合ANSI/ISO C语言标准;

    ◆main函数在终止前没有调用return语句。

    清单2:illcode.c

 #include
void main(void)
{
long long int var = 1;
printf(”It is not standard C code!\n”);
}

 

下面来看看GCC是如何帮助程序员来发现这些错误的。当GCC在编译不符合ANSI/ISO C语言标准的源代码时,如果加上了-pedantic选项,那么使用了扩展语法的地方将产生相应的警告信息:

 

 # gcc -pedantic illcode.c -o illcode
illcode.c: In function `main’:
illcode.c:9: ISO C89 does not support `long long’
illcode.c:8: return type of `main’ is not `int’

 

    需要注意的是,-pedantic编译选项并不能保证被编译程序与ANSI/ISO C标准的完全兼容,它仅仅只能用来帮助Linux程序员离这个目标越来越近。或者换句话说,-pedantic选项能够帮助程序员发现一些不符合 ANSI/ISO C标准的代码,但不是全部,事实上只有ANSI/ISO C语言标准中要求进行编译器诊断的那些情况,才有可能被GCC发现并提出警告。

    除了-pedantic之外,GCC还有一些其它编译选项也能够产生有用的警告信息。这些选项大多以-W开头,其中最有价值的当数-Wall了,使用它能够使GCC产生尽可能多的警告信息:

 # gcc -Wall illcode.c -o illcode
illcode.c:8: warning: return type of `main’ is not `int’
illcode.c: In function `main’:
illcode.c:9: warning: unused variable `var’

 

    GCC给出的警告信息虽然从严格意义上说不能算作是错误,但却很可能成为错误的栖身之所。一个优秀的Linux程序员应该尽量避免产生警告信息,使自己的代码始终保持简洁、优美和健壮的特性。

    在 处理警告方面,另一个常用的编译选项是-Werror,它要求GCC将所有的警告当成错误进行处理,这在使用自动编译工具(如Make等)时非常有用。如 果编译时带上-Werror选项,那么GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。只有当相应的警告信息消除时,才可能将编 译过程继续朝前推进。执行情况如下:

 # gcc -Wall -Werror illcode.c -o illcode
cc1: warnings being treated as errors
illcode.c:8: warning: return type of `main’ is not `int’
illcode.c: In function `main’:
illcode.c:9: warning: unused variable `var’

 

    对Linux程序员来讲,GCC给出的警告信息是很有价值的,它们不仅可以帮助程序员写出更加健壮的程序,而且还是跟踪和调试程序的有力工具。建议在用GCC编译源代码时始终带上-Wall选项,并把它逐渐培养成为一种习惯,这对找出常见的隐式编程错误很有帮助。

    库依赖

    在Linux 下开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助一个或多个函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实 际上就是一些头文件(。h)和库文件(。so或者。a)的集合。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库 文件则放到/usr/lib/目录下,但并不是所有的情况都是这样。正因如此,GCC在编译时必须有自己的办法来查找所需要的头文件和库文件。

    GCC采用搜索目录的办法来查找所需要的文件,-I选项可以向GCC的头文件搜索路径中添加新的目录。例如,如果在/home/xiaowp/include/目录下有编译时所需要的头文件,为了让GCC能够顺利地找到它们,就可以使用-I选项:

    # gcc foo.c -I /home/xiaowp/include -o foo

    同样,如果使用了不在标准位置的库文件,那么可以通过-L选项向GCC的库文件搜索路径中添加新的目录。例如,如果在/home/xiaowp/lib/目录下有链接时所需要的库文件libfoo.so,为了让GCC能够顺利地找到它,可以使用下面的命令:

    # gcc foo.c -L /home/xiaowp/lib -lfoo -o foo

    值得好好解释一下的是-l选项,它指示GCC去连接库文件libfoo.so.Linux下的库文件在命名时有一个约定,那就是应该以lib三个字母开头, 由于所有的库文件都遵循了同样的规范,因此在用-l选项指定链接的库文件名时可以省去lib三个字母,也就是说GCC在对-lfoo进行处理时,会自动去 链接名为libfoo.so的文件。

    Linux下的库文件分为两大类分别是动态链接库(通常以。so结尾)和静态链接库(通常以。a 结尾),两者的差别仅在程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。默认情况下,GCC在链接时优先使用动态链接库,只有当动态 链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。例如,如果在 /home/xiaowp/lib/目录下有链接时所需要的库文件libfoo.so和libfoo.a,为了让GCC在链接时只用到静态链接库,可以使 用下面的命令:

    # gcc foo.c -L /home/xiaowp/lib -static -lfoo -o foo

分享到:
评论

相关推荐

    LINUX下的C++编译器GCC简介

    ### Linux下的C++编译器GCC简介 #### 一、GCC概述 GCC(GNU C Compiler),作为GNU项目的重要组成部分之一,是由自由软件基金会推出的多平台编译器工具链。它支持包括C、C++在内的多种编程语言,并且能够在不同的...

    C++编译器GCC的源代码

    通过深入研究GCC源代码,不仅可以增强对C++语言和编译器内部运作的理解,还可以学习到软件工程实践,如模块化设计、错误处理和测试方法。这对于想要成为系统级程序员或编译器开发者的人来说是一笔宝贵的财富。不过,...

    Linux系统上C/C++编译器gcc/egcs详解

    ### Linux系统上C/C++编译器gcc/egcs详解 在Linux环境下,GCC(GNU Compiler Collection)作为一套重要的开源编译器集合,为开发者提供了强大的C和C++语言支持。GCC不仅支持C语言,还支持C++以及Objective-C等多种...

    Linux下CC++编译器gcc使用简介.doc

    GCC(GNU Compiler Collection)是 Linux 下最常用的 C/C++ 编译器,本文将详细介绍 GCC 的使用方法和相关参数。 1. GCC 包含的 C/C++ 编译器 GCC 包含了 C 和 C++ 两种编译器,分别是 gcc 和 g++。其中,gcc 用于...

    迷你型C++编译器和函数编译手册

    下面我们将深入探讨C++编译器的基本概念、C++语言的核心要素以及函数的使用方法。 首先,C++编译器是将源代码(程序员书写的C++代码)转换成可执行程序的软件。它负责解析源代码,检查语法错误,进行类型检查,并...

    MinGW-w64 C/C++编译器+libsvm安装包.rar

    C/C++编译器是软件开发的基础工具,它们将程序员编写的源代码转换成计算机可以执行的机器码。GCC通过解析源代码,进行语法分析、语义分析,然后生成中间代码,最后优化并生成可执行文件。MinGW-w64在Windows环境下,...

    Linux上的C-C++编译器和调试器

    ##### 1.1 GCC的使用方法 - **基本命令**: `gcc [options] source-files... -o executable-file` - `[options]` 表示各种选项,用于控制编译过程。 - `source-files...` 表示要编译的源文件。 - `-o executable-...

    gcc-4.4.0 c语言最好的编译器 ansii c 覆盖率98%。也含有c++编译器

    在压缩包的文件名称列表中,我们看到“man”通常包含编译器的手册页,这些手册页提供了详细的命令行选项、使用方法和错误信息解释,是开发者解决问题的重要参考。“bin”目录包含了可执行文件,比如gcc和g++的二进制...

    Linux C++编程:编译器GCC简介.pdf

    ### Linux C++编程:GCC编译器简介 #### GCC概览 GCC(GNU Compiler Collection),全称为GNU编译器集合,是GNU项目的核心组件之一,也是目前Linux及其他类Unix操作系统中最广泛使用的开源编译器。它支持多种编程...

    Intel C++ 编译器导读

    虽然主要是C++编译器,但Intel C++也支持Fortran和C语言,便于混合编程环境。 10. **编译器选项**: 提供丰富的编译器选项,如优化级别(-O1至-O3)、警告等级、代码生成目标等,以便根据需求调整编译策略。 ...

    小王儿--C++编译器

    C++编译器是将C++源代码转换成可执行程序的关键工具,它解析程序员书写的C++代码并将其转化为机器可以理解的语言。...总的来说,C++编译器是C++编程的基础,理解其工作原理和使用方法对于提升C++开发技能至关重要。

    【离线安装包】gcc-c++.zip

    GCC(GNU Compiler Collection)是GNU项目的一部分,是一个开源的、跨平台的编译器套件,用于将源代码编译成可执行程序。...理解其安装和使用方法是每个Linux系统管理员和C++开发者的基础技能之一。

    C++编译器:MinGW64 5.1.4版本(官方版)

    C++官方编译器:MinGW64, 5.1.4版本,完整版下载,绝无缺漏。通过cmd运行bin文件夹下的g++.exe或gcc.exe即可一键编译。用法示例:g++.exe hello.cpp -o hello.exe -Wall

    Matlab2020a配置MinGW-w64 C/C++ 编译器

    本教程将聚焦于如何在Matlab 2020a中配置MinGW-w64 C/C++编译器,以实现这一目标。 首先,MinGW-w64是一个开源项目,提供了一个Windows下的GCC(GNU Compiler Collection)编译环境,它支持32位和64位的应用程序...

    gcc中文手册 GNU Tools g++ c/c++编译器

    **GCC中文手册 GNU Tools - g++与C/C++编译器** GCC(GNU Compiler Collection),是由GNU项目开发的一套开源的、跨平台的编译工具集,它包含了针对多种编程语言(如C、C++、Objective-C、Fortran、Ada等)的编译器...

    linux系统下C编译器GCC入门.docx

    Linux 系统下 C 编译器 GCC 入门 GCC(GNU C Compiler)是 GNU 推出的功能强大、性能优越的多平台编译器,是 ...了解 GCC 编译器的工作原理和基本用法,可以帮助我们更好地使用 GCC 编译器,提高编译效率和代码质量。

    gcc 3.3 c c++ linux编译器

    GCC(GNU Compiler Collection)是GNU项目的一个核心组件,它是一个开源的、跨平台的编译器套件,用于将C、C++以及其他多种编程...了解和掌握其使用方法,对于深入理解编程语言的编译过程和Linux开发环境是非常有益的。

    linux编译器GCC编译手册

    本文档将详细介绍GCC内嵌汇编的使用方法及相关知识点。 #### 内嵌汇编的基本概念 内嵌汇编是指在高级语言程序(如C或C++)中直接嵌入汇编代码的一种技术。它允许程序员直接访问处理器特定的指令,从而实现更底层的...

    linuxc编程:编译器gcc简介.docx

    "Linux编程:编译器GCC简介" GCC(GNU Compiler Collection)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。GCC可以在多种硬件平台上编译出可执行程序,其执行效率与一般的编译器相比平均...

Global site tag (gtag.js) - Google Analytics