我从一辈子下来就呆在这个昏暗的地方。linux
我不明白为何程序员这么喜欢 Dark Mode,Brighten Mode 才是个人最爱。据说最近连 iphone 都开始支持 Dark Mode 了,没话讲。。。说好的毫不妥协呢?c++
我周围是熙熙攘攘的函数群,穿插着变量声明和宏定义。程序员
在咱们这里,函数是一等公民。express
固然,不光在 C++,在面向过程的 C 语言、面向对象的 Java ,尤为是在那些函数式编程的语言里,咱们都扮演着举足轻重的角色。编程
能力越大,责任越大。我和一群函数伙伴们就负责维护着程序的功能。每一个函数的一小步,合起来就是功能模块的一大步。windows
做为一门静态编译型语言,咱们不像那些解释语言同样,写完就能直接运行,而是要先通过编译这一道坎,成为机器语言,才可以运行在咱们赖以生存的机器上。iphone
这道坎不是那么好过的,再顶尖的程序员,也会在这上面栽跟头。函数式编程
放在往常,虽然程序偶尔会出 bug ,但你们齐心合力,可谓虫(bug)挡杀虫,过五关斩六将,整个程序也称得上是层次分明。函数
但此次,咱们遇到了大问题。调试
今天的一切看起来都很平凡,至少我是这么认为的。
屏幕外的程序员像日常同样敲着代码,咱们像日常迎接着新函数的到来,像日常同样嬉笑怒骂,像日常同样期待着预编译进程的到来。
预编译进程是整个编译进程的先锋。
像往常同样,咱们从磁盘出发,沿着总线来到了内存。这里就是进程的工做车间。
预编译进程第一步会 删除全部 #define
,展开宏定义。处理条件预编译指令。
#define WINDOWS #define BUFSIZE 1024 #define DEPTH 4 #define DECODE "utf-8" ...
上面的就是宏定义,每次咱们都要在预编译进程的指挥下,把语句里出现的宏替换成对应的值。
这一步其实原本不须要咱们干的,程序员怕麻烦,想要作到“一处修改,到处更改”,就发明了宏定义,让编译器来干这些“脏活累活”。
处理条件预编译指令就有点不同了:
//windows or linux #ifdef WINDOWS <experssion1> #else <experssion2> #endif
若是宏定义有这个 WINDOWS
,就只留下 <experssion1>
,没有的话就留 <experssion2>
。说白了,就是个预编译阶段能执行的 if... else ...
语句。上面的语句一处理,就变成了:
<experssion1>
对,注释也会被删除。
可怜那些注释,这一生都未曾领略 CPU 里的风景。
第二步是处理 #include
预编译指令。
这一步就比上面的复杂多了。用专业的话来讲,处理 “#include ”预编译指令,就是将被包含的文件插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的文件可能还包含其余文件。
#include "config.h" <expressions>
别看他们如今就只有短短两句,等把 config.h
文件内容复制过来,信息量一会儿就大了。
#ifndef _CONFIG_H_ #define _CONFIG_H_ #define VERSION "1.0.0" #define MODE 1 ... ... #endif <expressions>
补充一句,这个 .h
后缀的家伙,叫头文件。他是咱们与其余文件的函数公民的沟通渠道。
头文件这个家伙和源文件不太同样,他是包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明。也就是说,头文件里是没有函数的——咱们曾屡次试图占领头文件的领地,但都没有成功——都是由于程序员的约束。
每一个头文件都会带有一组条件预编译语句,用来防止本身被屡次编译。
至于怎么作到的,这太简单了,我不说你也能想出来。
据说有的编译器还支持 #pragma once
,添在头文件第一行就能作到相同的事情。惋惜咱们的编译器有点旧,不兼容他们。
最后这步就比较快了,添加行号和文件名标识。
走到这里,咱们已经获得了编译器调试的须要的行号信息,若是编译到哪一步出错,或者出现 warning
这样的警告,就能把行号显示出来,方便程序员及时发现问题源头。
今天的预编译比我想象中要快一点,可能此次没什么进程跟咱们抢 CPU 资源吧。
预编译阶段结束,#
的数量大大减小,仅剩下几个 #pragma
指令留在这里。
和其余宏定义指令不同的是,#pragma
是可以跟编译器分庭抗礼的存在,预编译进程见了都得避让三分。
#pragma warning( disable: 4507 34; once: 4385; error: 164 )
像这条指令,就是专门给编译器看的,意思是 ‘不显示4507和34号警告信息 ,4385号警告信息仅报告一次,把164号警告信息做为一个错误’ 。能够说,她是程序员和编译器之间的信鸽。
<!--要注意的是,这里面的第几步第几步是不严谨的,预编译没有划分这样的界限-->
对于我来讲,预编译阶段是比较轻松的,最复杂也只是处理条件预编译指令——删除几行代码罢了。
未完待续
若是你们对文章有什么见解和意见,欢迎提出来~