GCC起步
gcc标准(一)
gcc标准(一)GCC标准什么是GCC标准?GCC(GNU Compiler Collection)是一套由GNU开发的开源编程语言编译器套装。
它支持多种编程语言,包括C、C++、Objective-C、Fortran、Java和Ada等。
GCC标准是指GCC所遵循的编程语言标准和规范。
GCC标准的历史1.1987年:第一个GCC版本发布,支持C语言。
2.1991年:GCC开始支持C++语言。
3.2005年:版本发布,开始支持Objective-C和Fortran语言。
4.2006年:版本发布,开始支持Ada语言。
5.2010年:GCC开始支持Go语言。
6.2013年:版本发布,开始支持OpenACC和OpenMP语言扩展。
支持的编程语言GCC标准支持多种编程语言,包括:•C语言•C++语言•Objective-C语言•Fortran语言•Ada语言•Java语言•Go语言GCC标准的特性GCC标准具有以下特性:1.可移植性:GCC标准在多个平台上都能很好地工作,包括Linux、Windows、macOS等。
2.高度优化:GCC标准使用先进的优化算法,可以生成高效的机器码。
3.丰富的扩展:GCC标准支持各种编程语言的扩展,可以满足不同开发需求。
4.广泛使用:GCC标准是许多项目的首选编译器,被广泛应用于开源项目、商业项目等领域。
5.活跃的社区:GCC标准有一个庞大而活跃的社区,提供持续的维护和更新。
GCC标准的版本更新GCC标准不断进行版本更新,以提供更好的功能和性能。
以下是一些重要的GCC版本更新:•GCC :引入了Graphite优化框架,提供更好的循环优化能力。
•GCC :引入了支持C++0x标准的特性,如Lambda表达式和右值引用。
•GCC :引入了支持OpenACC和OpenMP语言扩展,使并行编程更加便捷。
•GCC :引入了对C11和C++14标准的支持。
如何使用GCC标准?要使用GCC标准进行编程,可以按照以下步骤:1.安装GCC标准:下载并安装GCC标准的最新版本,可以从官方网站或操作系统的软件仓库中获得。
gcc的使用方法
gcc的使用方法GCC(GNU Compiler Collection)是一款由GNU开发的编程语言编译器集合,支持多种编程语言,如C、C++、Fortran等。
它被广泛用于各种操作系统和硬件平台上的软件开发,提供了强大的功能和灵活的配置选项。
本文将介绍GCC的基本使用方法,帮助读者快速上手。
一、安装GCC要使用GCC,首先需要在您的计算机上安装它。
GCC可以在多个操作系统上运行,包括Linux、Windows和Mac OS。
具体的安装方法因操作系统而异,下面将分别介绍。
1. 在Linux上安装GCC:在大多数Linux发行版中,GCC已经默认安装。
如果您的系统中没有安装GCC,您可以通过包管理器来安装它。
例如,在Debian或Ubuntu系统上,可以使用以下命令安装GCC:```sudo apt-get install gcc```其他Linux发行版的安装方法请参考相应的文档。
2. 在Windows上安装GCC:在Windows上,可以通过MinGW或MSYS2来安装GCC。
这两个工具集提供了一种在Windows环境中使用GCC的方式。
您可以从官方网站上下载并按照安装向导进行安装。
3. 在Mac OS上安装GCC:在Mac OS上,可以使用Homebrew或MacPorts来安装GCC。
这两个软件包管理系统可以让您以与Linux相似的方式在Mac OS上安装软件。
例如,使用Homebrew安装GCC的命令如下:```brew install gcc```其他安装方法请参考相应文档。
二、编写源代码安装好GCC后,我们就可以开始编写源代码了。
GCC支持多种编程语言,但本文以C语言为例进行介绍。
打开任何文本编辑器,创建一个后缀名为.c的文件,并编写您的C 源代码。
例如,创建一个名为`hello.c`的文件,其中包含以下代码:```c#include <stdio.h>int main() {printf("Hello, world!\n");return 0;}```三、编译和运行代码一旦您编写好了源代码,接下来就可以使用GCC将其编译成可执行文件。
linux的gcc使用方法
linux的gcc使用方法Linux是一种开源的操作系统,广泛应用于服务器和嵌入式系统中。
而GCC(GNU Compiler Collection)是Linux下最常用的编译器套件之一,用于将源代码编译成可执行文件。
本文将介绍GCC的使用方法,帮助读者快速上手。
一、安装GCC在Linux系统中,默认情况下已经安装了GCC。
可以通过运行以下命令来验证是否已经安装了GCC:```gcc --version```如果GCC已经安装,则会显示GCC的版本信息;如果没有安装,则可以通过运行以下命令来安装GCC:```sudo apt-get install gcc```二、编写源代码在使用GCC之前,我们需要先编写源代码。
可以使用任何文本编辑器创建一个以.c为后缀的源文件,例如hello.c。
下面是一个示例的源代码:```c#include <stdio.h>int main() {printf("Hello, world!\n");return 0;}```三、编译源代码编写完源代码后,我们可以使用GCC来将其编译成可执行文件。
在终端中运行以下命令:```gcc -o hello hello.c```其中,-o参数用于指定编译后生成的可执行文件的名称,hello为示例的可执行文件名,hello.c为源代码文件名。
如果编译成功,GCC将会生成一个名为hello的可执行文件。
四、运行可执行文件在编译成功后,我们可以通过以下命令来运行可执行文件:```./hello```如果一切顺利,终端将会输出"Hello, world!"的字符串。
五、GCC的其他常用选项除了上述基本的使用方法外,GCC还提供了许多其他的选项,用于控制编译过程的行为。
以下是一些常用的选项:- -Wall:开启所有警告信息的显示。
- -g:生成供调试器使用的调试信息。
- -O2:进行优化处理,提高程序执行效率。
gcc 用法
gcc 用法GCC (GNU Compiler Collection) 是一套自由软件编译器,可以用于编译多种编程语言的源代码,包括 C、C++、Objective-C、Fortran、Ada 和其他一些语言。
GCC 是GNU计划的一部分,由自由软件基金会维护和发展。
本文将详细介绍 GCC 的使用方法。
一、环境准备在使用GCC之前,需要先安装好GCC。
GCC是开源软件,常见的Linux发行版都默认安装GCC,Windows下可以通过安装Cygwin或MinGW等方式安装GCC。
安装完成后,在命令行中输入gcc --version查看gcc的版本号确认是否安装成功。
除了GCC之外,还需要一个文本编辑器来编写源代码。
Windows下常用的文本编辑器有Notepad++,Linux下则使用vim或emacs等编辑器。
还需要了解一些基本的编程知识和语法。
二、GCC 编译 C 语言程序以下是一个简单的 C 语言程序,可以输出 "Hello, world!":```c#include <stdio.h>printf("Hello, world!\n");return 0;}```将上述代码保存为 helloworld.c 文件,然后在命令行中进入文件所在目录,输入以下命令编译该程序:```gcc helloworld.c -o helloworld```gcc是编译器的命令,helloworld.c是待编译的源代码文件名,-o helloworld是生成的可执行文件名。
执行上述命令后,GCC 会把源代码编译成可执行文件 helloworld。
运行该可执行文件,可以得到以下输出:```Hello, world!```三、GCC 编译 C++ 程序GCC 也可以编译 C++ 程序,以下是一个简单的 C++ 程序,可以输出 "Hello,world!":```c++#include <iostream>std::cout << "Hello, world!" << std::endl;return 0;}```将上述代码保存为 helloworld.cpp 文件,然后在命令行中进入文件所在目录,输入以下命令编译该程序:```g++ helloworld.cpp -o helloworld```g++是编译器的命令,helloworld.cpp是待编译的源代码文件名,-o helloworld是生成的可执行文件名。
gcc ld编译过程
gcc ld编译过程gcc和ld是GNU工具链中的两个重要组成部分,用于编译和链接程序。
编译过程分为四个主要阶段:预处理、编译、汇编和链接。
1. 预处理(Preprocessing):在这个阶段,编译器会对源代码进行一些预处理操作,例如宏展开、头文件包含等。
预处理的结果是一个包含了所有宏展开和文件包含的扩展源代码文件,通常以".i"或者".ii"作为文件扩展名。
2. 编译(Compiling):在这个阶段,编译器将预处理后的源代码翻译成汇编语言。
它首先进行词法分析和语法分析,生成一个中间表示(通常是一种称为抽象语法树的数据结构),然后进行语义分析和优化,最终将代码转换成汇编语言。
编译的结果是一个以".s"作为文件扩展名的汇编语言文件。
3. 汇编(Assembling):在这个阶段,汇编器将汇编语言代码翻译成机器语言指令。
它会读取汇编语言文件,将每条汇编指令转换成对应的二进制机器指令,并生成一个以".o"作为文件扩展名的目标文件。
4. 链接(Linking):在这个阶段,链接器将多个目标文件和库文件合并成一个可执行文件。
它会处理符号引用和重定位等问题,解析函数和变量的定义和引用关系,并生成最终的可执行文件。
链接的结果可以是一个可执行文件或者一个共享库文件(动态链接库),其文件扩展名可以是".out"、".exe"或者".so"。
ld(链接器)是负责链接的工具,在编译过程中由gcc自动调用。
它负责解析目标文件中的符号引用,连接不同的目标文件和库文件,解析重定位信息,最终生成可执行文件。
ld 还可以实现各种链接选项,如链接器脚本、库搜索路径等,以实现更灵活的链接过程。
总之,gcc和ld是GNU工具链中非常重要的两个组件,通过编译和链接过程将源代码转换成可执行文件。
gcc 编译流程
gcc 编译流程gcc 是一种常用的编译器,被广泛应用于程序开发和编译过程中。
在了解 gcc 编译流程之前,我们先简单介绍一下编译的基本概念。
编译是将高级语言(如C、C++ 等)编写的源代码转换为机器语言(如汇编代码或机器指令)的过程。
编译器是用来进行编译的工具,而 gcc 就是其中较为常用的一个。
gcc 是GNU Compiler Collection(GNU 编译器集合)的缩写,它是一个由GNU 开发的自由软件项目,也是许多Unix-like 系统中默认的编译器。
gcc 支持多种编程语言,包括C、C++、Objective-C、Objective-C++、Fortran、Ada 等。
这里我们以C 语言为例,来介绍 gcc 的编译流程。
gcc 的编译过程可以分为四个主要阶段:预处理、编译、汇编和链接。
下面将详细介绍这四个阶段的具体操作和作用。
1. 预处理阶段:在预处理阶段,gcc 将源代码中的预处理指令进行处理,生成预处理后的代码。
预处理指令以"#" 开头,如"#include"、"#define" 等。
预处理的主要作用是对源代码进行宏替换、文件包含和条件编译等操作,以生成经过宏展开和文件合并后的代码。
2. 编译阶段:在编译阶段,gcc 将预处理后的代码转换为汇编代码。
汇编代码是一种与机器相关的低级语言,它是由一系列的机器指令组成。
编译的主要任务是对源代码进行词法分析、语法分析和语义分析等操作,以生成对应的汇编代码。
3. 汇编阶段:在汇编阶段,gcc 将汇编代码转换为机器代码。
机器代码是二进制的指令序列,可以被计算机直接执行。
汇编的主要作用是将汇编代码翻译成机器指令,生成可执行文件。
4. 链接阶段:在链接阶段,gcc 将多个源文件编译生成的目标文件进行链接,生成最终的可执行文件。
链接的主要作用是解决函数调用和变量引用等符号之间的关系,将多个目标文件合并成一个可执行文件。
gcc编译过程的四个阶段
gcc编译过程的四个阶段1. 预处理(Preprocessing):预处理是编译过程的第一阶段。
预处理器负责对原始源文件进行处理,主要完成以下几个任务:-处理宏定义:预处理器会将源文件中的宏定义展开为相应的代码片段,并将其保存在一个临时文件中。
-处理条件编译指令:预处理器会根据条件编译指令的结果决定是否包含或排除一些代码片段。
- 处理#include指令:预处理器会将源文件中的#include指令所引用的其他文件插入到该指令所在的位置。
-移除注释:预处理器会删除源文件中的注释。
预处理后的文件成为扩展名为.i的中间文件,它包含了所有宏定义及展开后的代码。
编译是编译过程的第二阶段。
编译器将预处理生成的中间文件进行词法分析、语法分析和语义分析,生成相应的汇编代码。
主要过程如下:- 词法分析器将预处理生成的中间文件分解为一个个的词法单元(Token)。
- 语法分析器根据词法单元组织成的语法结构,生成抽象语法树(Abstract Syntax Tree,AST)。
-语义分析器对抽象语法树进行语义检查,包括类型检查和语义错误检查,确保程序的语义正确。
编译器将生成的汇编代码保存为扩展名为.s的汇编文件。
3. 汇编(Assembling):汇编是编译过程的第三阶段。
汇编器(Assembler)将编译器生成的汇编代码翻译成机器码,并生成目标文件。
具体过程如下:- 汇编器将汇编代码中的每一条汇编指令翻译成对应的机器码,同时为每个标号(Label)生成对应的地址。
-汇编器进行符号解析,将代码中引用的变量和函数与目标文件中的符号表进行匹配,生成正确的指令和地址。
汇编器将目标文件保存为扩展名为.o的目标文件。
4. 链接(Linking):链接是编译过程的最后阶段。
链接器(Linker)将目标文件与其他必要的库文件进行合并,生成最终的可执行文件或动态链接库。
主要过程如下:-链接器将目标文件中的函数和变量引用与其他目标文件中的定义进行匹配,解析外部引用,生成相应的引用表。
gcc -e 条件编译
GCC -e 条件编译GCC(GNU Compiler Collection)是一个广泛使用的编译器,支持多种编程语言,包括C、C++、Fortran等。
在GCC 中,-e选项可以用于指定入口点函数,也就是程序执行的起点。
入口点函数是程序中第一个被调用的函数,通常在程序的入口点设置了程序执行的开始。
1. 默认入口点默认情况下,GCC将程序的入口点设置为main函数。
因此,如果你没有特别指定入口点,编译器会默认将程序的执行起点设置为main函数。
以下是一个简单的示例程序,展示了默认入口点的使用:#include<stdio.h>int main() {printf("Hello, world!\n");return0;}在这个示例中,程序的入口点是main函数,当程序执行时,它首先调用main函数,并从这里开始执行。
2. 条件入口点GCC的-e选项允许你通过指定一个条件入口点来改变程序的执行起点。
这个选项允许你在编译时根据特定条件选择不同的入口点。
这对于实现条件编译非常有用,可以根据不同的编译选项或配置选择不同的代码路径。
下面是一个示例程序,展示了如何使用-e选项指定条件入口点:#include<stdio.h>void condition_entry() {printf("This is the condition entry point.\n");}int main() {printf("This is the main entry point.\n");return0;}编译命令如下:gcc -e condition_entry my_program.c -o my_program在这个示例中,我们通过指定-e condition_entry选项将程序的入口点设置为condition_entry函数。
当程序执行时,它将首先调用condition_entry函数,而不是默认的main函数。
gcc的四个步骤
gcc的四个步骤第一步:预处理预处理是GCC的第一个步骤,也是代码编译过程的第一步。
在预处理阶段,预处理器将根据一些特殊的预处理指令,对源代码进行一系列的处理,包括宏扩展、头文件包含、条件编译等等。
预处理的目的是提前处理一些不会因代码中的变化而改变的内容,为后续的编译步骤做准备。
预处理器首先会替换代码中的宏定义,将宏名称替换为其对应的宏代码。
然后进行头文件包含,将头文件中的内容插入到源文件中。
预处理器还会处理条件编译指令,根据条件对代码进行选择性编译。
最后生成一个经过预处理的中间文件,供下一步的编译使用。
第二步:编译编译是GCC的第二个步骤,也是代码编译过程的核心。
在编译阶段,编译器将预处理得到的中间文件进一步处理,将其转换为汇编语言代码。
编译器会对代码进行一系列的语法分析、语义分析、优化等操作,以保证代码的正确性和性能。
语法分析是指编译器对源代码进行词法分析和语法分析,将代码分解为基本的语法单元,并构建语法树。
语义分析是指编译器对语法树进行类型检查、语义检查等操作,确保代码的合法性和一致性。
优化是指编译器对代码进行一系列的优化操作,以提高代码的执行效率。
编译器将经过处理的代码转换为汇编语言代码,并生成一个汇编语言文件,作为下一步的汇编过程的输入。
第三步:汇编汇编是GCC的第三个步骤,也是代码编译过程的重要一环。
在汇编阶段,汇编器将编译得到的汇编语言文件进行处理,将其转换为机器码或者可重定位文件。
汇编器将汇编语言代码按照特定的指令格式和地址方式进行翻译,生成与特定处理器架构相兼容的机器码。
汇编器首先会解析汇编语言指令,将其转换为二进制机器码指令。
然后将地址符号转换为实际地址,生成指令和数据的链接关系。
最后生成一个与目标处理器兼容的机器码文件或可重定位文件。
第四步:链接链接是GCC的最后一个步骤,也是代码编译过程的最后一环。
在链接阶段,链接器将多个汇编产生的可重定位文件进行处理,将其合并成一个单一的可执行文件。
gcc基本命令
gcc基本命令概述GCC(GNU Compiler Collection)是一套由GNU开发的编译器集合,用于开发各种编程语言的应用程序。
它支持多种编程语言,包括C、C++、Objective-C、Fortran、Ada和Go等。
GCC编译器具有广泛的功能和强大的优化能力,被广泛应用于软件开发领域。
本文将介绍GCC的一些基本命令,帮助初学者快速入门并提高编程效率。
常用命令1. gccgcc命令用于将源代码编译成可执行文件。
其基本语法为:gcc [选项] [文件名]例如,要编译名为hello.c的C程序文件,可以使用以下命令:gcc hello.c -o hello2. g++g++是GCC的C++编译器。
与gcc类似,g++将C++源代码编译成可执行文件。
其基本语法为:g++ [选项] [文件名]例如,要编译名为hello.cpp的C++程序文件,可以使用以下命令:g++ hello.cpp -o hello3. gcc -cgcc -c命令用于将源代码编译成目标文件(Object File),而不生成可执行文件。
其基本语法为:gcc -c [选项] [文件名]例如,要将名为hello.c的C程序文件编译成目标文件,可以使用以下命令:gcc -c hello.c -o hello.o4. gcc -Egcc -E命令用于对源代码进行预处理,并将预处理结果输出到标准输出或指定的文件中。
其基本语法为:gcc -E [选项] [文件名]例如,要对名为hello.c的C程序文件进行预处理并输出到标准输出,可以使用以下命令:gcc -E hello.c5. gcc -ogcc -o命令用于指定生成的可执行文件的名称。
其基本语法为:gcc [选项] [文件名] -o [输出文件名]例如,要将名为hello.c的C程序文件编译成名为myhello的可执行文件,可以使用以下命令:gcc hello.c -o myhello6. gcc -Wallgcc -Wall命令用于开启所有警告信息。
gcc编译器使用方法
gcc编译器使用方法一、介绍:GCC(GNU Compiler Collection)是一套由GNU开发的编程语言编译器集合,支持多种编程语言,如C、C++、Objective-C、Fortran、Ada等。
在Linux系统中,GCC是最常用的编译器之一,本文将详细介绍GCC编译器的使用方法。
二、安装GCC编译器:在Linux系统中,GCC编译器通常已经预装。
可以通过以下命令检查GCC是否已经安装:```gcc --version```如果GCC已安装,则会显示其版本信息;如果未安装,则需要通过包管理器进行安装,例如在Ubuntu系统中,可以使用以下命令安装GCC:```sudo apt-get install gcc```三、编译C程序:GCC编译器可以用来编译C程序,以下是一个简单的例子:```c#include <stdio.h>int main() {printf("Hello, World!\n");return 0;}```将上述代码保存为hello.c文件,然后使用以下命令编译:```gcc hello.c -o hello```其中,hello.c是源文件的名称,-o指定输出文件的名称,这里将输出文件命名为hello。
编译成功后,可以执行生成的可执行文件:```./hello```输出结果将是:```Hello, World!```四、编译C++程序:GCC编译器也可以用来编译C++程序,以下是一个简单的例子:```cpp#include <iostream>int main() {std::cout << "Hello, World!" << std::endl;return 0;}```将上述代码保存为hello.cpp文件,然后使用以下命令编译:```g++ hello.cpp -o hello```其中,hello.cpp是源文件的名称,-o指定输出文件的名称,这里将输出文件命名为hello。
初次接触GCC因此花费了我不少时间搞了半天加一个晚上终于能编译
初次接触GCC因此花费了我不少时间,搞了半天加一个晚上终于能编译成功了!^_^先是安装《PN的配置与GCC 入门》操作了一遍,没有成功,之后在论坛了找啊找啊,找了hotpower的一篇文档,两者一结合,ok了,呵呵。
为了更好的方便象我一样的初学者,现在把我操作的一系列步骤写下来,给初学者一个参考。
1、安装WinA VR, 我按照其默认的状态安装的。
(省力省心,^_^)2、打开Programmers Notepad,先不要着急新建什么工程,编写什么程序。
按照《PN的配置与GCC 入门》配置一下字体显示和一些工具。
我配置的工具如下:小弟用的是双龙的下载软件。
当然在配置Makefile Wizard 时,要把C:\WinAVR\bin目录下的wish84.exe,tcl84.dll,tk84.dll三个文件复制到C:\WinAVR\mfile目录下,然后用PN打开该目录下的mfile.tcl文件,并按照下图修改。
如果WinAVR不是按默认目录安装的,假如安装到了D:/program/ 下,则上图中圈中的地方要改为set prefix “D:/program/WinAVR/mfile/”.同样工具配置的第一幅图中command和parameters 栏都要改到相应的目录下面。
以上配置基本完成,下面进入实战阶段。
3、在Programmers Notepad中,点击File->new->project 新建一工程项目,可取名为test.pnproj 如图4、 新建文件,点击File->New->Default,5、 在编辑区内编写自己的程序代码,并保存到刚才新建Project 的目录下面,取名为test.c 记住一定要保“.c ”的格式,否则没有语法显示。
之后整个界面如下所示:我所加的代码是我随便找的,代码是马老师的SPI主机的发送和接收一个字节的程序。
(做了一点修改)代码如下:#include <avr/io.h>#include <stdio.h>#include <avr/signal.h>#include <avr/interrupt.h>//#define unsigned char uchar#define SIZE 100unsigned char SPI_rx_buff[SIZE];unsigned char SPI_tx_buff[SIZE];unsigned char rx_wr_index,rx_rd_index,rx_counter,rx_buffer_overflow;unsigned char tx_wr_index,tx_rd_index,tx_counter,SPI_ok;unsigned char t10mscnt;unsigned char t500mscnt;unsigned char senddata;void mcu_ini(void){unsigned char temp;cli();MCUCR = 0x00; //disable all interruptsDDRA=0xff;PORTA=0x00;DDRC=0xff;PORTC=0x00;DDRD=0xff;PORTD=0x00;TCCR0 = 0x00; //stopTCNT0 = 0x06; //set count 250usOCR0 = 0x64; //set compareTCCR0 = 0x02; //start timerDDRB |= 0xBF; //MISO=input and MOSI,SCK,SS = outputPORTB |= 0x40; //MISO上拉电阻有效SPCR = 0xD5; //SPI允许,主机模式,MSB,允许SPI中断,极性方式01,1/16系统时钟速率SPSR = 0x00;temp = SPSR;temp = SPDR; //清空SPI,和中断标志,使SPI空闲SPI_ok = 1;MCUCR = 0x00;GICR = 0x00;TIMSK = 0x01; //timer interrupt sourcessei(); //re-enable interrupts}//#pragma interrupt_handler timer0_ovf_isr:10SIGNAL(SIG_OVERFLOW0){//250usTCNT0 = 0x06; //reload counter valueif(++t10mscnt>=40){t10mscnt=0;if(++t500mscnt>=50){senddata++;if(senddata>=16)senddata=0;t500mscnt=0;}}}//===========================//#pragma interrupt_handler master_spi_isr:11SIGNAL(SIG_SPI){SPI_rx_buff[rx_wr_index] = SPDR; //从ISP口读出收到的字节SPI_ok = 1; // SPI 空闲if (++rx_wr_index == SIZE) rx_wr_index = 0; //放入接收缓冲区,并调整队列指针if (++rx_counter == SIZE){rx_counter = 0;rx_buffer_overflow = 1; //接收缓冲区溢出}if (tx_counter) //如果发送缓冲区中有待发的数据tx_counter==0表示没有数据要发送{--tx_counter;SPDR = SPI_tx_buff[tx_rd_index]; //发送一个字节数据,并调整指针if (++tx_rd_index == SIZE)tx_rd_index = 0;SPI_ok = 0;}}//----------------------------------------unsigned char getSPIchar(void){unsigned char data;while (rx_counter == 0); //无接收数据,等待data = SPI_rx_buff[rx_rd_index]; //从接收缓冲区取出一个SPI收到的数据if (++rx_rd_index == SIZE)rx_rd_index = 0; //调整指针cli();--rx_counter;sei();return data;}//------------------------------------------void putSPIchar(char c){while (tx_counter == SIZE);//发送缓冲区满,等待cli();if (tx_counter || SPI_ok==0 ) //发送缓冲区已中有待发数据{ //或SPI正在发送数据时SPI_tx_buff[tx_wr_index] = c; //将数据放入发送缓冲区排队if (++tx_wr_index == SIZE)tx_wr_index = 0; //调整指针++tx_counter;}else{SPDR = c; //发送缓冲区中空且SPI口空闲,直接放入SPDR由SIP口发送SPI_ok = 0; //}sei();}//--------------------------------------------/*void spi_init(void){unsigned char temp;DDRB |= 0xB0; //MISO=input and MOSI,SCK,SS = outputPORTB |= 0xB0; //MISO上拉电阻有效SPCR = 0xD5; //SPI允许,主机模式,MSB,允许SPI中断,极性方式01,1/16系统时钟速率SPSR = 0x80;temp = SPSR;temp = SPDR; //清空SPI,和中断标志,使SPI空闲SPI_ok = 1;}*///---------------------------------------------------int main(void){unsigned char i;i=0;mcu_ini();//CLI(); //关中断//spi_init(); //初始化SPI接口//SEI(); //开中断while(1){putSPIchar(i); //发送一个字节//i++;putSPIchar(i++);putSPIchar(i++);getSPIchar(); //接收一个字节(第一个字节为空字节)getSPIchar();getSPIchar();//………}}6、至此代码别写完成,(呵呵,抄来的,别抽我)接下来就要做编译了。
gcc编译c++程序的过程
GCC(GNU Compiler Collection)是一个开源的编译器,支持多种编程语言,包括C、C++、Objective-C、Fortran、Ada等。
下面是使用GCC编译C++程序的一般步骤:
1. **编写源代码**:首先,你需要编写C++源代码文件,通常以`.cpp`为扩展名。
2. **预处理**:GCC首先会进行预处理,这一步会处理源文件中的预处理指令,比如#include、#define等。
GCC会扩展这些指令,并将结果输出到临时文件。
3. **编译**:接下来,GCC会将预处理后的代码进行编译。
编译是将源代码转换成机器代码的过程。
在这一步中,GCC会将C++代码转换成汇编语言。
4. **汇编**:然后,GCC会使用汇编器将上一步生成的汇编代码转换成目标文件(通常是`.o`文件)。
5. **链接**:最后,GCC会进行链接步骤。
链接是将目标文件和所需的库文件合并成一个可执行文件的过程。
在这个过程中,GCC还会处理符号引用和地址解析等问题。
如果你在命令行中运行GCC编译C++程序,可以使用如下命令:
```bash
gcc -o output_file source_file.cpp
```
其中,`-o`选项用于指定输出文件的名称,`source_file.cpp`是源代码文件的名称。
在编译完成后,GCC会生成一个名为`output_file`的可执行文件。
需要注意的是,GCC还支持许多其他选项和参数,可以用来优化编译过程、控制警告和错误处理等。
你可以通过运行`gcc --help`命令来查看所有可用的选项和参数。
gcc的使用方法
gcc的使用方法
gcc是一个编译器,它可以将文本类文件翻译成机器可以执行的二进制可执行文件。
使用gcc的方法包括以下步骤:
1.编写源代码:使用文本编辑器编写C语言源代码文件,通常以.c为扩展
名。
2.打开终端:在Linux或Mac OS X系统中打开终端应用程序,或者在
Windows系统中打开命令提示符。
3.进入源代码目录:使用cd命令进入存放源代码文件的目录。
4.编译源代码:输入gcc命令并附加选项和参数来编译源代码文件。
例
如,使用以下命令编译名为myfile.c的源代码文件:gcc myfile.c -o myfile。
其中,-o选项指定输出文件的名称为myfile。
5.运行可执行文件:如果编译成功,将生成一个可执行文件。
在Linux或
Mac OS X系统中,使用./myfile命令来运行可执行文件。
在Windows系统中,直接双击可执行文件即可运行。
另外,gcc还有很多选项和参数可用于优化代码、指定编译器警告级别、链接库文件等。
这些选项和参数可以在gcc命令中使用,并且可以通过查阅gcc文档来了解更多信息。
除了单个源文件的编译,gcc还可以用于编译多个源文件组成的程序。
在这种情况下,可以使用一条gcc命令来编译所有源文件并生成可执行文件。
以上是关于gcc使用方法的描述,希望对你有所帮助。
linux开发工具的使用gcc实验总结简短
linux开发工具的使用gcc实验总结简短在Linux开发中,GCC是一个广泛应用的编译器套件,为程序员提供了丰富的工具和功能,方便进行开发和调试。
本文将为大家总结一下使用GCC进行实验的经验与技巧。
一、安装GCC在开始使用GCC之前,首先需要安装GCC编译器。
在大多数Linux发行版中,GCC已经预安装,可以直接使用。
如果没有安装,可以通过包管理器进行安装,例如在Ubuntu上可以使用以下命令进行安装:```sudo apt-get install gcc```二、编写和编译源代码1. 创建源代码文件使用任意文本编辑器,创建一个以.c为扩展名的源代码文件,例如hello.c。
2. 编写源代码在源代码文件中,可以使用C语言来编写程序。
下面是一个简单的示例代码:```c#include <stdio.h>int main() {printf("Hello, World!\n");return 0;}```3. 编译源代码打开终端,进入源代码所在的目录,使用以下命令进行编译:```gcc hello.c -o hello```其中,`hello.c`是源代码文件的名称,`hello`是生成的可执行文件的名称。
通过`-o`选项指定输出文件名。
三、运行和调试程序1. 运行程序编译成功后,可以直接运行生成的可执行文件。
在终端输入以下命令运行程序:```./hello```程序将会输出`Hello, World!`。
2. 调试程序GCC也提供了强大的调试功能,方便程序员进行调试和排错。
可以通过使用`-g`选项来编译生成带有调试信息的可执行文件:```gcc -g hello.c -o hello-debug```然后,可以使用`gdb`命令来启动调试器,并加载可执行文件进行调试:```gdb hello-debug```调试器提供了许多命令和功能,可以帮助你定位和修复代码中的问题。
gcc编译器的编译流程
gcc编译器的编译流程GCC编译器是一款广泛使用的开源编译器,支持多种编程语言,如C、C++、Java等。
GCC的编译流程可以大致分为预处理、编译、汇编和链接四个阶段。
下面将详细介绍这四个阶段的具体内容。
1. 预处理阶段在预处理阶段,GCC会对源代码进行预处理,主要包括以下几个步骤:(1) 删除注释:GCC会将所有注释删除,以便后续处理。
(2) 处理宏定义:GCC会将所有宏定义进行替换,以便产生中间代码。
(3) 处理条件编译语句:GCC会根据条件编译语句的条件进行编译或者忽略。
(4) 处理头文件:GCC会将所有头文件包含到源代码中,以便后续处理。
2. 编译阶段在编译阶段,GCC会将预处理后的源代码翻译成汇编代码,主要包括以下几个步骤:(1) 词法分析:GCC会将源代码分解成一个个单词。
(2) 语法分析:GCC会根据语法规则对单词进行组合,生成语法树。
(3) 语义分析:GCC会对语法树进行类型检查和语义分析。
(4) 中间代码生成:GCC会将语法树转换成中间代码。
3. 汇编阶段在汇编阶段,GCC会将中间代码转化成机器码,主要包括以下几个步骤:(1) 汇编器生成符号表:GCC会在生成汇编代码时生成符号表,以便后续的链接。
(2) 汇编器生成目标文件:GCC会将中间代码转换成汇编代码,并生成目标文件。
4. 链接阶段在链接阶段,GCC会将目标文件和库文件链接成可执行文件,主要包括以下几个步骤:(1) 符号解析:GCC会将目标文件中的符号解析成实际的地址。
(2) 符号重定位:GCC会根据符号的实际地址将目标文件中的符号进行重定位。
(3) 库文件链接:GCC会将目标文件和库文件进行链接,生成可执行文件。
综上所述,GCC编译器的编译流程包括预处理、编译、汇编和链接四个阶段。
每个阶段都有其特定的功能,最终生成可执行文件。
gcc编译过程简述
gcc编译过程简述在linux系统上,从源⽂件到⽬标⽂件的转化是由编译器完成的。
以hello.c程序的编译为例,如下:dfcao@linux: gcc -o hello hello.c在这⾥,gcc编译器读取源⽂件hello.c,并把它翻译成⼀个可执⾏⽂件 hello。
这个翻译过程可分为四个阶段逐步完成:预处理,编译,汇编,链接,如下图所⽰。
逐步做下简单分析:在未编译前,hello.c 的源代码如下#include <stdio.h>int main(){printf("hello, world\n");}第⼀步、预处理阶段执⾏命令: gcc -o hello.i -E hello.c 或者 cpp -o hello.i hello.c (这⾥cpp不值c plus plus,⽽是预处理器the C Preprocessor)预处理器cpp根据以字符开头#开头的命令,修改原始C程序。
⽐如hello.c中的第⼀⾏为 #include <stdio.h>,预处理器便将stdio.h的内容直接插⼊到程序中。
预处理之后得到⽂本⽂件hello.i,打开如下# 1"hello.c"# 1"<built-in>"# 1"<命令⾏>"# 1"hello.c"# 1"/usr/include/stdio.h"134.........extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));# 940"/usr/include/stdio.h"34# 2"hello.c"2int main(){printf("hello, world\n");}在源代码的前⾯插⼊了stdio.h,整个hello.i 的⾏数由hello.c的6⾏变到了855⾏!第⼆步、编译阶段执⾏命令: gcc -o hello.s -S hello.i 或者 ccl -o hello.s hello.i编译器ccl 将⽂本⽂件hello.i 翻译为hello.s,这个⽂件⾥⾯包含⼀个汇编程序,如下.file "hello.c".section .rodata.LC0:.string "hello, world".text.globl main.type main, @functionmain:.LFB0:.cfi_startprocpushl %ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl %esp, %ebp.cfi_def_cfa_register 5andl $-16, %espsubl $16, %espmovl $.LC0, (%esp)call putsleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE0:.size main, .-main.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3".section .note.GNU-stack,"",@progbits汇编语⾔是⾮常有⽤的,因为它将不同⾼级语⾔的不同编译器提供了通⽤的输出语⾔。
gcc编译c文件并运行的方法
gcc编译c文件并运行的方法GCC是一款广泛使用的编译器,可用于编译多种编程语言,包括C语言。
它是一个开源软件,可以在多种平台上使用,如Linux、Windows和Mac OS等。
GCC编译器可以将C语言程序源代码编译为计算机可以执行的机器代码,这些机器代码可以在计算机上直接运行。
本文将介绍如何使用GCC编译C语言程序,并在计算机上运行它们。
步骤1:安装GCC编译器要使用GCC编译C语言程序,首先需要安装GCC编译器。
在Linux系统上,可以使用以下命令来安装GCC:```sudo apt-get install build-essential```在Windows系统上,可以下载MinGW安装包进行安装。
MinGW(Minimalist GNU for Windows)是一套在Windows上使用GCC编译器的工具集。
在Mac OS系统上,可以使用Homebrew包管理器来安装GCC编译器。
在终端上输入以下命令:```brew install gcc```步骤2:编写C语言程序要编译和运行C语言程序,首先需要编写一个C源代码文件。
C源代码文件通常以“.c”为扩展名。
可以编写一个简单的“hello world”程序,并将其保存为“hello.c”文件。
下面是一个示例程序:```#include <stdio.h>printf("Hello, World!");return 0;}```步骤3:使用GCC编译器编译C语言程序一旦编写好了C语言程序,就可以使用GCC编译器将其编译为可执行程序。
在终端上,进入C语言程序所在目录,并使用以下命令编译程序:```gcc -o hello hello.c```在这个命令中,“-o”参数指定编译器编译完后生成的可执行文件的名称。
在本例中,编译器将生成一个名为“hello”的可执行文件。
步骤4:运行已编译的C语言程序执行上述编译命令后,GCC编译器将生成一个可执行文件。
gcc编译的四个步骤
gcc编译的四个步骤GCC是一款广泛使用的编译器套件,能够将源代码转换为可执行程序。
GCC的编译过程可以分为四个主要步骤,包括预处理、编译、汇编和链接。
这四个步骤将按照顺序讨论如下:1. 预处理(Preprocessing):预处理是 GCC 的第一个步骤,它主要处理源代码中的预处理指令,如宏定义、条件编译等。
预处理会将这些指令进行展开或替换,输出一个经过预处理的代码文件。
这个过程主要由预处理器完成,预处理器根据源代码中的预处理指令,对代码进行修改。
在预处理阶段,还会将注释删除,可以通过使用 gcc 命令的 -E 选项查看预处理结果。
编译是 GCC 的第二个步骤,它将预处理后的代码文件翻译为汇编语言代码。
在这个步骤中,编译器将会对代码进行词法分析和语法分析,生成相应的中间代码。
中间代码是一种与特定机器无关的代码表示形式,它将源代码转化为了一种抽象的表示形式,方便后续的优化和转换。
可以通过使用 gcc 命令的 -S 选项查看编译结果。
3. 汇编(Assembly):汇编是 GCC 的第三个步骤,它将编译得到的汇编代码翻译成机器代码。
在这个步骤中,汇编器将会对汇编代码进行处理,生成与特定机器相关的目标代码。
目标代码是机器代码的一种表示形式,它直接可以被计算机处理。
可以通过使用 gcc 命令的 -c 选项查看汇编结果。
4. 链接(Linking):链接是 GCC 的最后一个步骤,它将目标代码与其他代码片段进行合并,生成最终可执行程序。
在这个步骤中,链接器将会处理各个目标文件和库文件,解析各个模块之间的引用关系,将它们组合成一个完整的可执行文件。
链接还可以包括符号解析、重定位等过程,以确保最终生成的可执行程序能够正确运行。
可以通过使用 gcc 命令的 -o 选项指定生成的可执行文件名。
总结起来,GCC编译的四个主要步骤包括预处理、编译、汇编和链接。
预处理是对源代码进行预处理指令展开或替换,编译是将预处理后的代码翻译为中间代码,汇编是将编译得到的汇编代码转化为机器代码,链接是将目标代码和其他代码片段合并生成最终可执行程序。
中文gcc手册
中文gcc手册GCC(GNU Compiler Collection)是一套用于编译各种编程语言的开源编译器。
它最初由Richard Stallman创建并由GNU项目维护,成为了GNU计划的重要组成部分。
GCC支持多种编程语言,包括C、C++、Objective-C、Fortran、Ada和Go等。
它不仅可以在各种操作系统上使用,如Linux、Windows和macOS等,还可以为不同架构的处理器生成可执行文件。
例如,x86、ARM和PowerPC等。
GCC提供了广泛的优化选项,以生成高效的代码。
GCC手册提供了关于GCC的详细信息,包括GCC的安装、使用和配置等方面的内容。
一般而言,GCC手册主要包括以下几个部分:1.安装GCC:包括从官方网站下载GCC源代码、配置和编译GCC、安装GCC及其依赖项等步骤。
2. GCC命令行选项:介绍GCC的各种命令行选项,用于指定编译器行为、选择编译器版本、指定目标架构和调整编译器优化等。
3. C语言扩展:介绍GCC对C语言的扩展功能,如内置函数、语言特性和编译指令等。
4. C++语言扩展:介绍GCC对C++语言的扩展功能,如模板元编程、重载、命名空间和异常处理等。
5.编译器优化:介绍GCC的优化选项,包括代码优化原则、优化等级、循环优化、内敛和代码生成等。
6. GCC插件:介绍GCC插件的开发和使用,包括GCC插件架构、插件开发接口和实现自定义的编译器扩展等。
7. GCC内部结构:介绍GCC的内部结构和设计原理,包括前端、中间表示(IR)、优化器和后端等。
GCC手册可以帮助开发人员更好地理解和使用GCC编译器。
它提供了丰富的示例代码和实用技巧,有助于编写高效和可靠的代码。
在GCC 手册中,用户可以找到关于GCC的详细说明、使用示例和案例研究等,可用作学习GCC编译器的重要参考资料。
总之,GCC手册是一本详尽而全面的文档,为用户提供了GCC编译器的深入指导和使用示例。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
GCC起步在为Linux开发应用程序时,绝大多数情况下使用的都是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 <stdio.h>int main(void){printf ("Hello world, Linux programming!\n");return 0;}然后执行下面的命令编译和运行这段程序:# gcc hello.c -o hello# ./helloHello world, Linux programming!从程序员的角度看,只需简单地执行一条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.oGCC默认将.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 <stdio.h>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 illcodeillcode.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 illcodeillcode.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 illcodecc1: warnings being treated as errorsillcode.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代码优化代码优化指的是编译器通过分析源代码,找出其中尚未达到最优的部分,然后对其重新进行组合,目的是改善程序的执行性能.GCC提供的代码优化功能非常强大,它通过编译选项-On来控制优化代码的生成,其中n是一个代表优化级别的整数.对于不同版本的GCC来讲,n的取值范围及其对应的优化效果可能并不完全相同,比较典型的范围是从0变化到2或3.编译时使用选项-O可以告诉GCC同时减小代码的长度和执行时间,其效果等价于-O1.在这一级别上能够进行的优化类型虽然取决于目标处理器,但一般都会包括线程跳转(Thread Jump)和延迟退栈(Deferred Stack Pops)两种优化.选项-O2告诉GCC除了完成所有-O1级别的优化之外,同时还要进行一些额外的调整工作,如处理器指令调度等.选项-O3则除了完成所有-O2级别的优化之外,还包括循环展开和其它一些与处理器特性相关的优化工作.通常来说,数字越大优化的等级越高,同时也就意味着程序的运行速度越快.许多Linux程序员都喜欢使用-O2选项,因为它在优化长度、编译时间和代码大小之间,取得了一个比较理想的平衡点.下面通过具体实例来感受一下GCC的代码优化功能,所用程序如清单3所示.清单3:optimize.c#include <stdio.h>int main(void){double counter;double result;double temp;for (counter = 0;counter < 2000.0 * 2000.0 * 2000.0 / 20.0 + 2020;counter += (5 - 1) / 4) {temp = counter / 1979;result = counter;}printf("Result is %lf\n", result);return 0;}首先不加任何优化选项进行编译:# gcc -Wall optimize.c -o optimize借助Linux提供的time命令,可以大致统计出该程序在运行时所需要的时间:# time ./optimizeResult is 400002019.000000real 0m14.942suser 0m14.940ssys 0m0.000s接下去使用优化选项来对代码进行优化处理:# gcc -Wall -O optimize.c -o optimize在同样的条件下再次测试一下运行时间:# time ./optimizeResult is 400002019.000000real 0m3.256suser 0m3.240ssys 0m0.000s对比两次执行的输出结果不难看出,程序的性能的确得到了很大幅度的改善,由原来的14秒缩短到了3秒.这个例子是专门针对GCC的优化功能而设计的,因此优化前后程序的执行速度发生了很大的改变.尽管GCC的代码优化功能非常强大,但作为一名优秀的Linux程序员,首先还是要力求能够手工编写出高质量的代码.如果编写的代码简短,并且逻辑性强,编译器就不会做更多的工作,甚至根本用不着优化.优化虽然能够给程序带来更好的执行性能,但在如下一些场合中应该避免优化代码:◆程序开发的时候优化等级越高,消耗在编译上的时间就越长,因此在开发的时候最好不要使用优化选项,只有到软件发行或开发结束的时候,才考虑对最终生成的代码进行优化.◆资源受限的时候一些优化选项会增加可执行代码的体积,如果程序在运行时能够申请到的内存资源非常紧张(如一些实时嵌入式设备),那就不要对代码进行优化,因为由这带来的负面影响可能会产生非常严重的后果.◆跟踪调试的时候在对代码进行优化的时候,某些代码可能会被删除或改写,或者为了取得更佳的性能而进行重组,从而使跟踪和调试变得异常困难.调试一个功能强大的调试器不仅为程序员提供了跟踪程序执行的手段,而且还可以帮助程序员找到解决问题的方法.对于Linux程序员来讲,GDB(GNU Debugger)通过与GCC的配合使用,为基于Linux的软件开发提供了一个完善的调试环境.默认情况下,GCC在编译时不会将调试符号插入到生成的二进制代码中,因为这样会增加可执行文件的大小.如果需要在编译时生成调试符号信息,可以使用GCC的-g或者-ggdb选项.GCC在产生调试符号时,同样采用了分级的思路,开发人员可以通过在-g选项后附加数字1、2或3来指定在代码中加入调试信息的多少.默认的级别是2(-g2),此时产生的调试信息包括扩展的符号表、行号、局部或外部变量信息.级别3(-g3)包含级别2中的所有调试信息,以及源代码中定义的宏.级别1(-g1)不包含局部变量和与行号有关的调试信息,因此只能够用于回溯跟踪和堆栈转储之用.回溯跟踪指的是监视程序在运行过程中的函数调用历史,堆栈转储则是一种以原始的十六进制格式保存程序执行环境的方法,两者都是经常用到的调试手段.GCC产生的调试符号具有普遍的适应性,可以被许多调试器加以利用,但如果使用的是GDB,那么还可以通过-ggdb选项在生成的二进制代码中包含GDB专用的调试信息.这种做法的优点是可以方便GDB的调试工作,但缺点是可能导致其它调试器(如DBX)无法进行正常的调试.选项-ggdb能够接受的调试级别和-g是完全一样的,它们对输出的调试符号有着相同的影响.需要注意的是,使用任何一个调试选项都会使最终生成的二进制文件的大小急剧增加,同时增加程序在执行时的开销,因此调试选项通常仅在软件的开发和调试阶段使用.调试选项对生成代码大小的影响从下面的对比过程中可以看出来:# gcc optimize.c -o optimize# ls optimize -l-rwxrwxr-x 1 xiaowp xiaowp 11649 Nov 20 08:53 optimize (未加调试选项)# gcc -g optimize.c -o optimize# ls optimize -l-rwxrwxr-x 1 xiaowp xiaowp 15889 Nov 20 08:54 optimize (加入调试选项)虽然调试选项会增加文件的大小,但事实上Linux中的许多软件在测试版本甚至最终发行版本中仍然使用了调试选项来进行编译,这样做的目的是鼓励用户在发现问题时自己动手解决,是Linux的一个显著特色.为调试编译代码(Compiling Code for Debugging)为了使gdb 正常工作, 你必须使你的程序在编译时包含调试信息. 调试信息包含你程序里的每个变量的类型和在可执行文件里的地址映射以及源代码的行号. gdb 利用这些信息使源代码和机器码相关联.◆在编译时用-g 选项打开调试选项.gdb 基本命令gdb 支持很多的命令使你能实现不同的功能. 这些命令从简单的文件装入到允许你检查所调用的堆栈内容的复杂命令, 表27.1列出了你在用gdb 调试时会用到的一些命令. 想了解gdb 的详细使用请参考gdb 的指南页.表27.1. 基本gdb 命令.命令描述file 装入想要调试的可执行文件.kill 终止正在调试的程序.list 列出产生执行文件的源代码的一部分.next 执行一行源代码但不进入函数内部.step 执行一行源代码而且进入函数内部.run 执行当前被调试的程序quit 终止gdbwatch 使你能监视一个变量的值而不管它何时被改变.break 在代码里设置断点, 这将使程序执行到这里时被挂起.make 使你能不退出gdb 就可以重新产生可执行文件.shell 使你能不离开gdb 就执行UNIX shell 命令.gdb 支持很多与UNIX shell 程序一样的命令编辑特征. 你能象在bash 或tcsh里那样按Tab 键让gdb 帮你补齐一个唯一的命令, 如果不唯一的话gdb 会列出所有匹配的命令. 你也能用光标键上下翻动历史命令.下面还是通过一个具体的实例说明如何利用调试符号来分析错误,所用程序见清单4所示. 清单4:crash.c#include <stdio.h>int main(void){int input =0;printf("Input an integer:");scanf("%d", input);printf("The integer you input is %d\n", input);return 0;}编译并运行上述代码,会产生一个严重的段错误(Segmentation fault)如下:# gcc -g crash.c -o crash# ./crashInput an integer:10Segmentation fault为了更快速地发现错误所在,可以使用GDB进行跟踪调试,方法如下:# gdb crashGNU gdb Red Hat Linux (5.3post-0.20021129.18rh)……(gdb)当GDB提示符出现的时候,表明GDB已经做好准备进行调试了,现在可以通过run命令让程序开始在GDB的监控下运行:(gdb) runStarting program: /home/xiaowp/thesis/gcc/code/crashInput an integer:10Program received signal SIGSEGV, Segmentation fault.0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6仔细分析一下GDB给出的输出结果不难看出,程序是由于段错误而导致异常中止的,说明内存操作出了问题,具体发生问题的地方是在调用_IO_vfscanf_internal ( )的时候.为了得到更加有价值的信息,可以使用GDB提供的回溯跟踪命令backtrace,执行结果如下:(gdb) backtrace#0 0x4008576b in _IO_vfscanf_internal () from /lib/libc.so.6#1 0xbffff0c0 in ?? ()#2 0x4008e0ba in scanf () from /lib/libc.so.6#3 0x08048393 in main () at crash.c:11#4 0x40042917 in __libc_start_main () from /lib/libc.so.6跳过输出结果中的前面三行,从输出结果的第四行中不难看出,GDB已经将错误定位到crash.c中的第11行了.现在仔细检查一下:(gdb) frame 3#3 0x08048393 in main () at crash.c:1111 scanf("%d", input);使用GDB提供的frame命令可以定位到发生错误的代码段,该命令后面跟着的数值可以在backtrace命令输出结果中的行首找到.现在已经发现错误所在了,应该将scanf("%d", input);改为scanf("%d", &input);完成后就可以退出GDB了,命令如下:(gdb) quitGDB的功能远远不止如此,它还可以单步跟踪程序、检查内存变量和设置断点等.调试时可能会需要用到编译器产生的中间结果,这时可以使用-save-temps选项,让GCC将预处理代码、汇编代码和目标代码都作为文件保存起来.如果想检查生成的代码是否能够通过手工调整的办法来提高执行性能,在编译过程中生成的中间文件将会很有帮助,具体情况如下:# gcc -save-temps foo.c -o foo# ls foo*foo foo.c foo.i foo.sGCC支持的其它调试选项还包括-p和-pg,它们会将剖析(Profiling)信息加入到最终生成的二进制代码中.剖析信息对于找出程序的性能瓶颈很有帮助,是协助Linux程序员开发出高性能程序的有力工具.在编译时加入-p选项会在生成的代码中加入通用剖析工具(Prof)能够识别的统计信息,而-pg选项则生成只有GNU剖析工具(Gprof)才能识别的统计信息.最后提醒一点,虽然GCC允许在优化的同时加入调试符号信息,但优化后的代码对于调试本身而言将是一个很大的挑战.代码在经过优化之后,在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句有可能因为循环展开而变得到处都有,所有这些对调试来讲都将是一场噩梦.建议在调试的时候最好不使用任何优化选项,只有当程序在最终发行的时候才考虑对其进行优化.上次的培训园地中介绍了GCC的编译过程、警告提示功能、库依赖、代码优化和程序调试六个方面的内容.这期是最后的一部分内容.加速在将源代码变成可执行文件的过程中,需要经过许多中间步骤,包含预处理、编译、汇编和连接.这些过程实际上是由不同的程序负责完成的.大多数情况下GCC可以为Linux程序员完成所有的后台工作,自动调用相应程序进行处理.这样做有一个很明显的缺点,就是GCC在处理每一个源文件时,最终都需要生成好几个临时文件才能完成相应的工作,从而无形中导致处理速度变慢.例如,GCC在处理一个源文件时,可能需要一个临时文件来保存预处理的输出、一个临时文件来保存编译器的输出、一个临时文件来保存汇编器的输出,而读写这些临时文件显然需要耗费一定的时间.当软件项目变得非常庞大的时候,花费在这上面的代价可能会变得很沉重.解决的办法是,使用Linux提供的一种更加高效的通信方式—管道.它可以用来同时连接两个程序,其中一个程序的输出将被直接作为另一个程序的输入,这样就可以避免使用临时文件,但编译时却需要消耗更多的内存.在编译过程中使用管道是由GCC的-pipe选项决定的.下面的这条命令就是借助GCC的管道功能来提高编译速度的:# gcc -pipe foo.c -o foo在编译小型工程时使用管道,编译时间上的差异可能还不是很明显,但在源代码非常多的大型工程中,差异将变得非常明显.文件扩展名在使用GCC的过程中,用户对一些常用的扩展名一定要熟悉,并知道其含义.为了方便大家学习使用GCC,在此将这些扩展名罗列如下:.c C原始程序;.C C++原始程序;.cc C++原始程序;.cxx C++原始程序;.m Objective-C原始程序;.i 已经过预处理的C原始程序;.ii 已经过预处理之C++原始程序;.s 组合语言原始程序;.S 组合语言原始程序;.h 预处理文件(标头文件);.o 目标文件;.a 存档文件.GCC常用选项GCC作为Linux下C/C++重要的编译环境,功能强大,编译选项繁多.为了方便大家日后编译方便,在此将常用的选项及说明罗列出来如下:-c 通知GCC取消链接步骤,即编译源码并在最后生成目标文件;-Dmacro 定义指定的宏,使它能够通过源码中的#ifdef进行检验;-E 不经过编译预处理程序的输出而输送至标准输出;-g3 获得有关调试程序的详细信息,它不能与-o选项联合使用;-Idirectory 在包含文件搜索路径的起点处添加指定目录;-llibrary 提示链接程序在创建最终可执行文件时包含指定的库;-O、-O2、-O3 将优化状态打开,该选项不能与-g选项联合使用;-S 要求编译程序生成来自源代码的汇编程序输出;-v 启动所有警报;-Wall 在发生警报时取消编译操作,即将警报看作是错误;-Werror 在发生警报时取消编译操作,即把报警当作是错误;-w 禁止所有的报警.小结GCC是在Linux下开发程序时必须掌握的工具之一.本文对GCC做了一个简要的介绍,主要讲述了如何使用GCC编译程序、产生警告信息、调试程序和加快GCC的编译速度.对所有希望早日跨入Linux开发者行列的人来说,GCC就是成为一名优秀的Linux程序员的起跑线.。