标签:style blog io color ar 使用 sp 文件 div
GCC(GNU C Compile)是Linux下标准的C编译器,能够编译C,C++ ,Object C 等多种语言,并且GCC支持夸平台编译,即在当前的CPU平台为不同的硬件平台和体系结构开发软件。(以下本文中所用GCC 版本为4.8.2,ubuntu14.02)
(1)安装GCC
sudo apt-get install gcc
安装后查看gcc版本命令: gcc -v
(2)程序编译原理
GCC编译器的命令格式:
gcc [options] [filenames]
为了更加深刻的记忆gcc的命令,了解程序的编译原理是有必要的。对于GCC编译器来说,程序编译需要经过以下四个阶段:
预处理(Pre-Processing)
编译(Compiling)
汇编(Assemling)
连接(Linking)
下面详细介绍这四个阶段:
预处理阶段是由GCC的预处理器(CPP)完成,其作用是将宏的求值,条件编译以及其他需要将代码传递到编译器前的工作,通常所见的 # 号后面的语句由CPP来进行处理。
执行:
gcc -o hello.i -E hello.c
以下为hello.i文件的部分内容:
# 1 "hello.c" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "hello.c" # 1 "/usr/include/stdio.h" 1 3 4 # 27 "/usr/include/stdio.h" 3 4 # 1 "/usr/include/features.h" 1 3 4 # 374 "/usr/include/features.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 # 385 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 # 386 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 # 375 "/usr/include/features.h" 2 3 4 # 398 "/usr/include/features.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4 # 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4 # 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4 # 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 # 399 "/usr/include/features.h" 2 3 4 # 28 "/usr/include/stdio.h" 2 3 4 .... # 2 "hello.c" 2 int main() { printf("Hello! This is our embedded world!n"); return 0; }
由此可见,CPP将stdio.h文件中的内容插入到hello.i文件中,即预处理。
编译
GCC在编译阶段会进行如下工作:检查代码的规范性以及语法的错误,确定代码实际要完成的任务,在确定无误后将C语言翻译成汇编语言,且并不将汇编语言转化为二进制代码。在此阶段,程序若出现错误,此种错误被称为编译错误。
执行:
gcc -o hello.s -S hello.i
以下为hello.a的部分内容:
.file "hello.c" .section .rodata .LC0: .string "hello world! " .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %edi call puts popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main
汇编(Assembling)
汇编阶段是把编译生成的”.s”文件转成目标二进制代码。
执行
gcc -o hello.o -c hello.s
连接
在成功编译之后,就进入了链接阶段。在这里涉及到一个重要的概念:函数库。
读者可以重新查看这个小程序,在这个程序中并没有定义”printf”的函数实现,且在预编译中包含进的”stdio.h”中也只有该函数的声明, 而没有定义函数的实现,那么,是在哪里实现”printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为libc.so.6的库文件中去了, 在没有特别指定时,Gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函 数”printf”了,而这也就是链接的作用。
函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要 库文件了。其后缀名一般为”.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这 样可以节省系统的开销。动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。Gcc在编译时默认使用动态库。
标签:style blog io color ar 使用 sp 文件 div
原文地址:http://www.cnblogs.com/feifeifei/p/4070942.html