如何成为一个优秀的程序员(宋劲杉)

转自:http://www.akaedu.org/pages/news_detail.php?id=294 

我们的老师每天都要应对报名者和学员提出的很多同样的问题,以下是这类典型问题的汇总:嵌入式行业(或者IT业)有没有前途?我听说编程编到三十五 岁就没人要了,一定要转行找出路是吗?做驱动开发和做应用开发哪个更有前途?我一开始看什么书都看不懂,怎么才能理出一个学习顺序?诸如此类。这使我迫切 地感觉到,应该总结这样一份非具体技术问题的FAQ了。本文仅代表我个人观点,有问题欢迎Email: songjinshan@akaedu.org

    在看这份FAQ之前,你必须先读完ESR的《如何成为一名黑客》(本文末尾附有中译版),该文所讲过的道理我不再重复。该文用很大的篇幅讲什么是黑客文 化,虽然态度和信仰的确是成功的最关键因素,但是你肯定会想,做不做黑客跟我没关系,我只是想学个一技之长,找个好工作而已,对吧?那么肯定更希望获得一 些具体的可操作的指导。

    1、各种软件技术之间是怎样的关系? 
    我把软件技术分为三个层次:
    问题域:计算机图形学、音视频编码、信息安全、模式识别、信息检索、自然语言分析、人工智能、科学计算等;
    系统集成:C++和Java等面向对象语言、Python等解释型语言、LISP等函数式编程语言、GUI、中间件、编译器与解释器、虚拟机、数据库、网络服务、并行计算、集群、Peer2Peer、系统管理等;

    系统功能:硬件描述语言、计算机体系结构与编程模型、指令集与汇编语言、C语言、内核、文件系统、设备驱动、网络协议、POSIX等。

    计算机最终是做什么用的呢?最终是通过问题域的各种技术为用户解决问题的,这些技术都包含很高深的算法,然而它们必须在一个平台上运行,它们需要利用平台 提供的各种基础设施,比如计算能力、I/O能力和网络互联能力。系统功能和系统集成层就是用来实现这个平台的。系统功能层实现计算、I/O和网络的基本功 能,系统集成层对这些基本功能做一些抽象和包装,提供更方便灵活的接口。

    2、为什么要学习嵌入式技术? 
    在亚嵌的学习期间,你将详细了解系统功能层的各部分是如何工作的,也会在面向对象编程、GUI、数据库、网络服务等系统集成层的技术方向进行探索。嵌入式 系统可说是麻雀虽小五脏俱全,虽然没有PC和服务器那么复杂,但计算机系统的各种组成一样也不缺。因此,以嵌入式系统作为切入点开始学习软件技术是非常好 的选择,避开不必要的复杂性,把握计算机系统最根本的概念和技术要点。打下扎实的基础之后,你的职业发展则完全不必局限于嵌入式领域,即使你日后做PC或 服务器开发,在亚嵌所学的知识和技能同样使你终生受益。正如庖丁解牛,心中有全牛,自然就能游刃有余。

    另一方面,你一定见到各大网站都有大量的宣传,说现在嵌入式行业前景空前的好,嵌入式人才紧缺,有几百万职位空缺等等。这些说法也是对的,但我们需要更深 入地理解这说明了什么问题。刚才我们说,嵌入式系统也是一个完整的计算机系统,和PC或服务器没有本质的区别,事实上,嵌入式、PC和服务器的界限已经越 来越模糊了。以前的嵌入式就是单片机,只能做简单的运算处理,现在的ARM处理器性能比从前的奔腾还强,打游戏、看电影都没问题,谁能说它不是PC呢?另 外有些专用的嵌入式系统已经在充当服务器的功能了,而集群技术更是可以使许多廉价的处理器组合在一起发挥大型服务器的作用。由于嵌入式越来越多地应用到电 器、汽车和各种设施上,无处不在,并且与PC、服务器呈融合的趋势,所以嵌入式行业前景空前的好。

    那么,为什么说嵌入式人才紧缺呢?其实,学嵌入式系统就是学计算机系统,本质上并没有什么特殊的只有嵌入式系统才有的技术。说嵌入式人才紧缺,其实质上是 说真正懂计算机的人才紧缺。现在很多学校的所谓“软件学院”培养的软件人才都是一叶障目不见泰山的:只懂J2EE和.NET,没学过C和汇编;只会调库函 数sort(),而对各种排序算法一无所知;设计模式、软件工程讲得头头是道,却不知道好的软件还是要靠牛人靠智商来做的。培养人像蒸包子一样一屉一屉地 出,靠软件工程搭一条生产线,然后让熟练工人站在生产线上拧螺丝,幻想着这样就能生产出好的软件,那是把软件工程和程序员的作用本末倒置了。现在嵌入式开 发对程序员的素质要求更高了,以上这类“软件人才”不能胜任了,因此说嵌入式人才紧缺。亚嵌的就业班虽然只有几个月,但培养目标是有完整的计算机系统概念 的软件人才,而不是只会拧螺丝的软件工人,这正得益于我们始终坚持做嵌入式培训而不是Java或.NET培训。

    3、有人说软件技术变化太快,现在学的东西过两年就要完全淘汰,是吗? 
    你知道这话是什么人说的吗?必然是已经被淘汰的人说的。比如Delphi、BCB、PB这些开发工具和语言,都曾经很是风光了一阵,但现在已经完全被 Java和.NET取代了。那么Java和.NET会不会被取代呢,也许在相当长的时间内还不会,但是我看好Python。

    这些被淘汰的程序员有一些共同的特点:只会用鼠标拖拽控件,离开IDE就不知道如何工作,学点儿花拳绣腿的功夫就想吃一辈子,对学习新技术不感兴趣,做一 天和尚撞一天钟。现在请回头看看FAQ1,在整个软件技术领域,这些变化快的技术其实只占了很小的一块,却成了这些人的全部看家本领,这样的人能不被淘汰 吗?

    与这些流行的开发工具和语言相反,很多技术和思想是很少变化的。比如,POSIX和SUS标准规定了一套系统函数接口和基本命令的语义,只有实现了这些才 可以称作UNIX,因此今天的Linux、Solaris跟20多年前的UNIX在系统功能层上是基本一致的。而指导计算机科学发展的数学理论,甚至是老 祖宗们在计算机还没诞生的年代就替我们想好的:布尔代数发表于19世纪,直到一个世纪后发明了计算机和数字电路才有了用武之地;数论在17世纪就出现了, 一直都被数学家们当成一套好玩的理论,但只是好玩而已,直到计算机密码学诞生后才发现它的实际用处。

    各种流行的开发工具和高级语言虽然变化很快,但是底层的编程语言却非常稳定,各种操作系统的内核都是用C语言写的,以前是这样,以后也不会改变。另一方 面,各种编程语言的设计思想也是非常稳定的。其实世界上只有两种编程语言,一种是C,一种是LISP,前者是imperative的,是对计算机模型的抽 象,后者是functional的,是对数学函数模型的抽象。面向对象是一种重要的软件工程思想,却算不上一种新的语言模型,应该归在C的一类。属于同一 类的各种语言其实都大同小异,一个精通C++的人学习Java需要多长时间?熟悉语法一个星期,熟悉类库三个星期,一个月足矣,以往的经验都可以套到新的 编程语言上。然而要想习得深厚的算法功底、逻辑思维和抽象思维修养,能够真正说清楚“系统”是什么,如何分析和设计“系统”,需要多长时间?恐怕要数十 年。

    4、C和Java哪种语言更好? 
    计算机科学与编程语言无关,甚至与计算机本身也没太大关系,它研究的对象并不是计算机,而是人分析问题解决问题的方法论。程序写出来最主要不是为了给计算 机执行的,而是为了给人看的,使用编程语言和使用自然语言一样是为了表达和交流,只不过程序还可以顺便给计算机执行而已。

    以上这些话并不是我说的,而是一位著名的计算机科学家说的。所以,在编程语言的层面上争论是没有意义的。很多初学者错误地认为掌握了编程语言就等于学会了 计算机,一种编程语言都还没有掌握好,更没有上升到方法论的层面,只有这种无知的人才会去争论哪种语言好的问题。掌握了编程语言远远不等于学会了计算机, 而只是最开始的一步,最简单的一步,到了工作中,用到什么语言就去学什么语言,什么语言过时了就丢掉,编程语言不需要积累因为它太简单了,真正需要积累的 是方法论。

    很多人喜欢参与到这类争论之中,毫无例外,每个人都在为自己熟练掌握的编程语言辩护,就是“我会的语言最好,我不会的语言都不好”,其实这些人真正想说的 是“我会的语言最好是千秋万代,我就不必学新的语言,不必适应新的变化了”,概括起来说就是一个字,懒。真正的高手都是会很多编程语言的,国外有些做技术 咨询的,每年都要学好几门新的编程语言,这样才能应对市场的变化。不断丢掉旧的编程语言学习新的,看起来好像完全是白费力气,没有积累,其实,每种编程语 言的设计都有独到之处,体现了每种语言的精髓,在融汇百家之后积累下来的正是方法论。

    争论哪种语言能做的事情更多、功能更强是没有意义的。从理论上说,任何一种符合图灵机模型的编程语言,加上适当的I/O扩展都可以做任何事情,用 shell脚本也可以写出很像样的游戏来。只不过各种语言的设计目标不同,表达能力不同,做不同的事情所需的代码量不同而已。

    另外一种错误认识是:哪种语言的市场最大,开发人员最多,哪种语言就最好。单从这种意义上说,Java的确比C更好,所以往届有学员问我们为什么只教C语 言。请你注意,操作系统内核是用C写的,各种底层的应用程序包括Java虚拟机也是用C写的。如果你想学Java,在亚嵌的学习完成后你将有能力分析 Java虚拟机的实现,站在计算机系统的高度来学Java才会使你成为真正的Java高手。如果你只想速成,想早点学成一门技术去做拧螺丝的工作,那么亚 嵌不适合你。

    在FAQ3里说过,世界上有C和LISP两种编程语言,你现在学了C,以后学了C++、Java、.NET等等,也仍然只认识了半个世界。LISP和 Haskell构成了另外半个世界,现在很常见的Python和JavaScript等解释型语言也借用了functional programming的思想。如果你只管闷着头写代码,而不去广泛涉猎,那么你将错过很多精彩。

    5、我听说编程编到三十五岁就没人要了一定要转行找出路是吗? 
    这个观点虽然很流行,但根本不值一驳。现在三十五岁转行的那些人,都具有前面所说的那些特征,对学习新技术不感兴趣,对探索计算机的本质不感兴趣,得过且 过,下了班就是打游戏、看电视,总之就是懒。如果是开出租、摆摊,勤快人懒人都有饭吃,而IT这一行对懒人是非常无情的,懒人就不该入IT这一行,不从自 身找原因,却到处散布这种言论,怪社会不好,打击新人的信心,着实可恨。

    另外一种情况,编程编到三十五岁,进入公司的管理层,或者自己创业,这都是很勤快的人,如果他们把这种勤快用在技术上肯定也可以做得更好,所以也无法证明编程编到三十五岁会因为没有出路而转行。

    编程不是个体力活,需要高强度的思考和智力投入,分析能力、思考能力都需要时间积累起来,所以并不是越年轻干得越好。相反,我认为三十岁以前写的代码都是 垃圾,三十岁以后才能写出像样的程序来。如果希望一辈子走技术的道路而不会被迫转行,就要不断地把自己的工作性质从“体力活”变成“脑力活”。什么叫“不 断地”变呢?这里的“体力活”并不是指种地、盖房子这种劳动,而是指简单重复地编写代码,这时你会感觉,派给你的工作都能凭以往的经验轻松应付了,但是千 万不要满足于现状,就像温水煮青蛙一样,这是危险的处境!要摆脱这种处境就需要学习、思考、提高,让公司派给你更有挑战性的工作,在工作中应用新学到的知 识和技术就是“脑力活”了,但是用得久了又会变成简单重复的“体力活”,这时就需要再学习、再提高,所以叫做“不断地”把自己的工作性质从“体力活”变成 “脑力活”。如果有一天你发现,自己长期陷于简单重复的劳动之中,并且业余时间非常少,无法学习提高,这说明公司不会用人,你就该考虑跳糟了。

    从另外一个角度来说,如果希望一辈子走技术的道路,就要有自己的核心竞争力,这个核心竞争力决不是凭以往的经验能够做某些工作的能力,而是学习能力、思考 能力和解决有挑战性的新问题的潜力。在IT这一行,凭借以往的经验干重复的活是干不长久的,原因很简单,一个问题不会被解决两次,当你发现你的经验能够解 决一类问题时,别人早把解决这一类问题的套路编写成framework,新上手的人即使不具备你的这些经验也可以调用framework中的类和函数来解 决问题,然后在这个framework的基础上积累新的经验解决新的问题。正因为如此,全世界开发人员的经验才会积累起来,促使软件技术发展得如此迅速。 这并不是说经验完全没有用,最关键的,学习和思考也是建立在以往经验的基础之上的。另一方面,现有的framework并不一定是某方面开发经验的完美整 合,也需要不断发展,用新的办法重新解决老问题,以Web开发为例,从早期的ASP、PHP到后来的.NET、J2EE,到现在的Ruby on Rails、Django等等,这些framework解决的是同一问题,就是如何快速有效地开发Web应用,这方面的经验被不断重新整合,推陈出新。总 结一下,什么才是核心竞争力呢?应该是在经验的基础上学习新技术、解决新问题的能力。

    6、做驱动开发还是做应用开发更有前途? 
    意思就是说,“你告诉我哪个更有前途,我就好好学哪个,另外一个就不用学了”。问这种问题的学员往往会同时问另外一些问题:我以后就想做驱动开发,你教我这些应用开发的技术有什么用?C++用得多吗?学了有什么用?我以后不想做GUI,你教我Qt有什么用?

    学习最忌讳的就是“有用的就学,没有用的就不学”这种功利的态度。两个问题:第一,在你还没学进去、还不了解这种技术时,要如何判断这种技术学了有没有 用?只能是根据道听途说,看各种论坛上都怎么说的,岂不知论坛上参与这种讨论的100%都是菜鸟,有的水平还不如你。第二,就算你学的技术没有用上,有什 么损失吗?从亚嵌毕业的学员从事各种各样的开发工作,有做驱动的,有做系统编程的,有做GUI的,有做Web开发的,只要确定了做一类工作,就不可能把在 亚嵌四个月学的知识都用上,但至少也用得上3/4的知识,假设剩下的1/4你一辈子也没机会用上了,那也就损失你一个月的学习时间而已,相比于你的收获, 这算是很大的损失吗?请注意,上面的假设是不成立的,没用上的那1/4也只是暂时没用上而已,程序员要换工作或者换项目是很常见的,任何人都不可能只涉及 一类开发工作,只要有扎实的基础、完备的知识体系,任何工作都能轻松上手。

    扎实的基础,完备的知识体系,我们在安排就业班课程体系的时候,正是以这两点为依据的。有的课程内容很少有学员在以后工作中会用到,但是缺了这一环就不成 为一个完备的知识体系,例如MMU和Cache,那这种课该不该上呢?毫无疑问该上。有的课程培养一种基本的编程思想,例如通过C++来讲面向对象编程, 通过Qt来讲面向对象、事件驱动和状态机编程,这些编程思想是程序员必备的基本素质,而C++和Qt可能有些学员以后工作用不到,那这种课该不该上呢?毫 无疑问该上。至于还有些人争论说C++不如Java用得多,Qt不如GTK用得多,请翻回去看FAQ4,这种争论是无意义的,有工夫争论谁优谁劣,不如把 两种都学了,会更有收获。

    回到做驱动开发还是做应用开发更有前途的问题。我只能说,做好了都有前途,做不好都没有前途,只会做一样而完全不懂另一样是最没前途的。不要以为内核开发 者就不写应用程序,Linus写了一个源代码管理系统git来维护内核,因为觉得现有的源代码管理系统都不好用。牛人都是这样,需要什么就写什么,才不管 是kernel space还是user space。同样,做应用开发如果不懂内核,也没有办法很好地利用内核提供的服务写出性能最优的程序。做内核难,因为调试难,要跟踪大量的并发线程,因为 入门难,要写一个hello world都需要学很多知识。做应用也难,回头去看FAQ1,计算机科学从理论到实践大部分都在上面两层做文章。所以不存在哪个更难哪个更有前途的问题, 任何关于哪个更难的讨论都是too naive的。

    7、我一开始看什么书都看不懂,怎么才能理出一个学习顺序? 
    以前有个学员在学C语言时说,“C语言很多地方都很奇怪,都得用内核的知识去解释,可是你又不先教我内核,我没法学C语言。我只好自己看操作系统的书,看 内核代码,可是看不懂。”当然看不懂了,内核代码都是用C写的,如果不学内核就没法学C语言,那不学C语言又怎么可能看懂内核?看来这是一个鸡生蛋还是蛋 生鸡的问题。

    懒真的是人的本性,就连学习的过程都希望是一条路顺利地走下去,不用动脑就能学会的:身后走过的路都是“已知”,每走一步就把眼前新的“未知”变成“已 知”,如此一路走来,把所有的“未知”都变成“已知”就算学成了。可惜,知识不是一条路,而是一个圈,你从任何一个地方跳进这个圈开始走,身后都是“未 知”,眼前也都是“未知”。有的人就是不能容忍自己的身后是“未知”:看一本书,一个新的概念A是用我不了解的概念B、C来解释的,我连B、C都不懂怎么 学A?没法学了!

    不是人家书写得不好,而是没有任何办法能把一个圈扯成一条直线的。学习的过程本质上就是一个循环往复的过程,唯一的办法就是“存疑”:在本子上记着,有 B、C这样两个概念是我暂时不理解的,然后就不再去想这回事,而是相信自己已经理解了B、C,基于自己的理解和假设去学习A,由A再去理解X、Y,这样学 下去,走完一圈之后再回来,自然就明白当初对B、C的假设正确不正确了,理解了这两个概念,就从本子上划掉,这时需要再走一圈,把原来的一些错误认识纠正 过来。所以,任何书都要至少看两遍,第二遍看的时候你会对很多概念有新的认识,因为你看过这个概念后面的章节,在此基础上产生了新的认识。古人早就明白这 个道理,所以提出了“温故而知新”。

    亚嵌的课程体系经过多年教学实践的锤炼,已经很好地理顺了知识之间的关系,使你从最佳的位置跳进这个圈开始学习,所谓“最佳位置”是指,在你初学的时候需 要容忍的“未知”尽可能少,需要做的假设尽可能少,但要想消除所有的“未知”是不可能的,例如没有学内核就要学C语言。根据你以往的经验和一些运气因素, 你对内核的一些假设可能正确也可能错误,但这并不影响你学C语言,对内核的一些错误假设可能会导致在学C语言的过程中有些误解,但没关系,只要跟着我们的 课程体系一步一步走下来,这些误解和错误的假设最终都会纠正过来。

    8、有哪些好书可以推荐一下吗? 
    能问出这个问题的都是聪明的学员。看书学习是入门过程中非常重要的一环,如果用一本烂书入门,浪费时间还是小事,如果被误导了就麻烦了,如果形成的错误认 识不能及时纠正,变得根深蒂固了就更麻烦了。所以,看书一定要有“品牌意识”,在决定看书学习一门技术时先问问这一领域最权威的书是哪本,这里列举一些 Bible级别的书:
    The C Programming Language, 2nd Edition; 
    C++ Primer, 4th Edition; 
    Structure and Interpretation of Computer Programs, 2nd Edition; 
    Introduction to Algorithms, 2nd Edition; 
    Compilers: Principles, Techniques, and Tools; 
    Advanced Programming in the UNIX Environment, 2nd Edition; 
    TCP/IP Illustrated, Volume 1: The Protocols; 
    UNIX Network Programming Volume 1, 3rd Edition: The Sockets Networking API; 
    Understanding the Linux Kernel, 3rd Edition; 
    Linux Device Drivers, 3rd Edition。

    在学习过程中,眼界一定要开阔,不要学到一点东西就沾沾自喜,坐井观天,以为这就是技术的全部。要多和别人交流,多了解别人在看什么书、别人对技术的认识是怎样的。书是看不完的,活到老学到老,对于程序员来说尤其如此。

    9、如何处理打游戏和学习的关系? 
    ESR的文章中也说过,黑客们都有一些特别的业余爱好,并且往往是非理性思维的爱好,大概是需要换换脑子吧。典型的例子是因滑翔机事故去世的 Stevens,他写了FAQ8所推荐的Bible当中的三本。爱打游戏的优秀程序员肯定大有人在,有一些还成了优秀的游戏开发人员。但是我认为,要想成 为优秀的程序员,必须有两点基本素质,一是对编程非常感兴趣,二是对所有别的事情都不感兴趣,或者都不如对编程感兴趣。有人说,人的一天有24小时,8小 时休息,8小时上班,另外的8小时在干什么就决定了你以后有多大发展。一有时间就看书学习,这就是一个程序员应该做的。今天打游戏,明天看电影,后天炒 股,那么你就等着三十五岁下岗。如果你不能够认同编程和思考是比其它事情更有吸引力的,那么你不必学编程,集中精力去做最喜欢的事情或许会有更大的成就。
