《C和指针》阅读笔记(2)

《C和指针》第二章的内容也非常简单,主要介绍了程序的编译过程和词法规则。个人认为对于初学者来说,可能编译过程能难于理解一些,所以本文会对编译过程再扩展一下,帮助理解;同时,也扩展一点关于C标准发展的timeline。关于词法规则的内容,理解上没有什么难度,多熟悉多使用,就慢慢的记住了。

C标准

本书中会经常出现K&R CANSI C,它们表示什么意思呢?就涉及到C语言标准的一些历史,在这里也简单介绍一下。

K&R C

1978年,Dennis MacAlistair Ritchie和Brian W. Kernighan一起出版了The C Programming Language,1989年,这哥俩进一步完善,出版了The C Programming Language,Second Edition。Dennis MacAlistair Ritchie被人们称作C语言之父。所以,The C Programming Language一书中使用的C语言标准也就叫做K&R C。即取了两位作者的名字的首字母。

ANSI C(C89)

ANSI(American National Standards Institute),美国国家标准协会,成立于1918年。这个机构诞生的原因就是没有统一标准而使许多企业和技术团队存在各种矛盾和问题。

ANSI C,就是该协会制订的关于C语言的标准。1983 年, ANSI委任 X3J11 委员会对 C语言 进行标准化。 经过长期艰苦的过程, 该委员会的工作于 1989 年 12 月 14 日正式被批准为ANSI X3.159-1989 并于 1990 年春天颁布。这个版本的C语言标准通常被称为ANSI C,也简称为C89

我们知道ANSI只是美国的一个标准化组织,但是并没有一个机构来完成全球范围内的标准化工作。于是,1946年10月,25个国家标准化机构的代表在伦敦召开大会,决定成立新的国际标准化机构,定名为ISO(International Organization for Standardization)。中国于1978年加入ISO,在2008年10月的第31届国际化标准组织大会上,中国正式成为ISO的[常任理事国。(PS:可以看出中国在技术上起步晚,相较于美国晚了90年,被人卡脖子也是意料之中,但中国的科学家、工程师正在奋起直追) ISO是一个国际性的非政府组织,ISO来源于希腊语"ISOS",即"EQUAL"平等之意。

C90

1990年,ANSI C标准(带有一些小改动)被美国国家标准协会采纳为ISO/IEC 9899:1990。这个版本有时候称为C90

C99

2000年3月,国际标准化组织(ISO)和国际电工委员会(IEC)采纳了C语言标准第二版,叫ISO/IEC 9899:1999,简称C99标准。

C11

2011年12月,国际标准化组织(ISO)和国际电工委员会(IEC)采纳了C语言标准第三版,叫ISO/IEC 9899:2011,简称C11标准。

两种环境

在C语言中,通常存在两种不同的环境:编译环境和执行环境。有时候编译环境和执行环境是相同的,有时候编译环境和执行环境是不同的。例如,在服务器后端开发时,编译和运行都是在服务器上,所以两种环境相同;在嵌入式开发中,通常编译是在X86机器上使用交叉编译器来完成程序的编译,而程序的执行是在目标设备上完成。

编译

《C和指针》阅读笔记(1)一文中提到了预处理的概念。第二章又着重介绍了程序的编译过程,这里我就再稍微展开一下,进一步的介绍编译过程到底做了什么工作。而我们常说的程序的"编译"是一种代称,有时候也叫构建(build)。(PS:我个人认为将整个过程表述为构建,更好一些,不至于混淆,但是如果听到别人说"编译"时,也要知道它表达的是整个过程)实际上程序的构建主要分为4个步骤,预处理(preprocessing)、编译(compilation)、汇编(assembly)、链接(linking)。

预处理(preprocessing)

预处理是由预处理器(preprocessor)来完成的。预处理过程主要由预处理器来解释源代码中以"#"开头的预处理指令。例如,#include,#define,#if,#pragma等等。通常使用gcc -E test.c -o test.i来完成预处理动作。

小技巧

当无法判断宏定义是否正确或这头文件包含是否正确时,可以通过预处理来更加直观的确认

编译(compilation)

编译是由编译器(compiler)来完成的。编译过程只要是把预处理后的文件(*.i)进行一系列的词法分析、语法分析、语义分析及优化后生成相应的汇编文件(*.s,*.S)。所以编译是整个构建过程中最复杂的一个环节,这里就不再展开,有机会再单独介绍编译更细节的过程。通常使用gcc -S hello.i -o hello.s来完成编译。可以使用cc1 hello.c

在这里插入图片描述

汇编(assembly)

汇编是由汇编器(assembler)来完成的。汇编过程就是将汇编代码转换成机器可执行的指令,经过预处理、编译、汇编后输出的文件就是目标文件(object file)。通常使用gcc -c hello.s -o hello.o,也可以使用as hello.s -o hello.o

链接(linking)

链接是由链接器(linker)来完成的。链接过程就是将目标文件以及库文件(动态库、静态库)链接起来生成可执行文件。通常使用gcc hello.o -lpthread -o hello,也可以使用ld hello.o -lpthread -o hello

通常我们可以直接使用gcc命令直接生产可执行文件,而不需要分步,例如,gcc hello.c -lpthread -o hello。细心的读者可能发现我也介绍了cc1asld,目的就是为了说明一下,平常我们看到的gcc命令只不过是这些子命令的封装,gcc 通过不同参数的指定可以只做部分过程,或者完整这个构建过程。

好了,第二章的阅读就到此了。

关注我

我的公众号二维码,欢迎关注
在这里插入图片描述

QQ讨论群:679603305
在这里插入图片描述