这一章讲的是C语言的发展史,包括它是多么不经意的诞生,而后又经历了早期C、K&C、ANSI C的各种阶段,直到它现在形成的这个样子。C语言从来不是一门完美的语言,所以它一直在发展,直到今日,它仍然有很多不足之处,但这些都掩盖不了它的光辉。

  C语言的产生源于一个失败的项目,这大概令许多人大吃一惊。这个项目是通用电气、麻省理工以及贝尔实验室联合创立的,Multics工程的目的是创建一个操作系统,结果当然就是操作系统失败了,C语言却从中诞生了。这个诞生的过程并不复杂,这个项目失败后,其中一个叫做Ken Thompson的研究人员用汇编语言为PDP-7编写了一个操作系统(这个PDP呢,相信看过《黑客——计算机革命的英雄》这本书的朋友不会太陌生,它是第一台小型机产品,PDP系列的计算机是早期麻省理工大学那块区域的黑客们爱如珍宝的计算机),这个操作系统就是有名的UNIX。Thompson发现用汇编语言编写UNIX显得非常笨拙,于是想利用高级语言的一些优点来完成它,在用Fortran进行了一番简短而又不成功的尝试后,他把用于研究的语言BCPL作了一番简化之后,就创建了B语言。当1970年开发平台转移到PDP-11之后,B语言的某些特性就变得有些不合时宜了。在这里就顺便说一下B语言的一些特性,它从BCPL语言简化而来的一个比较好的想法就是“引用数组元素相当于对指针加上偏移量”,现在的C语言同样沿用这个想法,它跟C语言一个比较大的区别就是它是没有类型的,这个问题导致它在PDP-11中显得有些不合时宜,因为PDP-11机器具有不同数据类型。Thompson的同事Dennis Ritchie利用PDP-11强大的性能,创立了能同时解决多种数据类型和效率的NEW B语言(这个名字很快变成了C语言),它与B语言的另一个重大区别就在于C语言采用编译模式而不是解释模式。至此,C语言诞生了。

  接下来谈谈早期的C语言,早期的C语言的许多特性是为了方便编译器设计者而建立的(当然,并不是为程序员写的),由于是为了编译器设计者而建立的,就导致了C语言简化的程度比较大,回避了一些复杂的语言要素(但是好像在C++中又出现了),这些特性让C语言更容易学习和实现,并且高效。早期的C语言并没有定义I/O,而是由库函数提供,可移植的I/O由Mike Lesk编写,最早出现于1972年左右,可在当时的三个平台上运行,但它的性能低于预期值,所以,经过人们对它的优化和裁剪,后来成为了标准I/O库函数。大约在这个时候,预处理器也加入进来,由于预处理器的强大替换功能,甚至可以改变C语言的语言结构,所以一般来说,不太提倡过度地使用它。

  至20世纪70年代中期,C语言已经很接近我们现在所使用的样子了,不过还是有许多区别。1978年,C语言经典名著The C Program Language出版的时候,也就是“K&R C"开始出现,由于这本书的影响力之广,导致K&R C广泛的传播,时至今日,这本书仍然是经典之作,不得不说,这本书也大大影响了C语言,使之成为当时最成功的编程语言之一。所以,想要学习C语言,The C Program Language确实是一本值得推荐的书,唯一要注意的就是它是K&R格式,当然,实际也相差不了太多。

  在20世纪80年代初,C语言虽然被广泛使用,但是由于编译器的不同,出现了许多版本,这可不是一个好的苗头,C语言受到了可能变成一种多个变种松散相关的语言的威胁,不过幸运的是,当时有许多其他语言都有自己正式的语言标准,所以C语言也走向这条路。K&R C对于C语言做了近40页的工作报告,1983年ANSI也成立了C语言工作小组,开始了C语言的标准化工作,最终在1991年3月发布了ANSI C语言标准,ANSI C标准是我们现在所使用C语言的公认标准,现在的绝大多数编译器都支持ANSI C标准,关于ANSI C与K&R C的不同之处可以浏览书上相关解释或有关资料。

  可以明确的是,ANSI C标准制定之后,代码的可移植性也相应的变强,只要遵守标准,能保证你的代码绝大多数情况下在多个平台下都能产生一样的结果,当然在你没有编写依赖编译器的代码的情况下,不过在ANSI C中有一条有趣的规定——编译器只有在违反语法规则和约束条件的情况下才能产生错误信息,这意味着所有不属于约束条件的语义你都可以不遵循,而且由于这种情况是未定义的,编译器可以采取任何行动,甚至不通知你。这个规则使得程序员在很多情况下意识到自己的错误变得更加困难,因为编译器可以不产生错误信息来提示你,除了语法错误和约束规定。

  从C的整个发展来看,它的形成过程比较曲折,有许多不经意,也有许多必然因素在里面,ANSI C标准的制定,使得我们有规则可循,当我们对某个用法不能确定或者对某个错误摸不着头脑时,可以回过头去查询标准规定,这无疑是个不错的做法,不过,这种做法的缺点也显而易见,一种东西一旦拥有所谓的标准,对它的修改、校正也会变得麻烦和形式起来,不过总得来说,这种标准的规定还是很有意义的,这也是C语言广泛应用的重要原因之一。另外一方面,我们可以发现尽管有了标准,但是编译器还是拥有很大的权力来对程序的编译进行处理,各种不同的编译器的编译过程也各不相同,由于这一点,程序的可移植性会有所降低,所以这个重大的责任就落到程序员的身上,尽量少编写一些依赖于编译器的程序。