附:如何成为一名黑客(中文版) http://translations.readthedocs.org/en/latest/hacker_howto.html 
附:如何成为一个优秀的程序员视频讲座  http://www.akae.cn/video/Marketing2/index.html 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
目录 历史 前言 I. C语言入门 1. 程序的基本概念 1. 程序和编程语言 2. 自然语言和形式语言 3. 程序的调试 4. 第一个程序 2. 常量、变量和表达式 1. 继续Hello World 2. 常量 3. 变量 4. 赋值 5. 表达式 6. 字符类型与字符编码 3. 简单函数 1. 数学函数 2. 自定义函数 3. 形参和实参 4. 全局变量、局部变量和作用域 4. 分支语句 1. if语句 2. if/else语句 3. 布尔代数 4. switch语句 5. 深入理解函数 1. return语句 2. 增量式开发 3. 递归 6. 循环语句 1. while语句 2. do/while语句 3. for语句 4. break和continue语句 5. 嵌套循环 6. goto语句和标号 7. 结构体 1. 复合类型与结构体 2. 数据抽象 3. 数据类型标志 4. 嵌套结构体 8. 数组 1. 数组的基本概念 2. 数组应用实例:统计随机数 3. 数组应用实例:直方图 4. 字符串 5. 多维数组 9. 编码风格 1. 缩进和空白 2. 注释 3. 标识符命名 4. 函数 5. indent工具 10. gdb 1. 单步执行和跟踪函数调用 2. 断点 3. 观察点 4. 段错误 11. 排序与查找 1. 算法的概念 2. 插入排序 3. 算法的时间复杂度分析 4. 归并排序 5. 线性查找 6. 折半查找 12. 栈与队列 1. 数据结构的概念 2. 堆栈 3. 深度优先搜索 4. 队列与广度优先搜索 5. 环形队列 13. 本阶段总结 II. C语言本质 14. 计算机中数的表示 1. 为什么计算机用二进制计数 2. 不同进制之间的换算 3. 整数的加减运算 3.1. Sign and Magnitude表示法 3.2. 1's Complement表示法 3.3. 2's Complement表示法 3.4. 有符号数和无符号数 4. 浮点数 15. 数据类型详解 1. 整型 2. 浮点型 3. 类型转换 3.1. Integer Promotion 3.2. Usual Arithmetic Conversion 3.3. 由赋值产生的类型转换 3.4. 强制类型转换 3.5. 编译器如何处理类型转换 16. 运算符详解 1. 位运算 1.1. 按位与、或、异或、取反运算 1.2. 移位运算 1.3. 掩码 1.4. 异或运算的一些特性 2. 其它运算符 2.1. 复合赋值运算符 2.2. 条件运算符 2.3. 逗号运算符 2.4. sizeof运算符与typedef类型声明 3. Side Effect与Sequence Point 4. 运算符总结 17. 计算机体系结构基础 1. 内存与地址 2. CPU 3. 设备 4. MMU 5. Memory Hierarchy 18. x86汇编程序基础 1. 最简单的汇编程序 2. x86的寄存器 3. 第二个汇编程序 4. 寻址方式 5. ELF文件 5.1. 目标文件 5.2. 可执行文件 19. 汇编与C之间的关系 1. 函数调用 2. main函数和启动例程 3. 变量的存储布局 4. 结构体和联合体 5. C内联汇编 6. volatile限定符 20. 链接详解 1. 多目标文件的链接 2. 定义和声明 2.1. extern和static关键字 2.2. 头文件 2.3. 定义和声明的详细规则 3. 静态库 4. 共享库 4.1. 编译、链接、运行 4.2. 动态链接的过程 4.3. 共享库的命名惯例 5. 虚拟内存管理 21. 预处理 1. 预处理的步骤 2. 宏定义 2.1. 函数式宏定义 2.2. 内联函数 2.3. #、##运算符和可变参数 2.4. 宏展开的步骤 3. 条件预处理指示 4. 其它预处理特性 22. Makefile基础 1. 基本规则 2. 隐含规则和模式规则 3. 变量 4. 自动处理头文件的依赖关系 5. 常用的make命令行选项 23. 指针 1. 指针的基本概念 2. 指针类型的参数和返回值 3. 指针与数组 4. 指针与const限定符 5. 指针与结构体 6. 指向指针的指针与指针数组 7. 指向数组的指针与多维数组 8. 函数类型和函数指针类型 9. 不完全类型和复杂声明 24. 函数接口 1. 本章的预备知识 1.1. strcpy与strncpy 1.2. malloc与free 2. 传入参数与传出参数 3. 两层指针的参数 4. 返回值是指针的情况 5. 回调函数 6. 可变参数 25. C标准库 1. 字符串操作函数 1.1. 初始化字符串 1.2. 取字符串的长度 1.3. 拷贝字符串 1.4. 连接字符串 1.5. 比较字符串 1.6. 搜索字符串 1.7. 分割字符串 2. 标准I/O库函数 2.1. 文件的基本概念 2.2. fopen/fclose 2.3. stdin/stdout/stderr 2.4. errno与perror函数 2.5. 以字节为单位的I/O函数 2.6. 操作读写位置的函数 2.7. 以字符串为单位的I/O函数 2.8. 以记录为单位的I/O函数 2.9. 格式化I/O函数 2.10. C标准库的I/O缓冲区 2.11. 本节综合练习 3. 数值字符串转换函数 4. 分配内存的函数 26. 链表、二叉树和哈希表 1. 链表 1.1. 单链表 1.2. 双向链表 1.3. 静态链表 1.4. 本节综合练习 2. 二叉树 2.1. 二叉树的基本概念 2.2. 排序二叉树 3. 哈希表 27. 本阶段总结 III. Linux系统编程 28. 文件与I/O 1. 汇编程序的Hello world 2. C标准I/O库函数与Unbuffered I/O函数 3. open/close 4. read/write 5. lseek 6. fcntl 7. ioctl 8. mmap 29. 文件系统 1. 引言 2. ext2文件系统 2.1. 总体存储布局 2.2. 实例剖析 2.3. 数据块寻址 2.4. 文件和目录操作的系统函数 3. VFS 3.1. 内核数据结构 3.2. dup和dup2函数 30. 进程 1. 引言 2. 环境变量 3. 进程控制 3.1. fork函数 3.2. exec函数 3.3. wait和waitpid函数 4. 进程间通信 4.1. 管道 4.2. 其它IPC机制 5. 练习:实现简单的Shell 31. Shell脚本 1. Shell的历史 2. Shell如何执行命令 2.1. 执行交互式命令 2.2. 执行脚本 3. Shell的基本语法 3.1. 变量 3.2. 文件名代换(Globbing):* ? [] 3.3. 命令代换:`或 $() 3.4. 算术代换:$(()) 3.5. 转义字符\ 3.6. 单引号 3.7. 双引号 4. bash启动脚本 4.1. 作为交互登录Shell启动,或者使用--login参数启动 4.2. 以交互非登录Shell启动 4.3. 非交互启动 4.4. 以sh命令启动 5. Shell脚本语法 5.1. 条件测试:test [ 5.2. if/then/elif/else/fi 5.3. case/esac 5.4. for/do/done 5.5. while/do/done 5.6. 位置参数和特殊变量 5.7. 函数 6. Shell脚本的调试方法 32. 正则表达式 1. 引言 2. 基本语法 3. sed 4. awk 5. 练习:在C语言中使用正则表达式 33. 信号 1. 信号的基本概念 2. 产生信号 2.1. 通过终端按键产生信号 2.2. 调用系统函数向进程发信号 2.3. 由软件条件产生信号 3. 阻塞信号 3.1. 信号在内核中的表示 3.2. 信号集操作函数 3.3. sigprocmask 3.4. sigpending 4. 捕捉信号 4.1. 内核如何实现信号的捕捉 4.2. sigaction 4.3. pause 4.4. 可重入函数 4.5. sig_atomic_t类型与volatile限定符 4.6. 竞态条件与sigsuspend函数 4.7. 关于SIGCHLD信号 34. 终端、作业控制与守护进程 1. 终端 1.1. 终端的基本概念 1.2. 终端登录过程 1.3. 网络登录过程 2. 作业控制 2.1. Session与进程组 2.2. 与作业控制有关的信号 3. 守护进程 35. 线程 1. 线程的概念 2. 线程控制 2.1. 创建线程 2.2. 终止线程 3. 线程间同步 3.1. mutex 3.2. Condition Variable 3.3. Semaphore 3.4. 其它线程间同步机制 4. 编程练习 36. TCP/IP协议基础 1. TCP/IP协议栈与数据包封装 2. 以太网(RFC 894)帧格式 3. ARP数据报格式 4. IP数据报格式 5. IP地址与路由 6. UDP段格式 7. TCP协议 7.1. 段格式 7.2. 通讯时序 7.3. 流量控制 37. socket编程 1. 预备知识 1.1. 网络字节序 1.2. socket地址的数据类型及相关函数 2. 基于TCP协议的网络程序 2.1. 最简单的TCP网络程序 2.2. 错误处理与读写控制 2.3. 把client改为交互式输入 2.4. 使用fork并发处理多个client的请求 2.5. setsockopt 2.6. 使用select 3. 基于UDP协议的网络程序 4. UNIX Domain Socket IPC 5. 练习:实现简单的Web服务器 5.1. 基本HTTP协议 5.2. 执行CGI程序 A. 字符编码 1. ASCII码 2. Unicode和UTF-8 3. 在Linux C编程中使用Unicode和UTF-8 B. GNU Free Documentation License Version 1.3, 3 November 2008 参考书目 索引
### 回答1: 《Linux C编程一站式学习》是由宋劲杉编写的一本关于Linux C编程的教材,主要介绍了Linux系统下C语言的基础知识和常用编程技巧。这本教材以文章简洁明了、逻辑性强、实例丰富等特点而受到广大编程学习者的欢迎。 《Linux C编程一站式学习》首先从Linux环境的搭建开始,介绍了Linux操作系统的基本概念和架构,包括文件系统、进程管理、内存管理等方面的知识。随后,教材详细介绍了C语言的基本语法、数据类型、运算符等内容,帮助读者建立起对C语言的基本理解。 接下来,教材介绍了Linux下的C编程工具和开发环境,包括GCC编译器、Makefile文件、调试工具等,使读者能够顺利地进行C程序的编译和调试。同时,还提供了大量的实例代码和实践项目,帮助读者通过实际操作加深对C语言和Linux编程的理解。 此外,《Linux C编程一站式学习》还专门介绍了Linux下的网络编程、多线程编程、进程间通信等高级主题。这些内容有助于读者深入了解Linux系统的底层机制和编程技巧,提升自己的编程能力。 总而言之,《Linux C编程一站式学习》是一本系统全面介绍Linux下C编程的教材,适合初学者和有一定编程基础的读者阅读。通过学习此书,读者能够掌握Linux环境下的C语言编程技能,为进一步深入学习和应用打下坚实的基础。 ### 回答2: 《Linux C编程一站式学习》是由宋劲杉编写的一本关于Linux C编程的教材。该书主要针对初学者,通过系统地介绍Linux系统、C语言及相关编程知识,帮助读者快速入门并掌握Linux C编程。 这本书共包含七个章节,分别是Linux的基础知识、Linux常用命令、Linux系统编程基础、C语言基础、C语言高级特性、Linux C编程实例和Makefile的使用。 在第一章的基础知识部分,作者详细介绍了Linux操作系统的历史、特点以及常见的发行版。第二章中,读者将学习到如何使用常用的Linux命令进行文件操作、目录管理以及常见的文本处理任务。 第三章和第四章分别介绍了Linux系统编程的基础知识和C语言的基础知识。在这两章中,读者将学习到如何使用系统调用、文件I/O、进程控制和信号处理等Linux系统编程的关键技术,同时也将学会C语言的基本语法、数据类型、函数等知识。 第五章则深入讲解了C语言的高级特性,包括指针、内存管理、结构体、位运算等。这些知识对于理解和编写复杂的C程序非常重要。 第六章和第七章给出了一些实例,通过实际的代码演示如何使用Linux C编程进行文件操作、进程间通信、网络编程等。 此外,《Linux C编程一站式学习》还介绍了Makefile的使用,这是一个用于自动化编译和构建项目的工具,对于更加高效地管理和组织C程序非常有用。 总之,通过阅读《Linux C编程一站式学习》,读者可以全面了解Linux系统、C语言和相关编程知识,并通过实例的演示掌握Linux C编程的技巧和方法,是一本非常实用的学习资料。 ### 回答3: 《Linux C编程一站式学习》是宋劲杉先生所著的一本关于Linux下C编程的书籍。这本书以实例为基础,讲解了Linux下C编程的各个方面,涉及了C语言基础知识、Linux系统调用、进程管理、线程编程、文件操作等内容。 书籍以通俗易懂的语言和丰富的实例详细介绍了C语言的基本语法和开发环境的搭建,对初学者非常友好。在讲解Linux系统调用时,通过介绍进程管理、线程编程以及进程间通信等内容,帮助读者深入理解Linux操作系统的原理和机制。 值得一提的是,书中重点讲解了gcc编译器的使用方法和调试技巧,使读者能够更好地理解和掌握C语言程序的编译和调试过程。此外,书中还介绍了常见的Linux工具和库函数,如make、gdb、pthread等,帮助读者提高开发效率和代码质量。 总体来说,《Linux C编程一站式学习》是一本非常实用的Linux C编程入门教材。通过阅读本书,读者可以系统地学习并运用C语言进行Linux下的程序开发。无论是新手入门还是有一定经验的开发者,都可以从中受益。此外,书籍中的实例代码也可以帮助读者进一步加深对C语言的理解和应用。 推荐这本书给对Linux C编程感兴趣的读者,它会成为你学习和掌握Linux下C编程的良好指南。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值