GCC常用选项使用详解

通常所说的GCC是GUN 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等。

本系列文章中,我们不仅介绍GCC的基本功能,还涉及到一些诸如优化之类的高级功能。另外,我们还考察GCC的一些映像操作工具,如size和objcopy等,这将在后续的文章中加以介绍。

二、程序的编译过程

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

     

从功能上分,预处理、编译、汇编是三个不同的阶段,但GCC的实际操作上,它可以把这三个步骤合并为一个步骤来执行。下面我们以C语言为例来谈一下不同阶段的输入和输出情况。

在预处理阶段,输入的是C语言的源文件,通常为*.c。它们通常带有.h之类头文件的包含文件。这个阶段主要处理源文件中的#ifdef、 #i nclude和#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

需要注意的是,要生成可执行程序时,一个程序无论有有一个源文件还是多个源文件,所有被编译和连接的源文件中必须有且仅有一个mai n函数,因为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的调试和优化技术。
该命令将同时编译三个源文件,即first.c、second.c和 third.c,然后将它们连接成一个可执行程序,名为test。

附录:

[参数详解]     
   -x    language    filename       
         设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根     
         据约定c语言的后缀名称是.c的,而c++的后缀名是.c或者.cpp,如果     
         你很个性,决定你的c代码文件的后缀名是.pig    哈哈,那你就要用这     
         个参数,这个参数对他后面的文件名都起作用,除非到了下一个参数     
         的使用。     
         可以使用的参数吗有下面的这些     
           `c,    `objective-c,    `c-header,    `c++,    `cpp-output,       
           `assembler,    and    `assembler-with-cpp.     
         看到英文,应该可以理解的。     
         例子用法:     
         gcc    -x    c    hello.pig     
          
   -x    none    filename     
     关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型     
     例子用法:     
     gcc    -x    c    hello.pig    -x    none    hello2.c     
          
   -c       
     只激活预处理,编译,和汇编,也就是他只把程序做成obj文件     
     例子用法:     
     gcc    -c    hello.c     
     他将生成.o的obj文件       
    
   -s     
     只激活预处理和编译,就是指把文件编译成为汇编代码。     
     例子用法     
     gcc    -s    hello.c     
     他将生成.s的汇编代码,你可以用文本编辑器察看     
    
   -e     
     只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里     
     面.     
     例子用法:     
     gcc    -e    hello.c    >    pianoapan.txt     
     gcc    -e    hello.c    |    more     
     慢慢看吧,一个hello    word    也要与处理成800行的代码     
    
   -o     
     制定目标名称,缺省的时候,gcc    编译出来的文件是a.out,很难听,如果     
     你和我有同感,改掉它,哈哈     
     例子用法     
     gcc    -o    hello.exe    hello.c    (哦,windows用习惯了)     
     gcc    -o    hello.asm    -s    hello.c     
    
   -pipe     
     使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问     
     题     
     gcc    -pipe    -o    hello.exe    hello.c     
    
   -ansi     
     关闭gnu    c中与ansi    c不兼容的特性,激活ansi    c的专有特性(包括禁止一     
     些asm    inline    typeof关键字,以及unix,vax等预处理宏,     
    
   -fno-asm     
     此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作     
     关键字。     
            
   -fno-strict-prototype     
     只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式     
     的对参数的个数和类型说明,而不是没有参数.     
     而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说     
     明的类型     
          
   -fthis-is-varialble     
     就是向传统c++看齐,可以使用this当一般变量使用.     
          
   -fcond-mismatch     
     允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型     
          
   -funsigned-char     
   -fno-signed-char     
   -fsigned-char     
   -fno-unsigned-char     
     这四个参数是对char类型进行设置,决定将char类型设置成unsigned    char(前     
     两个参数)或者    signed    char(后两个参数)     
          
   -include    file     
     包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以     
     用它设定,功能就相当于在代码中使用#include<filename>     
     例子用法:     
     gcc    hello.c    -include    /root/pianopan.h     
          
   -imacros    file     
     将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件     
     中     
          
   -dmacro     
     相当于c语言中的#define    macro     
          
   -dmacro=defn     
     相当于c语言中的#define    macro=defn     
          
   -umacro     
     相当于c语言中的#undef    macro     
    
   -undef     
     取消对任何非标准宏的定义     
          
   -idir     
     在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头     
     文件,如果没有找到,他回到缺省的头文件目录找,如果使用-i制定了目录,他     
     回先在你所制定的目录查找,然后再按常规的顺序去找.     
     对于#include<file>,gcc/g++会到-i制定的目录查找,查找不到,然后将到系     
     统的缺省的头文件目录查找     
          
   -i-     
     就是取消前一个参数的功能,所以一般在-idir之后使用     
          
   -idirafter    dir     
     在-i的目录里面查找失败,讲到这个目录里面查找.     
          
   -iprefix    prefix     
   -iwithprefix    dir     
     一般一起使用,当-i的目录查找失败,会到prefix+dir下查找     
          
   -nostdinc     
     使编译器不再系统缺省的头文件目录里面找头文件,一般和-i联合使用,明确     
     限定头文件的位置     
          
   -nostdin    c++     
     规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创建     
     libg++库使用     
          
   -c     
     在预处理的时候,不删除注释信息,一般和-e使用,有时候分析程序,用这个很     
     方便的     
          
   -m     
     生成文件关联的信息。包含目标文件所依赖的所有源代码     
     你可以用gcc    -m    hello.c来测试一下,很简单。     
          
   -mm     
     和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。     
          
   -md     
     和-m相同,但是输出将导入到.d的文件里面     
          
   -mmd     
     和-mm相同,但是输出将导入到.d的文件里面     
          
   -wa,option     
     此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选     
     项,然后传递给会汇编程序     
          
   -wl.option     
     此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选     
     项,然后传递给会连接程序.     
          
    
   -llibrary       
     制定编译的时候使用的库     
     例子用法     
     gcc    -lcurses    hello.c     
     使用ncurses库编译程序     
          
   -ldir     
     制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然     
     编译器将只在标准库的目录找。这个dir就是目录的名称。     
          
   -o0     
   -o1     
   -o2     
   -o3     
     编译器的优化选项的4个级别,-o0表示没有优化,-o1为缺省值,-o3优化级别最     
     高       
          
   -g     
     只是编译器,在编译的时候,产生条是信息。     
          
   -gstabs     
     此选项以stabs格式声称调试信息,但是不包括gdb调试信息.     
          
   -gstabs+     
     此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息.     
          
   -ggdb     
     此选项将尽可能的生成gdb的可以使用的调试信息. 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454848.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 井字棋 人机_井字游戏 人机对战 java实现

package com.ecnu.Main;/*** 主函数触发游戏*/public class MainApplication {public static void main(String[] args){TicTacToeGame ticTacToeGame new TicTacToeGame();ticTacToeGame.start();}}//TicTacToeGame 方法类import java.util.Scanner;public class TicTacToeGa…

Session(数据)共享的前后端分离Shiro实战

1&#xff0c;前言本文期望描述如何使用Shiro构建基本的安全登录和权限验证。本文实战场景有如下特殊需求&#xff1a;1&#xff0c;在集群和分布式环境实现session共享&#xff1b;2&#xff0c;前端只使用HTML/CSS/JS。因此无法直接使用Shiro提供的SessionManager&#xff0c…

读书笔记(javascript 高级程序设计)

一. 数据类型&#xff1a; 1. undefined&#xff1a; 未声明和未初始化的变量&#xff0c;typeof 操作符返回的结果都是 undefined&#xff1b;&#xff08;建议未初始化的变量进行显式赋值&#xff0c;这样当 typeof 返回 undefined 时就知道是未声明了&#xff0c;帮助定位问…

关于gcc扩展中的宏定义中用 # 和 ##

关于gcc扩展中的宏定义中用 "#" 和 "##"今天测试了宏定义中的 "#" 和 "##" 的区别。 结果如下&#xff1a; "#" 代表和一个字符串相连接 "##" 代表和一个符号连接&#xff0c;符号可以是变量&#xff0c;或另一…

java 年计算_java实现计算某年某月的天数

在计算某年某月的天数时&#xff0c;需要注意平年闰年。分析&#xff1a;闰年具体的判定方法就要看它的判定条件&#xff1a;四年一闰 &#xff0c; 百年不闰 &#xff0c;400年再闰。而计算该年该月的天数&#xff0c;又分大月和小月&#xff0c;特殊月份2月之分。(视频教程推…

添加自定义菜单,报错40155

2019独角兽企业重金招聘Python工程师标准>>> 提交的json中&#xff0c;某个自定义菜单对应的URL访问是有问题的&#xff0c;请挨个检查一下。 转载于:https://my.oschina.net/selly1025/blog/1551496

gcc编译流程及中间表示层RTL的探索

gcc编译流程及中间表示层RTL的探索收藏新一篇: 解读VC编程中的文件操作API和CFile类 | 旧一篇: Effective Item21 尽可能使用const 内容摘要 本文将以 C 语言为例&#xff0c;介绍 gcc 在接受一个 .c文件的输入之后&#xff0c;其前端是如何进行处理并得到一个中间表示并转交给…

【bzoj2132】圈地计划 网络流最小割

题目描述 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解&#xff0c;这块土地是一块矩形的区域&#xff0c;可以纵横划分为NM块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根据不同的地形环境&#xff0c;每…

python爬虫爬取数据如何将br去掉_Python怎么去除爬取下来的网站中的一些转义字符串 - 收获啦...

基本方法其实用python爬取网页很简单&#xff0c;只有简单的几句话这样就可以获得到页面的内容。接下来再用正则匹配去匹配所需要的内容就行了。但是&#xff0c;真正要做起来&#xff0c;就会有各种各样的细节问题。2.登录这是一个需要登录认证的网站。也不太难&#xff0c;只…

Linux基础

Linux的特点&#xff1a; 系统版本&#xff1a;常见的有debian、Redhat更适合做服务器&#xff0c;更安全和稳定&#xff0c;Ubuntu唯一的优势就是图形界面好&#xff0c;centos目前被redhat收购&#xff0c;红旗已经倒闭。 1、免费的/开源的&#xff1b;2、支持多线程/多用户&…

GCC的编译和调试--入门介绍

编译与调试1.1编译的概念和理解在进行C程序开发时&#xff0c;编译就是将编写的C语言代码变成可执行程序的过程&#xff0c;这一过程是由编译器来完成的。编译器就是完成程序编译工作的软件&#xff0c;在进行程序编译时完成了一系列复杂的过程。1.1.1程序编译的过程在执行这一…

A* a=new B ,会不会产生内存泄露了,露了B-A的部分?

A* anew B ,delete a;会不会产生内存泄露了&#xff0c;露了B-A的部分。其中B为A的子类 析构函数在下边3种情况时被调用&#xff1a;1.对象生命周期结束&#xff0c;被销毁时&#xff1b;2.delete指向对象的指针时&#xff0c;或delete指向对象的基类类型指针&#xff0c;而其基…

spring 第一天:1015

对象加强的三种方法&#xff1a;1/继承2/装饰着模式3/动态调用 2&#xff1a;装饰着模式&#xff1a;就是就是1-先建一个基类 &#xff0c;如咖啡类 。味道很苦2- 再建一个类配料类 也就是说是所欲配料种类的父类。然后写多配料子类个子类继承配料类&#xff0c;。3-子类三个步…

java public 继承_java继承问题

代码&#xff1a;父类&#xff1a;public class Father {public Father() {System.out.println("基类构造函数{");show();new a();System.out.println("}");}public void show() {System.out.println("基类----show");}public class a {public a…

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数(数位DP+恶心细节)

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 Time Limit: 5 Sec Memory Limit: 64 MBDescription 正如你所知&#xff0c;奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺序。她们甚至也不能通过仍硬币的方式。 所以她们通过"round number&q…

Optimizing Code with GCC

现在的编译器越来越聪明&#xff0c;功能越来越强&#xff0c;从简单的函数内联&#xff0c;到复杂的寄存器分析&#xff0c;一系列代码革命使程序运行得越来越快。大多数时候&#xff0c;更快比更小重要&#xff0c;因为磁盘空间和内存都变得便宜了。但是在嵌入式系统里&#…

QTP的那些事--操作excel的函数

1: QTP Excel函数 操作EXCEL 数据表格 表单 编辑EXCEL 工作表 2: Dim ExcelApp As Excel.Application 3: Dim excelSheet As Excel.worksheet 4: Dim excelBook As Excel.workbook 5: Dim fso As scrīpting.FileSystemObject 6: 7: ******************…

java-生产者消费者模式

经常会有公司叫我们手撕代码&#xff0c;比如网易&#xff0c;阿里&#xff0c;那我们是不是该掌握下呢。下面这段代码来自《现代操作系统》进程与线程P49页。 public class ProducerConsumer {public ProducerConsumer() { }private static final int N 100;static Producer …

yum查询已经安装mysql_通过yum安装mysql

在linux中安装数据库首选MySQL&#xff0c;Mysql数据库的第一个版本就是发行在Linux系统上&#xff0c;其他选择还可以有postgreSQL&#xff0c;oracle等在Linux上安装mysql数据库&#xff0c;我们可以去其官网上下载mysql数据库的rpm包&#xff0c;http://dev.mysql.com/downl…

koa2-cookie-session

node.js的path.extname方法使用   由于该方法属于path模块&#xff0c;使用前需要引入path模块&#xff08;var path require(“path”) &#xff09;   接收参数&#xff1a;   p path 路径 path.extname(index.html)// returns.htmlpath.extname(index.)// returns.pat…