初识C语言
一、C语言发展史
C语言是一门功能强大,灵活多变的语言。它深受职业程序员和业余编程爱好者的喜爱。C语言是由肯•汤普逊(Ken Thompson)和丹尼斯•里奇(D.M.Ritchie)合力开发的。最初只是用来编写UNIX操作系统,但后来扩展到了诸如微型计算机,嵌入式处理器等领域。下面来简单回顾一下C语言的发展历程。
1.ALGOL 60 语言
C语言最早的原型是ALGOL 60语言,它也称A语言 ,全称Algorithmic Languagelo,ALGOL 60语言是世界最早的高级语言之一,他为以后许多语言的发明奠定了基础(包括C语言)。但是他仍有使用繁琐,不适合编写系统程序的缺点。
2.CPL
CPL(Combined Programming Language)是在ALGOL 60语言的基础上,由英国剑桥大学改进而成的,但依然有着编写不便,难以实现等缺点。
3.BCPL
BCPL(Basic Combined Programming Language)是由CPL语言简化而来的,它的缩写第一个字母就代表着Basic,在英语中有简化的意思。它是一种面向过程的高级语言,并且比CPL更加方便易用,更加模块化且容易实现。
4.B语言
1969年,肯•汤普逊和丹尼斯•里奇在BCPL的基础上继续进行简化,形成了B语言。B语言从BCPL中删除了许多非必要的组件,以便能更好地适应当时日益流行的小型计算机。它在数据类型,内存管理方面依旧有明显的缺点,但仍不失为一种简单易用,功能强大的语言,可以说是C语言的雏形。
5.C语言(特点)
C语言继承了它的祖先们的许多优点,至今仍是一门流行,用途广泛的语言,它的优点主要如下:
(1)兼顾汇编语言与高级语言的特点,能以简易的方式编译,处理低级存储器,操纵地址,又有抽象化编程的特点;
(2)编译后的可执行程序效率较高,仅比汇编语言低10%到20%;
(3)可移植性强,在不用修改代码的情况下,可以从一台计算机移植到另一台计算机上;
(4)使用结构化编程,代码复用性好,可以编写大型程序,且方便修改;
(5)代码格式较自由 ,对语法限制不严格,使程序员可以根据自己的风格写程序。
C语言有如此多的优点,使得这种语言很快被广泛运用。1979年,Bjarne Stroustrup 在C语言的基础上,又添加了面向对象特性和泛型编程特性,形成了C++。后来,Sun公司又以C语言为蓝本,发明了JAVA语言。C语言依然影响着许许多多的语言,如Visual Basic,D语言,C#,Object-C等。在编程史上有着重要的地位。
二、C语言标准
K&R C
C 语言最初由 Dennis Rithie 于 1969 年到 1973 年在 AT&T 贝尔实验室开发出来的,主要用于重新实现 Unix 操作系统。此时 C 语言叫做 K&R C(K 是 Kernighan 的首字母,R 是 Rithie 的首字母)。
即使在后来ANSI C标准被提出的许多年后,K&R C仍然是许多编译器的最低标准要求,许多老旧的编译仍然运行K&R C的标准。
ANSI C和ISO C
C 的第一个标准是由ANSI发布的。虽然这份文档后来被国际标准化组织(ISO)采纳并且ISO发布的修订版也被ANSI采纳了,但名称ANSI C(而不是 ISO C)仍被广泛使用。ANSI C现在被几乎所有广泛使用的编译器支持。现在多数C代码是在ANSI C基础上写的。
C 语言被各大公司所使用,因此到1989 年,美国国家标准协会(ANSI)对此进行了标准化;
C89和C90
1983年,美国国家标准协会组成了一个委员会,X3J11,为了创立 C 的一套标准。经过漫长而艰苦的过程,该标准于1989年完成,并在作为ANSI X3.159-1989 “Programming Language C”正式生效。这个版本的语言经常被称作”ANSI C”,或有时称为”C89”(为了区别C99)。 在1990年,ANSI C标准(带有一些小改动)被美国国家标准协会采纳为ISO/IEC 9899:1990。这个版本有时候称为C90或者ISO C。因此,C89和C90通常指同一种语言。
ISO/IEC 9899:1990 中的 9899 是 C 语言在 ISO 标准中的代号,像 C++ 在 ISO 标准中的代号是 14882;冒号后面的 1990 表示当前修订的好的版本是在 1990 年发布的。
C99
1999年,正式发布了 ISO/IEC 9899:1999,简称 C99。2000年3月,ANSI 采纳了 ISO/IEC 9899:1999 标准。
C99 标准引入了许多特性,包括:内联函数、可变长度的数组、灵活的数组成员(用于结构体)、复合字面量、指定成员的初始化器、对 IEEE754 浮点数的改进、支持不定参数个数的宏定义、在数据类型上增加了 long long int 以及复数类型。
但是,很少有 C 语言编译器是完整支持 C99 ,像主流的 GCC 以及 Clang 编译器支持高达 90% 以上,而微软的 Visual Studio 2015 中的 C 编译器只能支持 70% 左右。
C11
2007 年,C 语言标准委员会又重新修订 C 语言,到 2011 年正式发布了 ISO/IEC 9899:2011,简称 C11 标准。
C11 标准引入了:字节对齐说明符、泛型机制、对多线程的支持、静态断言、原子操作以及对 Unicode 的支持。
C语言的编程机制
gcc编译过程图解:
编译过程(从高级语言->汇编语言->机器语言(二进制)):
1.预处理(Preprocessing)编译器cpp
$gcc -E hello.c -o hello.i 将头文件展开,宏替换,注释去掉
上述命令中-E
是让编译器在预处理之后就退出,不进行后续编译过程;-o
指定输出文件名。预处理之后的程序还是文本,可以用文本编辑器打开。
2.编译(Compilation)器gcc
$gcc -S hello.i -o hello.s c文件变成汇编文件
上述命令中-S
让编译器在编译之后停止,不进行后续过程。编译过程完成后,将生成程序的汇编代码test.s
,这也是文本文件。
3.汇编(Assemble)器as
汇编过程将上一步的汇编代码转换成机器码(machine code),这一步产生的文件叫做目标文件,是二进制格式。:
$gcc -c hello.s -o hello.o汇编文件变成二进制文件
4.链接(Linking)器ld
$gcc hello.o -o hello 将函数库中相应的代码组合到目标文件中
第一步 预处理
由.c文件到.i文件,这个过程叫预处理。预处理过程实质上是处理“#”,将#include包含的头文件直接拷贝到hell.c当中;将#define定义的宏进行替换,同时将代码中没用的注释部分删除等
具体做的事儿如下:
(1)将所有的#define删除,并且展开所有的宏定义。说白了就是字符替换
(2)处理所有的条件编译指令,#ifdef #ifndef #endif等,就是带#的那些
(3)处理#include,将#include指向的文件插入到该行处
(4)删除所有注释
(5)添加行号和文件标示,这样的在调试和编译出错的时候才知道是是哪个文件的哪一行
(6)保留#pragma编译器指令,因为编译器需要使用它们。
第二步 编译
由.i文件到.s文件,这个过程叫编译。编译的过程实质上是把高级语言翻译成机器语言的过程
(1)词法分析
(2)语法分析
(3)语义分析
(4)优化后生成相应的汇编代码
第三步 汇编
由.s文件到.o文件,这个过程叫汇编。汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。
第四步 链接
由.o文件到可执行文件,这个过程叫链接。就像刚才的hello.c它使用到了C标准库的东西“printf”,但是编译过程只是把源文件翻译成二进制而已,这个二进制还不能直接执行,这个时候就需要做一个动作,将翻译成的二进制与需要用到库绑定在一块。
gcc hello.c -o a可以生成可执行程序。gcc不带任何参数,ld就可以看到你的可执行程序依赖的库。