嵌入式Linux编译器GCC的使用

1、GCC概述

作为自由软件的旗舰项目,Richard Stallman在十多年前刚开始写作GCC的时候,还只是仅仅把它当作一个C程序语言的编译器,GCC的意思也只是GNU C Compiler而已。

经过了这么多年的发展,GCC已经不仅仅能支持C语言,它现在还支持Ada语言、C++语言、Java语言、Objective C语言、PASCAL语言、COBOL语言,并支持函数式编程和逻辑编程的Mercury语言等。而GCC也不再单只GNU C语言编译器的意思了,而是变成了GNU编译器家族了。

GCC的编译流程分为了4个步骤,分别为:

l          预处理(Pre-Processing)

l          编译(Compiling)

l          汇编(Assembling)

l          链接(Linking)

编译器通过程序的扩展名可分辨编写原始程序源码所用的语言,由于不同的程序所需要执行编译的步骤是不同的,因此GCC根据不同的后缀名对它们进行分别处理,下表指出了不同后缀名的处理方式:

GCC所支持后缀名解释

后缀名

所对应的语言

编译流程

.c

C原始程序

预处理、编译、汇编

.C/.cc/.cxx

C++原始程序

预处理、编译、汇编

.m

Objective-C原始程序

预处理、编译、汇编

.i

已经过预处理的C原始程序

编译、汇编

.ii

已经过预处理的C++原始程序

编译、汇编

.s/.S

汇编语言原始程序

汇编

.h

预处理文件(头文件)

(一般不出现在指令行)

.o

目标文件

链接

.a/.so

编译后的库文件

链接

2、GCC编译流程分析

GCC使用的基本语法为:

Gcc  [ option | filename ]

l          option是GCC使用时的一些选项,通过指定不同的选项GCC可以实现其强大的功能。

l          这里的filename则是GCC要编译的文件,GCC会根据用户所指定的编译选项以及所识别的文件后缀名来对编译文件进行相应的处理。

这里从编译流程的角度讲解GCC的常见使用方法。首先,这里有一段简单的C语言程序,该程序由两个文件组成,其中“hello.h”为头文件,在“hello.c”中包含了“hello.h”,其源文件如下所示。

/* hello.h */

#ifndef_HELLO_H_

#define_HELLO_H_

typedef unsigned long val32_t;

#endif

/* hello.c */

#include <stdio.h>

#include <stdlib.h>

#include "hello.h"

int main(int argc, char *argv[])

{

val32_t I = 5;

printf("hello,embedded world%d\n", i);

}

A.         预处理阶段

GCC的选项“-E”可以使编译器在预处理结束时就停止编译,选项“-o”是指定GCC输出的结果,其命令格式为如下所示。

Gcc –E –o [目标文件] [编译文件]

我们已经知道,后缀名为“.i”的文件是经过预处理的C原始程序。要注意,“hello.h”文件是不能进行编译的,因此,使编译器在预处理后停止的命令如下所示。

[root@localhost gcc]# gcc –E –o hello.i hello.c

在此处,选项‘-o’是指目标文件,而‘.i’文件为已经过预处理的C原始程序。以下列出了hello.i文件的部分内容。

#2"hello.c"2

#1"hello.h"1

typedef unsigned long val32_t;

#3"hello.c"2

int main()

{

val32_t i=5;

printf("hello,embedded world%d\n",i);

}

由此可见,GCC确实进行了预处理,它把“hello.h”的内容插入到hello.i文件中了。

B.         编译阶段

编译器在预处理结束之后,就进入编译阶段,GCC在编译阶段首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,就开始把代码翻译成汇编语言,GCC的选项“-S”能使编译器在进行完汇编之前就停止。我们已经知道,“.s”是汇编语言原始程序,因此,此处的目标文件就可设为“.s”类型。

[root@localhost gcc]# gcc –S –o hello.s hello.i

以下列出了hello.s的内容,可见GCC已经将其转化为汇编了,感兴趣的话可以分析一下这一行简单的C语言小程序用汇编代码是如何实现的。

.file"hello.c"

.section.rodata

.LC0:

.string"hello,embedded world%d\n"

.text

.globl main

.type main,@function

main:

pushl%ebp

movl%esp,%ebp

subl$8,%esp

andl$-16,%esp

movl$0,%eax

addl$15,%eax

addl$15,%eax

shrl$4,%eax

sall$4,%eax

subl%eax,%esp

movl$5,-4(%ebp)

subl$8,%esp

pushl-4(%ebp)

pushl$.LC0

call printf

addl$16,%esp

leave

ret

.size main,.-main

.section.note.GNU-stack,"",@progbits

..ident"GCC:(GNU)4.0.0 20050519(Red Hat 4.0.0-8)"

我们可以看到,这一小段C语言的程序在汇编中已经复杂很多了,这也是C语言作为所谓中级语言的优势所在。

C.         汇编阶段

汇编阶段是把编译阶段生成的“.s”文件生成目标文件,读者在此使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。如下所示。

[root@localhost gcc]# gcc –c hello.s –o hello.o

D.         链接阶段

在成功编译之后,就进入了链接阶段。在这里涉及一个重要的概念:函数库。

问题:在这个程序中并没有定义“printf”的函数实现,在预编译中包含进的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?

答案:

系统把这些函数实现都已经被放入名为libc.so.6的库文件中去了,在没有特别指定时,GCC会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。

