C语言导论
前言:从C开始的步伐 当前已经有很多书籍阐述C语言。这本书希望与众不同。它一方面想向读者展现作者学习该门编程语言的心路;另外一方面,它希望作为一本入门性的,提纲挈领性的教材,能够 全面引导读者走进编程世界。C语言作为一门非对象型的编程语言,在计算机编程语言具有非常重要的地位。首先C语言是真正意义的高阶编程语言,这体现在C语言隐藏了大部分(当然不是全部)编程理论中对硬件原理的理解,程序员可以尽可能的以符合人类逻辑思维习惯的方式编写程序。其次C语言是一门“规模”非常小的语言,这意味着我们的教材可以以非常小的篇幅介绍他的语法和文法。相比更加高阶的编程语言,如Java,C++,C#,GO,python等等编程语言来说,C语言的缺点是过程性而不具备对象性特征。这意味着用C语言编写程序相对更加繁琐,客观上也决定了C语言确实不很适合编写大型程序,因为编程的规模会相对更加繁重而庞大。 但是C语言却绝非原始的编程语言。在笔者看来,C语言的重要性体现在它是一些更加“现代”,更加适合编写大型应用程序的编程语言的本源。从某种角度上说,使用java或者C++编写程序,其实只是站在C语言的肩膀上编程。因为C++或者java的编译器或解释器本身就来自于C,我们见到的大多数面向对象的编程语言的编译器或者解释器都是用C语言实现的。这本身足以说明C语言的广泛适用性。也正因为C语言是一门非常适合编写计算机操作系统和其他与硬件通信,强调效率性的程序,所以它几乎可以称为现代计算机编程语言的鼻祖。我们设计编程语言很难摒弃C语言。这不是说,每一位程序员都应该具备设计编程语言的能力,而是充分揭示当我们使用Java和C++之类的更庞大的编程语言编程的时候,我们无法超越C语言。在效率性方面,C语言理所当然会超越它们。 C语言的另一重要特点在于它的可移植性。程序代码的可移植性体现在,一种程序的源代码,在不同处理器编译,所需要付出的工作量大小。比如说,我们在X86系列处理器上编写的程序源代码,是否能以最小的劳动量在Arm架构的处理器上运行。对于Java来说,这通常不是难题。因为运行java的虚拟机本身已经完成了可移植性工作。java程序员完全可以不必关心底层的兼容问题。但是这本身其实仍然是C语言的优点。因为底层的可移植性难题,本身就是用C语言作为工具处理的。通常来说,针对不同处理器的特性编写的代码,是无法移植的,因为不同处理器对应的指令集不可能完全一样。C语言的优点在于它尽可能集中处理不同处理器的难题,将通用性的问题通用性处理,这才是C语言可移植性良好的关键所在。也是java程序员或者诸如python之类的编程语言可移植性良好的关键。java程序员不必关注可移植性问题,因为java平台已经为他们处理了。 我们学习C语言的重要意义在于C语言在编程语言占据着极为重要的地位。当前C系列的编程语言为现代编程语言的绝大多数,C语言堪称构建现在编程语言大厦的基石,它是java,C++,C#的鼻祖。笔者认为,一名合格的程序员如果不能了解底层,如果不能熟悉代码运行背后究竟发生了什么,他就很难真正领会程序设计的本质意义。C语言是程序员了解程序底层哲学的重要桥梁。 很多程序员认为,我们学习一门编程语言,目的在于完成既定的工作目的。比如说,我们学习java,目的在于设计通用性的,可移植性的大型应用软件。C语言在完成同样的工作上,是逊色于java的。在他们看来,编程语言只是一种工具,我们的工作内容决定了我们对工具的选择。然而在笔者看来,并不是如此。因为从另外一个维度上说,我们学习编程语言,目的还在于更好的完成既定的工作。同样是设计软件,我们理应心存能不能更快,更好,更优质。C语言在完成同样的工作,在工作量上可能确实逊色java。逊色的原因并非C语言在设计哲学上比java差,而是因为java平台已经完成了很多工作了,简化了必要的工作环节。java程序员设计大型应用程序,就好像是拿着菜刀切肉;而C程序员设计大型应用程序,则是先像一个铁匠一样完成菜刀的制造,再去切肉。我们通常不会用C语言设计大型应用程序,但是对于有个有着深厚的C语言功底的程序员,它既然有铁匠的技术水准,当然可以定制一把菜刀,也可以定制一把宝剑。不懂C语言的java程序员或许只能拿着菜刀切菜,而懂C语言的程序员则不仅可以拿着菜刀切菜,还可以拿着宝剑比武。 因此C语言不仅仅是一门工具意义的编程语言,它更加接近编程语言的哲学。这难道还不能说服大量编程初学者选择C语言作为进入编程殿堂的理由吗? 计算机软件行业是一个非常庞大的行业,编程语言多如牛毛,编程书籍汗牛充栋。单纯学java或者汇编语言,很难窥见全局,容易使初学者只见树木不见森林。而学习C语言的重要意义在于它贯穿着软件行业诸多技术细节。它培养着一名程序员新手对软件绝大部分技术的全面性理解,从而建立一个体系化的软件知识。笔者认为一名想在软件行业有所建树,渴望走的更远的程序员,理应从C语言作为学习的第一步。任何一名程序员显然不能只接触一门编程语言。首先掌握了C语言,就有了对编程语言的整体印象,在以后学习java,C++等更“高阶”的语言,就有了事半功倍的可能。从某种意义上说,编程语言不过就是编程语法和API(API是一种编程接口,读者可以理解为是一种编程工具,用于和编译器或者解释器通信,相当于英文中的单词)的集合,所以每种编程语言的设计哲学都有相似性,他们的不同体现在编程平台之上。编程平台才真正决定了编程语言的不同。任何编程平台底层都是汇编或者C语言写成的。而汇编本身就是处理器的“方言”,C语言相当于处理器的“世界语”。 相对于java和C++等大型面向对象的编程语言来说,C语言规模非常小。笔者甚至可以用不到50页的篇幅介绍它,再通过不到50页的篇幅介绍这门语言的API。但是众所周知的是,C语言是一门公认较难的程序语言。它的难点来自于它的灵活性非常强,而灵活性来自于C语言的精华甚至是全部:指针。大多数编程语言隐藏了指针的概念。C语言的指针,是C语言能够作为硬件设计的重要原因。而要理解指针,必然要充分理解计算机的硬件。大多数现代编程语言隐藏了指针的概念,就对程序员隐藏了计算机底层硬件原理。这有他的优点,那就是程序员能够将他们的精力集中在程序设计方面,把其他工作交给更高的高手,也就是编译平台设计者本身来处理;这同样也是缺点,因为程序员的程序性能基本已经由编译平台设计者决定,至少无法超越他。C语言给了程序员们最大的自由,他们可以充分的运用计算机的性能,以指针的方式。 指针的概念和计算机硬件原理息息相关。掌握硬件原理,是一名程序员新手应该有的基本功,除非他只是想成为一名普通的应用程序员,而对成为一名计算机专家毫无兴趣。这也正是众人认为C语言学习曲线非常陡峭的关键。然而笔者要说的是,软件行业本身是技术密集性行业,C语言的难点在于硬件理解的难点,而理解硬件是非常有必要的。忽略硬件原理,就无法走的更远。而如果程序员理解了硬件的基本原理,那么C语言的难点就成了他的优点。他最终能够成功的运用这门灵活,强大的语言。 C语言确实很难,但是这种难是非常有必要的。一旦你掌握了它,你就有了成为软件大咖的基本素质,你就和那些只会下载java平台jre编写代码的程序员有着本质不同。在java程序员的工具箱里,他们只有菜刀和木棍,而这些菜刀和木棍还是别的编程高手恩赐的;而C程序员的工具箱,应有尽有,并且C程序员可以信手拈来,自己创造自己想要的工具。 C语言当然也有自己的编译工具。有读者或许会问,C语言的设计者是如何设计C语言的?答案是汇编语言。而汇编语言是不可移植的。那么由汇编语言直接设计的C语言究竟有什么优点能让C语言强大至今,无法摧毁呢?汇编语言,通常也有一个工具用于编译,那就是汇编器。汇编器将汇编语言转化为机器语言,即计算机可以直接识别的语言,通常是1和0的组合。设计C语言的计算机科学大师(只能如此膜拜),充分考虑了C语言语法的自然逻辑性和硬件之间的关系,取得了一个良好的平衡点,允许C语言的编译器可以充分运用计算机的性能,对应生成的计算机语言贴合实际目标,产生了更少的无用代码段。才构建了C语言卓越的本质。 C语言的强大和灵活来源于C语言的编译器和编译器的设计哲学。因此笔者认为,不结合具体的编译器讲解C语言,可以称之为空中楼阁。单纯的程序语言讲解起来并没有多少意义。我们学习C语言的实质不在于语法,而在于培养对程序设计的宏观认识,对硬件原理的基础理解,对设计程序的精准把握。这当然也是本教材讲解C语言的出发点。 本教材题为《C语言导论》,而其实有着更加宏大的目标,那就是培养读者对程序设计的全面性的认识和把握,是一本讲解内功而非外功的教材。深入而再深入,将一切问题尽可能讲述透彻,是笔者写作的基本目标。笔者不希望读者心存任何疑惑,而以刨根问底的精神将一切问题解释清楚。笔者认为,这是一名伟大的程序员应该有的素质。 题外,中国的软件行业非常发达,但是我们可知的是大多数重要的工程领域的软件都是国外设计。比如操作系统的重要部分,Linux/Unix,windows,都来自欧美国家。中国实际没有成熟商业运作的现代操作系统;再比如说,Photoshop,matlab,VisualStudio等等大型应用软件,也都是欧美国家设计出来并得到广泛运用;而大多数流行的编程语言,也是国外发明创造出来,众所周知的C++,Java,Python,C#等等,包括本教材中所要讲述的C语言,无一例外不是国外设计。这本身让我们感到汗颜。有着十四亿人口的中国在基础软件技术领域存在巨大的空白,几乎全然依靠国外的基础性技术!更不要说,在硬件领域,各类芯片的国产缺失。这些缺失本身说明了我们国家在信息科技领域缺少人去从事基础性的工作。而之所以存在如此之大之多的空白,本质还是我们信息科技行业十分浮躁,很少有人愿意深入钻研信息科技的本质问题。笔者希望能够有更多的朋友同我一样,有着高度的钻研热情研究基础信息科技领域。中国信息科技的进步,不能建立在缺少原创的基础上。如果中国缺少自己的芯片,缺少自己的操作系统,就可以认为中国缺少自己的信息文化,就无法认为中国是一个真正意义的信息强国。这既不合理,也十分危险。
第一章 起步:从操作系统开始 笔者认为讲解一门编程语言,就不能和结合编程语言的平台讲解。脱离了编程平台,编程语言毫无一用。我们学习C#,一定要下载安装微软公司的.net平台;我们学习java,一定要下载安装Orcle公司的JDK;我们学习python,必然要下载安装python的解释器;只有在编程平台上,我们编写的程序代码才有运行的可能。从某种意义上说,正是编程平台决定了编程语言的实质。如果编程平台有了一定的变化,可以认为编程语言也有了一定的变化。笔者看来为微软公司研发的Visual Studio编译C语言程序所对应的C语言语言,和GCC编程平台所对应的C语言是不尽相同的,极端情况下可以认为他们并不是相同的编程语言。GCC平台下完成的C语言程序可以编译成为可在硬件直接安装的操作系统,而VisualStudio平台编译运行的C语言程序则只能是.net程序,即特定的应用程序。为了完整全面讲解C语言,笔者选用GCC平台。 而当前大多数编程语言平台,本身就是一种应用程序。应用程序运行在操作系统之上。换而言之,应用程序本身也需要操作系统平台。出于同样的目的,笔者选用GCC平台,也推荐读者选用GCC平台对应的一种操作系统平台:Linux。笔者选用Linux平台的重要原因有二:第一,开源性,读者如果选用windows操作系统平台,由于windows操作系统是闭源的,我们无法清晰的看到windows操作究竟是如何运行我们的C语言代码,因为windows操作系统封装了底层的技术细节,并加以隐藏,这并不很利于我们接触到全面的技术细节。所以最佳方案是几乎完全透明的Linux;第二,Linux本身和C语言密不可分,笔者希望读者在充分掌握C语言之后能进一步熟悉Linux操作系统,进而掌握操作系统原理。 编写C语言代码,要用到GCC;要用到GCC,就要用到Linux。而真正伟大的程序员是不希望被任何事物约束自己手脚的。他一定是希望能够自己创造自己的操作系统,自己创造自己的平台,自己创造自己的编程语言,自己运用自己的一切。热爱自由,是人之本性。出于自由的考虑,笔者也不希望读者被约束住手脚。但是C语言毕竟是计算机大师的发明,我们借鉴大师的发明,那么就不能不暂时利用既有的平台。但是这样的平台应该是透明的,而不应该是黑箱。打个比方说,我们用菜刀切肉,我们同样也希望自己能够生产出菜刀。通过消化对菜刀制造的知识,我们就有可能积累铸造宝剑的知识。Linux和GCC提供了这种可能性,这也正是笔者推荐的理由。 无论是Linux还是GCC,都是一种软件。软件建立在硬件之上。没有硬件,一切都没有存在的可能。当前的计算机硬件设备,也是欧美国家的发明。在我们尚没有对应技术的前提下,也只能选用他们的技术设备。本书并不是讲解硬件原理的书籍,因此只是推荐读者尽可能采用X86体系的处理器,至于其他的硬件,如芯片组,内存,外存等设备,读者可以自由选用(实际上我们也没有多少选用空间,毕竟几乎都是被国外垄断的技术)。个人PC设备采用的通常都是X86体系设备,笔者建议读者可以选用intel主流的处理器。 为了让我们的硬件设备具体化。笔者推荐一组设备:i3-8100处理器,主流B360主板,DDR4内存,500G大小的机械硬盘,其他输入出设备可以任意选择,无关紧要。之所以这样推荐在于这样的硬件设备较为主流。部分读者可能有进一步接触底层的想法,比如设计自己的操作系统。读者对此表示非常赞赏,我们国家需要这样头脑聪慧,见识非凡,深究到底的人才!选择intel处理器,在于笔者注意到intel公司官方的处理器参考文档非常详尽,这非常有利于我们学习他们的处理器架构知识。如果我们能够通过他们的官方文档,在他们的处理器平台z上独立设计出拥有自己理念的操作系统,这就是超越他们的开始!这本身就提供了我们在自己的硬件基础设计出操作系统的软件技术可能!希望阅读本书的读者能够有这样的雄心壮志! 通过X86体系硬件,安装一种linux发行版本(所谓发行版本,就是可以直接下载安装的操作系统),然后在linux发行版本上安装笔者推荐的GCC平台(大多数linux发行版本都已经预装了GCC,所以这个步骤通常可以省略)。就可以开始我们的C语言学习旅程了。为了更加具体的让读者无障碍起步。笔者进一步说明平台配置步骤。 首先,读者可以按照笔者推荐的硬件清单组装一台电脑,键盘,鼠标,显示器,机箱,电源等外设不在本文讨论范围,因为这些外部设备通用性很强,因此笔者认为不必强调。如果读者认为组装电脑过于麻烦,可以直接购买一台内置intel处理器的台式机。笔者非常不推荐直接购买台式机,更加不推荐直接购买笔记本。笔者希望读者能够在尚对计算机技术一无所知的开端能够建立对硬件的基本认识。对于一本介绍编程知识的书籍来说,实在是无法利用大段篇幅说明如何组装一台电脑,请读者自行百度。任何一名有志于信息技术的人理应有这样的钻研精神研究如何组装一台机器。或者读者至少能够拆开机器去识别,何为处理器,何为内存,何为芯片组,何为南桥,何为北桥,主板上BIOS芯片在哪里,串口和并口是什么。 其次,读者理应能够独立安装一种linux发行版本。毫不讳言,笔者热爱linux操作系统。这种操作系统优美而强大。笔者推荐读者安装ubuntu linux。我们初次学习编程技术,能够有稳定的图形界面仍然是有必要的。ubuntu linux在图形界面的稳定性值得称道,它也适合新手建立对linux的良好印象。为了安装ubuntu,读者可以准备一个不小于8G的U盘设备。利用一台安装有windows系统的电脑(这样的电脑,在我们国家到处都是),在ubuntu官网下载ubuntu linux 18.04桌面版本,放在本地硬盘中。为了将ubuntu安装到自己的电脑上,读者要将ubuntu写入自己的U盘中,然后让自己的电脑以U盘启动,进而安装。而如何将下载的Ubuntu写入U盘呢?笔者推荐http://www.pendrivelinux.com/universal-usb-installer-easy-as-1-2-3/网站的一个小小的写入U盘工具,universal usb installer。下载后双击打开这个写入工具,选择ubuntu,选择U盘设备,写入。这个过程非常简单,相信不必详细叙述。写入完毕后将U盘插入到自己的电脑上,以U盘启动,进而开始操作系统安装。安装过程同样非常简单,在此不再详细叙述。 再其次,当读者的电脑安装好Ubuntu 18.04之后,该操作系统将自带GCC。因此至此其实已经完成了我们学习C语言所需要的一切平台。为了书写代码的方便快捷,笔者建议读者在启动操作系统之后,打开终端(Ctrl+Alt+t),输入 sudo apt install vim。选择安装vim文本编辑器。终端是我们学习C语言始终身处的环境。在今后的章节,笔者将通过讲解C语言慢慢展开对linux的讨论,以使笔者能够自由运用它。 至此,我们学习linux的物质基础就已经准备就绪。下面,让我们开始和操作系统,和硬件,作第一次通话,写第一行C语言代码。
本文转自异步社区
原文链接:https://www.epubit.com/articleDetails?id=N406209fc-4727-4b8d-b458-e53089496aff
- 点赞
- 收藏
- 关注作者
评论(0)