从零开始学C语言
@阆苑祁寒
更新时间:2019-12-31
更新说明:此版本是最终版本。初始版本有关helloworld的内容调到了附录部分。
pdf版本下载链接:
写在前面:本文从一个初学者的角度,给出了对C语言的简单理解。最近一次更新调整了之前的叙述方式。
目录 |
|
Part1 |
从Hello World讲起 |
Part2 |
知识结构梳理 |
Part3 |
一路走来的习题 |
Part4 |
实践心得和疑难释义 |
Part5 |
结束语 |
Part6 |
附录 |
如有谬误,敬请指出!
Part1 从Hello World讲起
“C语言是一门计算机语言。”这表明:
(1)C语言是源于计算机的,通过C语言,可以接触到计算机的某些工作原理。
(2)C语言是一门语言,既有和汉语和英语等语言相似的特性,也有语言所必须的语法结构。
(3)C语言是计算机语言,可唯一解释性使得C语言有别于其他语言,反之,只要掌握了每一个语句的原理,很容易学好计算机语言。
要知道,想要学习好每一门学科,都必须了解其历史,这也是历史这门学科的主要价值。第一台计算机是美国宾夕法尼亚大学设计的用于弹道计算的ENIAC(英耐克),而与之密切的网络则是为了弥补单一通讯方式的不足而被发明。可见,计算机和网络都是随战争诞生的,以及运筹学(优化算法的理论基础)也是在二战期间应运而生。因此,认为战争催化科技发展这句话毫不为过。
简单了解ENIAC后,认识到其架构是具有时代局限性的,其程序和数据存储是分开的,数据通过类似于电话接线局的接线方式来连接对应的程序。这是相当麻烦的,以至于从事曼哈顿计划的冯·诺依曼,改进了计算机的架构,将程序和数据放在一起,这也是冯·诺依曼被公认为计算机之父的原因。相反,现代电话都是程控接线,这表明技术的发展也永远并不是单一领域的。
但是,这样的简化并不能适应大规模的运算。众所周知,计算机数据和程序的存储方式是二进制代码,用1和0分别代表数字电路中的开和关,也即布尔代数中真(true)和假(false),一个二进制位称为1 bit(比特),通常将8个二进制位称为1 Byte(字节),在内存作为一个存储空间。根据数理逻辑运算定义加和乘,就完成了传统计算机体系的构建。
必须指出,我们公认的计算机编码表ASCII表(American Standard Code for Information Interchange)就恰好有128=28个特殊字符(后被扩充到256个特殊字符),依次从0编号到127,对应1字节长度的二进制数字的十进制大小。
尽管将计算机架构中的数据存储和程序放在一起,已经大大提高了计算机的效率。但对于程序本身而言,常常会出现一行固定指令被重复使用多次的情形。因此考虑将其提炼为机器语言(汇编语言),进而再一次提高了计算机的效率。进一步,将重复出现的机器语言再一次提炼,就得到了高级语言。
第一门高级语言C语言,具有划时代的意义,它连接了计算机组成(硬件)和计算机程序(软件),这对于入门计算机学科是极好的。
不可否认,C语言并非十全十美。一方面,面向过程的灵活性(指针)常常会因为小小的错误而使整个程序乃至计算机崩溃(早期计算机内存并未设置程序与操作系统,以及不同程序之间的界限)。另一方面,尽管在函数和宏中初步体现了大规模程序开发的模块化思想和封装思想,但是例如C语言的函数不可互相嵌套等缺陷使得灵活性下降。除此之外,作为语言本身先于语法而出现的特性,决定了基于C语言的计算机语言的语法结构,在发展中必然是逐渐完善的。C语言一些看似不符合常理的语句,它们的出现就好解释了。
局部来说,针对不同的目的,新出现的计算机语言在C语言的基础上进行各自的改良。但从总体来说,计算机语言逐渐从面向过程到面向对象。程序的封装,使得计算机程序员只需要查阅参考手册相关包的使用说明,如无必要,不再去关注内部封装的算法本身,这也是作为工程学科的一个重要特点。这些后续发展而来的语言也就因此被称为面向对象的语言。
最后,包括C语言在内的诸多计算机语言,第一课与其说是认识计算机语言,不如说是认识最基本的语句Hello World里的所包含的全部信息及相关附录!在此之前,你的手头应该拥有一本C语言的教材,下面将一本讲得非常明晰的教材推荐给大家:
《C语言程序设计教程》·姜恒远·高等教育出版社
以下便是C语言的Hollow world程序(不止一种写法,但它是最为经典的):
#include < stdio.h> int main(void) { printf("Hello, world! /n"); return 0; } |
最初拿到这个程序时,除了几个类似于英文单词的记号,其余的内容,就像初学一门新的课程一样,其实大脑是一片空白的。也许好奇心驱使你稍稍改动这个程序,但更多的还是受改动范围的局限和因为报错而沮丧罢了。
下面对这个最基本的程序涉及到的基本语法列出如下:
☆ #include
☆ int main(void) 函数头的声明形式,声明了一个名为main的函数,返回值类型是int类型,形式参数是void空类型。需要指出,main函数是C语言的主函数,有且仅有一个。一方面,编译过程总是从主函数开始,再根据调用关系读取其他的函数;另一方面,同名的函数会造成编译冲突。
☆ {} 表示复合语句,常用在循环结构和函数体中,如果没有花括号,C语言默认只逐级向下读取一行,其余内容作为花括号(如果有)中的最大层级解释。需要注意,C语言不像Python,会受到缩进的影响,反过来,有一个标准的编程规范,对于C语言的学习相当重要。
☆ printf("Hello, world! /n"); 调用了头文件中的printf函数,输出字符串常量,’\n’作为转义字符表示换行。
☆ return 0; 函数返回值,相当于右花括号的作用,用于结束对应类型的函数。事实上,int类型的主函数有无返回值,对于编译成功与否没有影响。严格来说,对应数据类型的函数,必须要有对应数据类型的返回值。在初学时需要注意,返回值并不是输出在屏幕上的值,而是函数本身有了一个值,也就是如果在另一个函数(主调函数)中调用这个函数(被调函数),这个函数的返回值可以赋给一个变量或者输出。
红色字体的部分可以参考“函数”和“结构化程序设计”章节的内容,高亮字体的部分可以参考“数据结构”章节的内容,紫色字体的部分可以参考“基本运算和输入输出”章节的内容。
更多细节部分,可以参考主流C语言参考书自行补充完整。需要指出,ASCII表、优先级与结合级表、输入输出函数转换说明符表和常用转义字符表,是初学C语言时最为重要的四个表,应该作为工具经常使用。
其余更深入的内容,在学到对应的知识后将一目了然。此时,就没有必要去盲目补充了,与其沉溺于起点寸步不前,不如走向远方,等学有所成时再回头看起点,将恍然明悟,且获益匪浅!
Part2 知识结构梳理