完成了链接之后,GCC就可以生成可执行文件,其命令如下所示:

[root@localhost gcc]# gcc hello.o –o hello

运行该可执行文件,出现正确的结果。

[root@localhost gcc]# ./hello

hello,embedded world 5

Linux编译器GCC的使用相关推荐

  1. Linux编译器-gcc/g++的使用

    ★★★★★ 是小夏啊! 我们知道,当我们用像VS等这样的编译器写完代码后,会通过快捷键操作或是编译器上相应的选项来编译运行,紧接着我们一般通过控制面板来观察程序运行的结果,从而判断自己写的程序代码是否 ...

  2. 【Linux】Linux编译器gcc/g++的使用

    今天不学习,明天变垃圾. 文章目录 一.程序的翻译过程 1.预处理(1.2.3把你的代码编译成二进制代码) 2.编译(C语言 ==> 汇编语言) 3.汇编(无法被执行的二进制文件,为什么捏?) ...

  3. Linux | 编译器gcc/g++的使用【动静态库的认识】

    文章目录 一.对程序的认知 && 初识gcc 1.程序是如何诞生的? 2.gcc的初步认识 3.如何使用gcc 二.gcc逐步分析程序的翻译环境 1.预编译[进行宏替换] 2.编译[C ...

  4. 【Linux】三、Linux 环境基础及开发工具使用(上篇)|开发工具|编辑器-vim使用|sudo提升权限问题|编译器 - gcc/g++使用|项目自动化构建工构建工具-make/Makefile

    目录 一.开发工具 二.Linux编辑器 - vim使用 2.1 vim 的基本概念 2.2 vim的基本操作 2.3 vim正常模式命令集 2.4 vim末行模式命令集 2.5 简单vim配置 2. ...

  5. Linux 之 编译器 gcc/g++参数详解

    2016年12月9日16:48:53 ----------------------------- 内容目录: [介绍]  gcc and g++分别是gnu的c & c++编译器 gcc/g+ ...

  6. Day 3 Linux(目录篇 、文件操作篇 、压缩解压相关命令, 编辑器vi 、编译器gcc 、调试器gdb、 makefile工程管理器初学)

    一.目录篇: 1.文件处理命令:cp 英文原意:copy 语法:cp -rp[源文件或目录][目的目录] 源文件可以同时是多个,即同时复制到多个文件 -r 复制目录 -p保留文件属性,比如文件创建时间 ...

  7. Redhat linux 安装 gcc编译器,Gcc源码包,rpm包安装方法!

    点评:分两种情况: 先看这篇转过来的文章,俺老孙懒得写了. Linux软件安装通用思路 在Linux系统中,软件安装程序比较纷繁复杂,不过最常见的有两种: 1)一种是软件的源代码,您需要自己动手编译它 ...

  8. linux g 编译目录下,你真的了解Linux下gcc编译器的工作过程吗?

    小豆丁:老张!老张! 老张:干嘛? 小豆丁:咋啦?愁眉苦脸的,是不是又被媳妇给揍了? 老张:开玩笑,我在家那就是相当于老虎的存在,谁敢揍我! 媳妇:老张,你说啥?我没听清,你再说一遍? 老张:我是老虎 ...

  9. Linux下gcc/g++编译器gdb调试器和makefile的使用

    文章目录 一.gcc的使用 gcc选项 二.gdb的使用 三.Linux项目自动化构建工具-make/Makefile 3.1 概念 3.2 使用 3.3 原理 一.gcc的使用 首先我们知道一个C/ ...

最新文章

  1. python采用解释方式执行_Python初学(一)
  2. WinDbg调试.NET程序入门
  3. C#结合js 上传文件和删除文件(技术点有:asp.net mvc ,nhibernate,ajax等)
  4. Python基础38(进程基础)
  5. python读取大文件内容_python读取大文件
  6. 右边菜单_AI基础教程65:使用文字菜单编辑文字(七)查找字体
  7. 江苏师范大学科文学院计算机科学与技术,2019江苏师范大学科文学院专业排名...
  8. Centos6配置samba服务器并批量添加用户和文件夹
  9. android怎样降版本,Android7.0 APP降级方法
  10. mysql 查询一年中每个月份的数据量
  11. Excel模板下载(带下拉框)
  12. 每日面试】阿里巴巴 Java后端 57min
  13. DirectX和OPenGL 与 UE4 U3D的关系是什么?
  14. zkw线段树(详解)
  15. java图书管理系统这个怎么改呢
  16. AI算法之Attention机制
  17. 转载 真正解决activesync与wince5连接问题
  18. Module3:Alice in Wonderland
  19. (戒急用忍)本来是要展望2019的,没想到重点不由自主的写成了回顾前几年的事情了
  20. php实用吗,php实用小窍门

热门文章

  1. mysql right join实例_mysql left join,right join,inner join简单实例
  2. HJ0427分隔输出
  3. LabVIEW图像特征与机器视觉概念(理论篇—4)
  4. 个人销售建筑服务器,建筑个人云服务器
  5. Maven向本地仓库导入官方仓库没有的jar包
  6. Redis在CentOS 6.8中的安装方法,JAVA初级使用Redis连接池
  7. 使用Go语言遇到的“坑”收集
  8. Unity 创建2D平台游戏开发学习教程
  9. 关于CSS的长度单位及颜色表示
  10. [JSOI2008]魔兽地图