《C专家编程》第一章——C:穿越时空的迷雾的更多相关文章

  1. Windows核心编程第一章.错误处理

    Windows核心编程第一章,错误处理. 一丶错误处理 1.核心编程学习总结 不管是做逆向,开始做开发.在Windows下.你都需要看一下核心编程这本书.这本书确实写得很好.所以自己在学习这本书的同时 ...

  2. Java 面向对象编程——第一章 初识Java

      第一章    初识Java 1.  什么是Java? Java是一种简单的.面向对象的.分布式的.解释的.安全的.可移植的.性能优异的多线程语言.它以其强安全性.平台无关性.硬件结构无关性.语言简 ...

  3. UNIX环境高级编程--第一章 UNIX基础知识

    第一章 UNIX基础知识 1.2 UNIX体系结构   从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们将这种软件称为内核(kernel),因为 它相对较小,且 ...

  4. 读高性能JavaScript编程 第一章

    草草的看完第一章,虽然看的是译文也是感觉涨姿势了, 我来总结一下: 由于 大多数浏览器都是 single process 处理 ui updatas and js execute 于是产生问题: js ...

  5. Go Web 编程 第一章 Web相关概念

    第一章 Go与Web应用 Go学习群:415660935 1.1 Web应用 在计算机的世界里,应用(application)是一个与用户进行交互,并完成用户特定任务的软件程序.而Web应用则是部署在 ...

  6. windows核心编程-第一章 对程序错误的处理

    第一章-对程序错误的处理 在开始介绍Microsoft Windows 的特性之前,必须首先了解 Wi n d o w s的各个函数是如何进行错误处理的. 当调用一个Wi n d o w s函数时,它 ...

  7. 【程序员翻身计划】Java高性能编程第一章-Java多线程概述

    目标 重点: 线程安全的概念 线程通信的方式与应用 reactor线程模型 线程数量的优化 jdk常用命令 Netty框架的作用 难点 java运行的原理 同步关键字的原理 AQS的抽象 JUC的源码 ...

  8. windows核心编程---第一章 谈谈windows中的错误处理机制

        我们写的函数会用返回值表示程序执行的正确与否,使用void,就意味着程序一定不会出错.Bool类型标识true时为真,false时为假.其他类型根据需要可以定义成不同意义.       Win ...

  9. 开启Golang编程第一章

    Go is an open source programming language that makes it easy to build simple,reliable, and effcient ...

  10. java并发编程--第一章并发编程的挑战

    一.java并发编程的挑战 并发编程需要注意的问题: 并发编程的目的是让程序运行的更快,然而并不是启动更多的线程就能让程序最大限度的并发执行.若希望通过多线程并发让程序执行的更快,会受到如下问题的挑战 ...

随机推荐

  1. hihoCoder#1039

    刚开始学习C语言,准备在做hiho的题目的过程中来学习,在此进行记录,如果代码中有错误或者不当的地方还请指正. 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi最近在 ...

  2. 关于css样式1

    背景色 可以使用 background-color 属性为元素设置背景色.这个属性接受任何合法的颜色值. 这条规则把元素的背景设置为灰色: p {background-color: gray;} 如果 ...

  3. 007-Scala类的属性和对象私有字段实战详解

    007-Scala类的属性和对象私有字段实战详解 Scala类的使用实战 变量里的类必须赋初值 def函数时如果没参数可不带括号 2.不需要加Public声明 getter与setter实战 gett ...

  4. Httpclient请求数据

    package com.baidu.myutils; import java.io.IOException; import org.apache.http.HttpEntity; import org ...

  5. C++11:新式的字符串字面常量(String Literal)

    自C++11起,我们可以定义 raw string 字符串字面常量. Raw string 允许我们定义所见即所得的字符串字面常量,从而可以省下很多用来修饰特殊 字符的符号. Raw string 以 ...

  6. 关于CSS三列Float布局任务

    任务目标 掌握HTML/CSS布局的概念 掌握盒模型的概念 掌握position与float的概念以及在布局时的用法 任务描述 使用 HTML 与 CSS 按照示意图;实现三栏式布局. 左右两栏宽度固 ...

  7. SQL获取汉字首字母

    )) ) as begin ) ) collate Chinese_PRC_CI_AS,letter )) insert into @t(chr,letter) select '吖','A' unio ...

  8. android原生ExpandableListView

    android原生可扩展ExpandableListView就是可以伸缩的listView,一条标题下面有多条内容. 这个list的adapter对的数据要求与普通ListView的数据要求也有一些差 ...

  9. MVC3之ViewData与ViewBag

    首先先用代码来说话: ViewData: public ActionResult Index() { List<string> colors = new List<string> ...

  10. GSM Hacking Part② :使用SDR捕获GSM网络数据并解密

    0×00 在文章第一部分 GSM Hacking Part① :使用SDR扫描嗅探GSM网络 搭建了嗅探GSM流量的环境,在第二部中,我们来讨论如何捕获发短信以及通话过程中的流量,从捕获到的数据中解密 ...