很长时间以来,都是在用C语言写东西。也一直在思考,如何能很好的掌握C,查过很多资料,也作过一些尝试,于是整理成此文。
在大部分情况下,我们会写或者使用一个C库,然后被应用程序使用,运行在Linux的系统上。于是,就有了基于C语言的知识结构:
App
------------------- C API
C, libc
------------------- Posix API
Linux Kernel
整体结构大致有上面的三层,五个部分。大致思路是:必须了解上层的需求,和下层能提供的功能。
- App:使用C库的应用程序
- C API:C库定义的API
- C, libc:C语言和C语言标准库
- Posix API:Linux内核定义的接口
- Linux Kernel:Linux内核
App
引用程序代表这需求,该部分了解即可。你需要了解他们,然后从他们的角度去看待你写的库。
C API
C API是你提供给应用层序的界面,应用程序将参考它进行对接。如何定义好它,是你需要一直考虑的问题,最好的方法就是模仿,参考Posix API等的定义方试即可。
C,libc
对于C语言的学习,请考虑一下你写C代码的步骤:写代码、编译、运行、调试。搞定每个步骤的细节,将对你的学习有很大的提升。
写代码
写代码首要的问题就是Coding Style,包括:变量命名、代码的格式等。比如,Linux Kernel有自己的Coding Style,GNU项目也有它的Coding Style,还有NASA的Coding Style等等,这些Coding Style是让参与的人能够统一,不要乱了风格。若是新手,参考一个用的比较多的即可(参见Stack Overflow上的讨论),然后形成自己的代码风格。这是一个长期的过程,需要日积月累,以及长时间的思考。那么,有个问题是Coding Style有什么用?一是它有助于团队开发。二是有助于提升代码的可阅读性。三是作为新手,对提升很有帮助。具体到写代码,只要项目或模块有一致的风格即可。
然后,就是重构,重构的意思时候,随着需求的增加,代码越来越多,原有的代码结构已经阻碍了开发的效率,需要重新整理。原来看过一本《重构:改善既有代码的设计》,好像是基于Java的,不过重构思路还是可以运用到C上面的。代码重构也是需要长期积累和思考。
再然后就是设计模式,设计模式的意思是说,当你面对一个需求时,有特定的代码结构可以参考。那种代码结构是经过别人优化过的,你就不要再发明*了。当然,某个设计模式只是适用于特定的代码场景。关于C语言的设计模式,可以参考Stack Overflow上的讨论。
关于写代码的应该不止这些,这正是我们思考的好时机。
编译
编译的第一步是编译工具gcc之类的,包含了对编译过程的理解。你肯定需要了解Linux的命令行工具。然后,你会用到Makefile,甚至Automake工具来让编译变得简单。再然后,你会用到Shell来自动化编译过程。
运行
这一块的内容,其实挺多的。不能单纯的理解为,C程序的执行。你需要考虑一个问题,我写的C代码,在运行态在干嘛。因为是跑在Linux上的,所以只需要考虑两点即可:内存和CPU。即C里面定义的所有变量,存在于内存的哪里,我该如何动态管理它们。C代码是如何运行的,若是有多个线程,它们的执行机制是什么。但实际上,这里面还有很多东西,我还在观察。
调试
调试的话,就是定位程序的问题,保证程序能按预期工作。可以使用gdb工具,添加足够多的日志等技术来完成。但是,毫无疑问,你若知道程序的运行原理,调试将不是一件难事。
libc
libc虽然不是C语言的一部分,但是,它和C语言是一体的,基本上,写任何C语言都要用到它。而且,它是一个很好的C参考。
说到libc,不得不提C语言标准文档,比如:C99。标准文档是C语言的终极解释,通常不同的C编译器都会对标准有所支持。
Posix API
这部分内容不复杂,可以参考书籍《UNIX环境高级编程》。这本看起来像工具书,但是还是通读几遍吧。
Linux Kernel
这部分内容熟悉就好,了解内核在干嘛,在某些情况下是有帮助的。
总结
上面的内容只是个大纲,可执行性不强。而且他是基于Linux的,其实,其它平台也同样适用。
若是其它语言,也同样适用,只是不同的语言侧重点不一样。比如:C++可能更多用于构建一个比较大的项目。语法、使用场景、设计模式都比C更加复杂。
如果抽象层次再高一点的话,当你对一门语言熟悉到一定程度以后,语言将不在是问题的关键,实际的需求到语言之间的转换才是。就好比说话,说到一定程度,你关注的不是怎么说,而是如何说。