`
hyshucom
  • 浏览: 806093 次
文章分类
社区版块
存档分类
最新评论

编译器之GCC命令

 
阅读更多

gcc ,gdb, makefile在linux下编程都是很重要的东西

GDB手册在chinaunix有一份:你去好好研究下哦,

http://wiki.chinaunix.net/index.php/%E5%88%86%E7%B1%BB:GDB%E6%89%8B%E5%86%8C

下面是gcc常用的选项,后面会经常用到的

编译时加个开关 -g
-g
在编译的时候,产生调试信息
-c
只激活预处理,编译和汇编,也就是把程序做成obj文件。如gcc -c test.c 就会生成test.o文件,

当然这样还只是目标文件,需要经过ld连接器对所有的.o文件进行联接才能生成可执行文件.

-S
只激活预处理和编译,把文件编译到汇编代码。相当到对源程序做一个egcs操作,生成.s文件。

可以查看生成的汇编文件结果。这个对于研究汇编语言的程序员来说是很有作用的。

-E
只激活预处理,这个将对文件进行预处理,将对所有引入的include文件和define定义的量进行代换,

为我们开头所说的gcc编译的第一步,即用cpp命令将程序语言文件进行预处理.但这一步不生成结果文件,

如果你需要生成结果文件保存,那么需要利用系统中的输出重定向。

-o
定制目标名称,缺省的时候在unix和linux平台下gcc filename的结果是一个文件名为a.out的文件,

windows下用mingw里带的gcc编译结果是a.exe。如果我们用gcc -o hello.exe test.c的话,

将生成hello.exe可执行程序。这个并不一定只限于最后一步可执行程序的生成,

如用上面所讲的-S生成的汇编程序也可以用-o参数生成,比如 gcc -o hello.asm -S test.c

这样hello.asm就是test.c经过预处理和编译之后的结果。

-Idir
在#include 的时候,先在用这个参数指定的位置找头文件,如果没有找到,则到缺省的目录找头文件
-llibrary
用于制定编译的时候使用的库,如 gcc -lgtk tset.c则程序使用gtk库进行编译,

不过需要注意的是gcc库一般都是以libname.a来命名库文件,在用-l参数来加入库文件的时候,

直接用-lname来引入,而前面的lib被省掉。这一点需要注意。
-Ldir
编译的时候设定库文件查找的路径,不然的话,编译器只在标准库路径里面找库。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、GCC简介

通 常所说的GCC是GNU Compiler Collection的简称,除了编译程序之外,它还含其他相关工具,

所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进制代 码。

GCC是Linux平台下最常用的编译程序,它是Linux平台编译器的事实标准。

同时,在Linux平台下的嵌入式开发领域,GCC也是用得最普遍 的一种编译器。

GCC之所以被广泛采用,是因为它能支持各种不同的目标体系结构。

例如,它既支持基于宿主的开发(简单讲就是要为某平台编译程序,就在该平 台上编译),

也支持交叉编译(即在A平台上编译的程序是供平台B使用的)。目前,GCC支持的体系结构有四十余种,

常见的有X86系列、Arm、 PowerPC等。

同时,GCC还能运行在不同的操作系统上,如Linux、Solaris、Windows等。

除了上面讲的之外,GCC除了支持C语言外,还支持多种其他语言,

例如C++、Ada、Java、Objective-C、FORTRAN、Pascal等。

二、程序的编译过程

对于GUN编译器来说,程序的编译要经历预处理、编译、汇编、连接四个阶段,如下图所示:

从功能上分,预处理、编译、汇编是三个不同的阶段,但GCC的实际操作上,

它可以把这三个步骤合并为一个步骤来执行。下面我们以C语言为例来谈一下不同阶段的输入和输出情况。

在预处理阶段,输入的是C语言的源文件, 通常为*.c。它们通常带有.h之类头文件的包含文件。

这个阶段主要处理源文件中的#ifdef、 #include和#define命令。

该阶段会生成一个中间文件*.i,但实际工作中通常不用专门生成这种文件,因为基本上用不到;

若非要生成这种文件 不可,可以利用下面的示例命令:

gcc -E test.c -o test.i

在编译阶段,输入的是中间文件*.i,编译后生成汇编语言文件*.s 。这个阶段对应的GCC命令如下所示:

GCC -S test.i -o test.s

在汇编阶段,将输入的汇编文件*.s转换成机器语言*.o。这个阶段对应的GCC命令如下所示:

GCC -c test.s -o test.o

最后,在连接阶段将输入的机器代码文件*.s(与其它的机器代码文件和库文件)

汇集成一个可执行的二进制代码文件。这一步骤,可以利用下面的示例命令完成:

GCC test.o -o test

上面介绍了GCC编译过程的四个阶段以及相应的命令。下面我们进一步介绍常用的GCC的模式。

三、GCC常用模式

这里介绍GCC追常用的两种模式:编译模式和编译连接模式。下面以一个例子来说明各种模式的使用方法。

为简单起见,假设我们全部的源代码都在一个文件test.c中,要想把这个源文件直接编译成可执行程序,

可以使用以下命令:

$ GCC -o test

这里test.c是源文件,生成的可执行代码存放在一个名为test 的文件中(该文件是机器代码并且可执行)。

-o 是生成可执行文件的输出选项。如果我们只想让源文件生成目标文件(给文件虽然也是机器代码但不可执行),

可以使用标记-c ,详细命令如下所示:

$ GCC -c test.c

默认情况下,生成的目标文件被命名为test.o,但我们也可以为输出文件指定名称,如下所示:

$ GCC -c test.c -o

上面这条命令将编译后的目标文件命名为mytest.o,而不是默认的test.o。

迄今为止,我们谈论的程序仅涉及到一个源文件;现实中,一个程序的源代码通常包含在多个源文件之中,

这该怎么办?没关系,即使这样,用GCC处理起来也并不复杂,见下例:

$ GCC -o test first.c second.c third.c

该命令将同时编译三个源文件,即first.c、second.c和 third.c,然后将它们连接成一个可执行程序,名为test。

需要注意的是,要生成可执行程序时,一个 程序无论有有一个源文件还是多个源文件,

所有被编译和连接的源文件中必须有且仅有一个main函数,因为main函数是该程序的入口点

(换句话说,当系统 调用该程序时,首先将控制权授予程序的main函数)。

但如果仅仅是把源文件编译成目标文件的时候,因为不会进行连接,所以main函数不是必需的。

四、常用选项

许多情况下,头文件和源文件会单独存放在不同的目录中。例如,假设存放源文件的子目录名为./src,

而包含文件则放在层次的其他目录下,如./inc。当我们在./src 目录下进行编译工作时,

如何告诉GCC到哪里找头文件呢?方法如下所示:

$ gcc test.c –I../inc -o test

上面的命令告诉GCC包含文件存放在./inc 目录下,在当前目录的上一级。

如果在编译时需要的包含文件存放在多个目录下,可以使用多个-I 来指定各个目录:

$ gcc test.c –I../inc –I../../inc2 -o test

这里指出了另一个包含子目录inc2,较之前目录它还要在再上两级才能找到。

另外,我们还可以在编译命令行中定义符号常量。为此,我们可以简单的在命令行中使用-D选项即可,

如下例所示:

$ gcc -DTEST_CONFIGURATION test.c -o test

上面的命令与在源文件中加入下列命令是等效的:

#define TEST_CONFIGURATION

在编译命令行中定义符号常量的好处是,不必修改源文件就能改变由符号常量控制的行为。

五、警告功能

当GCC在编译过程中检查出错误的话,它 就会中止编译;但检测到警告时却能继续编译生成可执行程序,

因为警告只是针对程序结构的诊断信息,它不能说明程序一定有错误,而是存在风险,或者可能存在 错误。

虽然GCC提供了非常丰富的警告,但前提是你已经启用了它们,否则它不会报告这些检测到的警告。

在众多的警告选项之中,最常用的就是-Wall选项。该选项能发现程序中一系列的常见错误警告,

该选项用法举例如下:

$ gcc -Wall test.c -o test

该选项相当于同时使用了下列所有的选项:

◆unused-function:遇到仅声明过但尚未定义的静态函数时发出警告。
◆unused-label:遇到声明过但不使用的标号的警告。
◆unused-parameter:从未用过的函数参数的警告。
◆unused-variable:在本地声明但从未用过的变量的警告。
◆unused-value:仅计算但从未用过的值得警告。
◆Format:检查对printf和scanf等函数的调用,确认各个参数类型和格式串中的一致。
◆implicit-int:警告没有规定类型的声明。
◆implicit-function-:在函数在未经声明就使用时给予警告。
◆char-subscripts:警告把char类型作为数组下标。这是常见错误,程序员经常忘记在某些机器上char有符号。
◆missing-braces:聚合初始化两边缺少大括号。
◆Parentheses:在某些情况下如果忽略了括号,编译器就发出警告。
◆return-type:如果函数定义了返回类型,而默认类型是int型,编译器就发出警告。

同时警告那些不带返回值的 return语句,如果他们所属的函数并非void类型。
◆sequence-point:出现可疑的代码元素时,发出报警。
◆Switch:如果某条switch语句的参数属于枚举类型,但是没有对应的case语句使用枚举元素,

编译器就发出警告(在switch语句中使用default分支能够防止这个警告)。

超出枚举范围的case语句同样会导致这个警告。
◆strict-aliasing:对变量别名进行最严格的检查。
◆unknown-pragmas:使用了不允许的#pragma。
◆Uninitialized:在初始化之前就使用自动变量。

需要注意的是,各警告选项既然能使之生效,当然也能使之关闭。比如假设我们想要使用-Wall来启用个选项,

同时又要关闭unused警告,利益通过下面的命令来达到目的:

$ gcc -Wall -Wno-unused test.c -o test

下面是使用-Wall选项的时候没有生效的一些警告项:

◆cast-align:一旦某个指针类型强制转换时,会导致目标所需的地址对齐边界扩展,编译器就发出警告。

例如,某些机器上只能在2或4字节边界上访问整数,如果在这种机型上把char *强制转换成int *类型,

编译器就发出警告。
◆sign-compare:将有符号类型和无符号类型数据进行比较时发出警告。
◆missing-prototypes :如果没有预先声明函数原形就定义了全局函数,编译器就发出警告。

即使函数定义自身提供了函数原形也会产生这个警告。这样做的目的是检查没有在头文件中声明的全局函数。
◆Packed:当结构体带有packed属性但实际并没有出现紧缩式给出警告。
◆Padded:如果结构体通过充填进行对齐则给出警告。
◆unreachable-code:如果发现从未执行的代码时给出警告。
◆Inline:如果某函数不能内嵌(inline),无论是声明为inline或者是指定了-finline-functions 选项,

编译器都将发出警告。
◆disabled-optimization:当需要太长时间或过多资源而导致不能完成某项优化时给出警告。

上面是使用-Wall选项时没有生效,但又比较常用的一些警告选项。

本文中要介绍的最后一个常用警告选项是-Werror。使用该选项后,

GCC发现可疑之处时不会简单的发出警告就算完事,而是将警告作为一个错误而中断编译过程。

该选项在希望得到高质量代码时非常有用。

六、小结

本文介绍了GCC的基本编译过程和编译模式,并详细阐述了GCC的一些常用选项以及警告功能。

这些是在利用GCC进行应用编程时最基本也最常用的一些内容。


分享到:
评论

相关推荐

    gcc编译器常识介绍

    从程序员的角度看,只需简单地执行一条GCC命令就可以了,但从编译器的角度来看,却需要完成一系列非常繁杂的工作。首先,GCC需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句...

    linux -vi-gcc 命令

    包含vi编辑器的常用命令,同时还有gcc编译器的常用命令,适合初学linux系统的学者使用,中文解释。

    linux学习Gcc命令

    linux编译器GCC命令,常用的一些例子,适合初学者学习

    Windows上的GCC编译器

    Windows上的GCC编译器,很实用,虽然兼容性没有微软的好,但微软IDE是收费的,编译器命令也是看不见的。这个编译器很好用,部分Win32 API可能会出问题,编译器环境变量已配置好,直接运行StartStinging.bat用编译...

    Linux上gcc编译器详细

    从程序员的角度看,只需简单地执行一条GCC命令就可以了,但从编译器的角度来看,却需要完成一系列非常繁杂的工作。首先,GCC需要调用预处理程序 cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句...

    arm-linux-gnueabihf-gcc编译器

    Linux编译器 交叉编译

    linux上的C-C++编译器gcc-egcs详解

    linux上的C-C++编译器gcc-egcs详解 使用GCC很有必要

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

    2004年4月20日最新版本的GCC编译器3.4.0发布了。目前,GCC可以用来编译 C/C++、FORTRAN、JAVA、OBJC、ADA 等语言的程序,可根据需要选择安装支持的语言。GCC 3.4.0比以前版本更好地支持了C++标准。本文以在Redhat ...

    linux系统编译器gcc的rpm包

    gcc的rpm安装包,使用rpm命令快速安装

    GCC 参考手册 Linux下的c编译器

    Linux下的c编译器 包含大量gcc命令,参数选项及详细描述

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

    Linux 中最重要的软件开发工具是 GCC.GCC是 GNU的 C和 C++编译器。实际上,GCC 能够编译三种语言:C 、C++ 和ObjectC (C 语言的一种面向对象扩展)。利用 gcc命令可同时编译并连接 C和 C++源程序。

    IDE集成GCC编译器的方法

    为了缩短基于Windows平台的嵌入式软件IDE的... 以及后台编译命令执行进程到前台界面显示进程的单管道设计,实现GNU GCC 从Linux 到Windows的移植,以及编译器编译信息的实时显示,为IDE 的编译器集成提供一条有效的捷径

    docker-alpine-gcc:使用C编译器(GCC)的最小Docker映像(101MB)

    } ' > qq.c$ docker run --rm -v ` pwd ` :/tmp frolvlad/alpine-gcc gcc --static /tmp/qq.c -o /tmp/qq 运行这些命令后,您将在当前目录中拥有qq可执行文件,如果执行该命令,则会显示“ Hello World”!

    cl tcc gcc编译器

    本资源机集成了tcc gcc cl三个编译器,在dos命令行下面使用,方便初学者。

    gcc常用命令

    基于linux开发环境的gcc编译器常用的命令概述。

    MinGw gcc编译器

    解压完MinGW.7z文件后,配置完环境变量,编写一个c/c++程序hello.c/hello.cpp原代码,cmd进入windows命令行后,cd进入到当前hello.c或hello.cpp源代码所在路劲下,使用...这个东西还可以作为CodeBlocks的gcc编译器用。

    gcc命令 GUN C/C++编译器

    gcc命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点。 现在很多程序员都应用gcc,目前gcc可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言...

    GCC使用手册及常用命令行.doc

    GCC使用手册及常用命令行 gcc编译器的各种命令

    GCC命令详解

    gcc包含的c/c++编译器 gcc,cc,c++,g++,gcc和cc是一样的,c++和g++是一样的,一般c程序就用gcc编译,c++程序就用g++编译 2。gcc的基本用法 gcc test.c这样将编译出一个名为a.out的程序 gcc test.c -o test这样将编译...

    gcc使用教程 讲解gcc

    Linux 中最重要的软件开发工具是 GCC。GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 Object C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++ 源程序。

Global site tag (gtag.js) - Google Analytics