学习笔记之编译和链接
2014-12-12 12:07
260 查看
#include <stdio.h>
int main(int argc,char **argv)
{
printf("hello world\n");
return 0;
}
在linux下,使用GCC来编译helloworld 程序时,只需使用最简单的命令:
& gcc hello.cpp -o a
或$ gcc hello.cpp; $./a.out
即可在屏幕上输出hello world
事实上,上述过程可以分解为4个步骤,分别是预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking),如下图所示:
1、预编译
首先是源代码文件hello.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。对于C++程序来说,它的源代码文件的扩展名可能是.cpp或.cxx,头文件的扩展名可能是.hpp,而预编译后的文件扩展名是.ii。第一步预编译后的文件扩展名是.ii。第一步预编译的过程相当于如下命令(-E表示只进行预编译):
$ gcc -E hello.c -o hello.i
或者:$ cpp hello.c > hello.i
预编译过程主要处理那些原文件中以“#”开始的预编译指令。比如"#include"、"#define"等,主要处理规则如下:
>将所有的"#define"删除,并展开所有的宏定义。
>处理所有条件预编译指令,比如"#if"、"#ifdef"、"#elif"、"#else"、"#endif"。
>处理"#include"预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能包含其它的文件。
>删除所有的注释"//"和"/**/"。
>添加行号和文件名标识,比如#2 "hello.c" 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
>保留所有#pragma 编译器指令,因为编译器需要使用。
2、编译
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后产生相应的汇编代码文件,这个过程是整个程序构建的核心部分。上例的编译部分相当于:
$ gcc -S hello.i -o hello.s
3、汇编
汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。所以汇编器的汇编过程相对于编译器比较简单,他没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。上例的汇编过程可以用汇编器as来完成:
$ as hello.s -o hello.o
或者:
$ gcc -c hello.s -o hello.o
或者使用gcc命令从C源代码文件开始,经过预编译、编译和汇编直接输出目标文件(Object File):
$ gcc -c hello.c -o hello.o
4、链接
先总结至此,后续补充.......
int main(int argc,char **argv)
{
printf("hello world\n");
return 0;
}
在linux下,使用GCC来编译helloworld 程序时,只需使用最简单的命令:
& gcc hello.cpp -o a
或$ gcc hello.cpp; $./a.out
即可在屏幕上输出hello world
事实上,上述过程可以分解为4个步骤,分别是预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking),如下图所示:
1、预编译
首先是源代码文件hello.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。对于C++程序来说,它的源代码文件的扩展名可能是.cpp或.cxx,头文件的扩展名可能是.hpp,而预编译后的文件扩展名是.ii。第一步预编译后的文件扩展名是.ii。第一步预编译的过程相当于如下命令(-E表示只进行预编译):
$ gcc -E hello.c -o hello.i
或者:$ cpp hello.c > hello.i
预编译过程主要处理那些原文件中以“#”开始的预编译指令。比如"#include"、"#define"等,主要处理规则如下:
>将所有的"#define"删除,并展开所有的宏定义。
>处理所有条件预编译指令,比如"#if"、"#ifdef"、"#elif"、"#else"、"#endif"。
>处理"#include"预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能包含其它的文件。
>删除所有的注释"//"和"/**/"。
>添加行号和文件名标识,比如#2 "hello.c" 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
>保留所有#pragma 编译器指令,因为编译器需要使用。
2、编译
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后产生相应的汇编代码文件,这个过程是整个程序构建的核心部分。上例的编译部分相当于:
$ gcc -S hello.i -o hello.s
3、汇编
汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。所以汇编器的汇编过程相对于编译器比较简单,他没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。上例的汇编过程可以用汇编器as来完成:
$ as hello.s -o hello.o
或者:
$ gcc -c hello.s -o hello.o
或者使用gcc命令从C源代码文件开始,经过预编译、编译和汇编直接输出目标文件(Object File):
$ gcc -c hello.c -o hello.o
4、链接
先总结至此,后续补充.......
相关文章推荐
- (编译-链接)-C语言学习笔记1
- 程序员的自我修养-编译,链接和库--学习笔记
- 菜鸟C++精髓学习笔记--C++程序内部执行过程(预处理、编译、链接过程的作用)
- TQ2440 学习笔记—— 29、移植U-Boot【U-Boot 的编译、链接过程】
- 链接、装载与库学习笔记(一、编译)
- 自己在linux上编译、链接、动态库和静态库的学习笔记
- linux下使用eclipse编译、链接、动态库的学习笔记
- 自己在linux上编译、链接、动态库和静态库的学习笔记
- C和指针 学习笔记-1.编译与链接
- 编译、链接学习笔记(五)动态链接
- linux学习笔记一, c语言程序的编译链接
- 自己在linux上编译、链接、动态库和静态库的学习笔记
- 编译、链接学习笔记(三)静态链接
- 编译、链接学习笔记(四)进程装载
- “程序员自我修养”学习笔记---编译链接
- [学习笔记]jsp中超级链接 中文编码处理
- JavaScript学习笔记 3-if-then 和Link Events(链接事件)
- uClinux学习笔记之二 - 将新增应用程序编译进内存镜像文件
- 对链接应用样式--Css学习笔记(四)
- Ubuntu学习笔记(1)---编译源码包