`
xinklabi
  • 浏览: 1562788 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
文章分类
社区版块
存档分类
最新评论

C/C++编译过程理解

阅读更多

标准CC++将编译过程定义为9个阶段(Phases of Translation)

 

1.字符映射(Character Mapping)

    文件中的物理源字符被映射到源字符集中,其中包括三字符运算符的替换、控制字符(行尾的回车换行)的替换。许多非美式键盘不支持基本源字符集中的一些字符,文件中可用三字符来代替这些基本源字符,以??为前导。但如果所用键盘是美式键盘,有些编译器可能不对三字符进行查找和替换,需要增加-trigraphs编译参数。在C++程序中,任何不在基本源字符集中的字符都被它的通用字符名替换。

 

2.行合并(Line Splicing)

    以反斜杠\结束的行和它接下来的行合并。

 

3.标记化(Tokenization)

    每一条注释被一个单独的空字符所替换。C++双字符运算符被识别为标记(为了开发可读性更强的程序,C++为非ASCII码开发者定义了一套双字符运算符集和新的保留字集)。源代码被分析成预处理标记。

 

4.预处理(Preprocessing)

    调用预处理指令并扩展宏。使用#include指令包含的文件,重复步骤14。上述四个阶段统称为预处理阶段。

 

5.字符集映射(Character-set Mapping)

    源字符集成员、转义序列被转换成等价的执行字符集成员。例如:'\a'ASCII环境下会被转换成值为一个字节,值为7

 

6.字符串连接(String Concatenation)

    相邻的字符串被连接。例如:"""hahaha""huohuohuo"将成为"hahahahuohuohuo"

 

7.翻译(Translation)

    进行语法和语义分析编译,并翻译成目标代码。

 

8.处理模板

    处理模板实例。

 

9.连接(Linkage)

 

理解:

    解决外部引用的问题,准备好程序映像以便执行。

l        一直对这块内容都很怵头,因为它看不到摸不着,我们只能盯着最后编译链接之后的结果是成功或是失败,但是却不知道编译器内部是如何操作的;

l        每当编译器给出错误时我们都只是单纯的去处理错误,却不知道编译器是如何找出来的;

l        我们都很熟悉许多编译错误,但是却不大熟悉链接错误,对链接错误产生的原因也不大清楚。

 

今天,通过自己的努力终于对C/C++的编译过程有了个粗略的了解,毕竟不想去翻《编译原理》这样的大部头书籍,但是又急于对编译的过程有个大概的了解,唉,这么多年来一直在苦苦挣扎,今天总算是对这个过程有了个大概的了解了。下面就说说我了解到的一些东西:

    
首先是预编译,这一步可以粗略的认为只做了一件事情,那就是宏展开,也就是对那些#***的命令的一种展开,例如define MAX 1000就是建立起MAX1000之间的对等关系,好在编译阶段进行替换。例如ifdef/ifndef就是从一个文件中有选择性的挑出一些符合条件的代码来交给下一步的编译阶段来处理。这里面最复杂的莫过于include了,其实也很简单,就是相当于把那个对应的文件里面的内容一下子替换到这条include***语句的地方来。

其次是编译,这一步很重要,编译是以一个个独立的文件作为单元的,一个文件就会编译出一个目标文件。(这里插入一点关于编译的文件的说明,编译器通过后缀名来辨识是否编译该文件,因此“.h”的头文件一概不理会,而“.cpp”的源文件一律都要被编译,我实验过把.h文件的后缀名改为.cpp,然后在include的地方相应的改为***.cpp,这样一来,编译器就会编译许多不必要的头文件,只不过头文件里我们通常只放置声明而不是定义,因此最后链接生成的可执行文件的大小是不会改变的)清楚编译是以一个个单独的文件为单元的,这一点很重要,因此编译只负责本单元的那些事,而对外部的事情一概不理会,在这一步里,我们可以调用一个函数而不必给出这个函数的定义,但是要在调用前得到这个函数的声明(其实这就是include的本质,不就是为了给你提前提供个声明而好让你使用吗?至于那个函数到底是如何实现的,需要在链接这一步里去找函数的入口地址。因此提供声明的方式可以是用include把放在别的文件中的声明拿过来,也可以是在调用之前自己写一句void max(int,int);都行。),编译阶段剩下的事情就是分析语法的正确性之类的工作了。好啦,总结一下,可以粗略的认为编译阶段分两步:第一步,检验函数或者变量是否存在它们的声明;第二步,检查语句是否符合C++语法。

 

最后一步是链接,它会把所有编译好的单元全部链接为一个整体文件,其实这一步可以比作一个连线的过程,比如A文件用了B文件中的函数,那么链接的这一步会建立起这个关联。链接时最重要的我认为是检查全局空间里面是不是有重复定义或者缺失定义。这也就解释了为什么我们一般不在头文件中出现定义,因为头文件有可能被释放到多个源文件中,每个源文件都会单独编译,链接时就会发现全局空间中有多个定义了。

分享到:
评论

相关推荐

    高级C/C++编译技术(英文原版)

    米兰·斯特瓦诺维奇编著的这本《高级c/c++编译技术》从多个角度全面、系统地讲解多任务操作系统中编译、链接、装载与库的内幕和技术细节,为深入理解和掌握系统底层技术提供详实参考和实践指南。与纯粹讲解理论与...

    C/C++头文件重编译的深度理解和剖析

    C/C++头文件重编译的深度理解和剖析,是个人理解,绝对原创,和网络上流传的那些绝对不一样,我曾经在此部分花了相当的时间进行研究,希望大家指正

    DevCpp-C/C++语言编译开发工具

    它是一个免费开源的软件,提供了一套工具和功能,方便开发者编写、调试和编译C和C++程序。Dev-C++具有简单易用的界面和直观的功能,适合初学者和有经验的开发者使用。 Dev-C++适用于学生、教育机构、自学者和专业...

    C/C++语言做的五子棋源码 完全可以使用

    C/C++语言做的五子棋,使用了类的思想,程序内核比较清晰易懂 并且完全通过编译,工程量小,易于理解 比较适合期末C++实验的完成

    C/C++程序员面试指南.杨国祥(带详细书签).pdf

    面试题18:简述C、C++程序编译的内存分配情况 面试题19:以下四段代码中哪段没有错误 第6章 字符串 6.1 数字字符串 面试题1:编码实现数字转化为字符串 面试题2:编码实现字符串转化为数字 6.2 字符串函数 面试题3:...

    C/C++笔试题(附答案,华为面试题系列)

    答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变 量和函数是按照C语言方式编译和连接的。由于编译后的名字不同,C++程序不能直接调 用C 函数。C++提供了一个C 连接交换指定符号...

    编译原理 - 词法分析:C/C++实现

    词法分析是编译过程中的第一个阶段,其主要目标是将源代码分割成称为“词法单元”的基本单元,例如标识符、关键字、操作符、常量等。词法分析器(也称为词法扫描器)负责识别源代码中的这些词法单元,并将它们转化为...

    C/C++语言贪吃蛇在VC6.0和VC2010环境下运行

    在设计这个程序中我主要学会了如何运用以下有关C语言和C/C++的知识 1)函数定义是要做到顾名思义是很重要的,它对读程序的人正确认识程序 十分重要,在修改这个程序的过程中也能很快找到程序各模块的作用,大大增 加...

    C/C++音视频实战-gb28181系列-pjsip-sip栈-h264安防流媒体服务器

    1、搞音视频必须有扎实的C/C++开发语言基础、 JNI基础,学会如何交叉编译 FFmpeg 等 C/C++库; 2、其次,我们需要阅读大量的音视频规范/协议文档(如H264、MP4/FLV、RTP/RTCP等)。这些文档中的内容基本都以位为单位...

    编译原理 - LR(1)分析法:C/C++实现

    它是一种强大的自底向上语法分析方法,适用于具有一定复杂性的上下文无关文法,通过使用向前查看符号来处理文法中的二义性,使得可以更精确地分析和理解输入。 在实验的代码实现过程中,定义了ACTION表和GOTO表,这...

    跨平台C_C++解释计算平台Ch_的教学魅力

    本文介绍的Ch是一个面向交互式教学的跨平台C/C++解释计算环境,是一个完整的C语言解释器,支持最新C语言标准C99中大部分的新增特性以及C++的类,由交互式命令外壳(command shell)和教学专用且界面友好的集成开发环境...

    编译原理 - 逆波兰式的产生及计算:C/C++实现

    相比传统的中缀表达式,逆波兰式更容易被计算机程序理解和处理。 通过这次实验,我实现了逆波兰式的产生及计算代码,并对逆波兰式的原理和实现有了更加深入的理解。 逆波兰式通过将操作符放在操作数的后面来表示...

    桂林电子科技大学编译原理课程设计

    完整的编译原理课程设计,C++编写,可以运行,有注释,也有实验报告可以参考,非常全,关键是也很好理解。

    c/c++ 学习总结 初学者必备

    如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,由于“指向指针的指针”这个概念不容易理解,我们也可以用函数返回值来传递动态内存。 常常有人把return语句用错了。这里强调不要用return语句...

    基于C++实现的语法分析程序代码

    以前课程设计做的C++的语法分析程序,功能比较简单,有详细注释,容易理解

    c/c++基础编程资源(包含“网红代码,爱心,窗口轰炸等等”)

    该套件可跟随本作者发布的博客来理解和引用,里面不仅有本作者发布的全部资源,还有未发布的代码资源,其中有c++重点之一《通讯录管理系统》,本套资源还可随黑马程序员课程相合并理解。该套资源包含了本人入门到...

    C 的优化汇编代码.doc

    其实在不同的C/C++编译器中,由同样的C/C++代码编译成的汇编(机器)代码是不同的。主要讨论Microsoft Visual C++.Net编译器生成的机器代码。Visual C++不同版本的编译器生成的代码没有什么大的区别,这些在讨论后面...

    ARM汇编实现流水灯,STM32F103,COTEX-M3系列指令

    不仅仅理解学会如何使用ARM汇编进行实际操作,而且可以很容易的了解STM32F103系列芯片的时钟构造,学会灵活配置系统时钟,AHB总线时钟,APB1,APB2时钟,并且可以完整的学习GPIO的配置原理和工作原理,可以说汇编语言...

    编译原理词法分析器与语法分析器源代码&实验报告

    本资源包括了编译原理这门课程所要求的两次实验——编写词法分析器和语法分析器的源代码及实验报告,对于没有头绪的同学们是一个很好的参考,可以有效的帮助你们打开思路

Global site tag (gtag.js) - Google Analytics