“Hello,World”背后的故事

学习一门语言,经常都是从打印“Hello,World”开始的,打过招呼后,你便可以进入程序的新世界。

就拿经典的C语言举例,基本上每个程序员在上学时就可以闭着眼睛写下“Hello,World”,这也是检测开发环境是否能正常工作常用的小程序,就像有的人看能不能上网就输个百度试试(手动斜眼,程序员应该用谷歌).

//hello.c
#include <stdio.h>

int main()
{
    printf("Hello World\n");
    return 0;
}

我们使用gcc编译并运行该文件:

$ gcc hello.c -o hello
$ ./hello

输出结果:


helloworld

其实,输出一行字符并没有那么简单,gcc帮我们处理了很多步,如果你用Visual Studio,运行按钮更是连编译指令都不用敲了,IDE是简化了很多步骤,但是深入探索背后的步骤是每个程序员必备的素养,更何况很多成熟的大型项目都是需要自己构建(Build)。

上述过程可以分为4个步骤:

  • 预处理 (Prepressing)
  • 编译 (Compilation)
  • 汇编 (Assembly)
  • 链接 (Linking)
gcc编译过程

下面我们详述这一过程:

预处理##

预处理器cpphello.c及包含的头文件,这里就是stdio.h预编译成为一个hello.i的文件。
我们可以用以下命令只对hello.c进行预处理:

$ gcc -E hello.c -o hello.i

或者:

$ cpp hello.c > hello.i

你没看错,预处理器就是cpp,与C++扩展名.cpp没有关系,具体可以man cpp查看手册,其实gcc只是把预编译器,编译器,汇编器,链接器这一系列工具集成在一起,通过不同的参数去调用不同的部分或者全部调用

预处理做的工作:

  • 将所有的#define删除, 并且展开所有的宏定义,像#define MAX 1024,那么代码文件中所有的MAX都会被1024代替。
  • 处理所有的条件预编译指令,包括#if#ifdef#elif#else#endif。至于这些指令到底干嘛的,任何一本C语言教材都会有明确的解释。
  • 处理#include指令,将所有头文件插入到预编译指令的位置,这一过程是递归进行的,也就是说,头文件里包含的头文件也会被插入头文件里。良好的代码规范都指导我们使用头文件保护,避免重复包含头文件。
  • 删除所有注释///* ··· */。注释给人看的,机器不需要看注释。
  • 添加行号和文件名标识,比如打开刚刚的hello.i,int main()之前插入了一句# 2 "hello.c" 2,以便于编译器产生调试用的行号信息,这样产生编译错误或警告时,编译器就会给出文件名和行号。
    -保留所有的#pragma指令,编译器会使用它们。

经过预处理后,文件中所有的宏被展开,包含的文件也被插入,这时候就可以给编译器使用。

编译##

编译过程是整个程序构建的核心部分,包含了大量编译原理的知识,注明的参考书有龙书
编译过程可以分为以下几个部分,每个部分深究起来都很耗费功夫,有机会可以自己实现:

  • 词法分析
  • 语法分析
  • 语义分析
  • 中间语言生成与优化

现在版本的gcc把预处理和编译两个步骤合二为一,使用一个叫cc1的程序完成这两个步骤,在我的计算机里位于“/usr/lib/gcc/i686-linux-gnu/4.8/cc1”
我们可以通过以下命令生成编译后的文件:

$ gcc -S hello.c -o hello.s

也可以直接使用cc1:

$ /usr/lib/gcc/i686-linux-gnu/4.8/cc1 hello.c

编译后生成汇编文件hello.s

汇编##

汇编器就是将汇编代码转变成机器可以执行的指令,每一条汇编语句几乎都对应一条机器指令。所以汇编器相对简单,只需要一一翻译就可以。
我们使用汇编器as完成如上工作:

$ gcc -c hello.s -o hello.o

或者

$ as hello.s - o hello.o

也可以直接从hello.c直接得到目标文件:

$ gcc -c hello.c -o hello.o

链接##

据说链接器的历史比编译器还长,像我们的“Hello,World”程序,生成的hello.o中包含了printf函数,头文件只包含了函数的申明,所以最后还需要链接到libc.a,其实需要链接的不仅仅是printf,我们用链接器ld链接以下这么多模块才能生成最终的可执行文件。

$ ld -static /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i686-linux-gnu/4.8/crtbeginT.o 
-L/usr/lib -L/lib hello.o --start-group -lgcc -lgcc_rh -lc --end-group 
/usr/lib/gcc/i686-linux-gnu/4.8/crtend.o /usr/lib/crtn.o

一个再复杂的软件也是如此,将源代码分别独立编译,再组装起来,这个过程就叫做链接,链接的主要目的,一个是将模块间依赖的函数调用打通,还有就是模块间共通的变量打通。

链接器所做的工作主要就是“调整地址”,写汇编代码时,有这么一句jmp foo,其实链接器就帮我们把foo翻译成运行时的地址。

链接的主要过程:

  • 地址和空间分配 (Address and Storage Allocation)
  • 符号决议 (Symbol Resolution)
  • 重定位 (Relocation)

举个例子,可以很清楚的解释这个过程,我们在main.c调用了另外一个文件func.c中的函数test(),那么当我们在main.c中每使用一次test()都必须知道test()的地址,但文件都是单独编译的,所以我们在main.c中的做法是暂时搁置test()的地址,当链接的时候,链接器会根据test符号,自动填入test()的地址,如果func.c重新编译了,test()地址会变化,但是编译时,没有改变的main.c并不会编译了,只是在链接时,会链接新的test()的地址。这个修正的过程也叫作重定位

链接还分为静态链接动态链接,这个以后会专门说。

如果觉得还不错,请点个赞吧~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容