290 likes | 395 Views
C 语言程序设计 教学体会. 孙志岗 的 “ 个人体会 ”. 代码风格. 代码风格就是程序员的书法 比书法好学得多,基本不需要特别练习 但是坏习惯一旦养成,就像书法一样难以改变 是最易获得和实践的软件工程规则 对设计程序结构、培养团队精神都大有帮助 不给学生看到任何一个风格糟糕的例子. 标识符命名 宏全部大写 Windows 风格和 Unix 风格 VariableName variable_name 缩进 “ { ” 位置的两种风格 用 4 格 tab 还是用空格. 空格 增强单行清晰度 每行代码长不要超过 80 空行 自然段. 代码风格.
E N D
C语言程序设计教学体会 孙志岗的“个人体会”
代码风格 • 代码风格就是程序员的书法 • 比书法好学得多,基本不需要特别练习 • 但是坏习惯一旦养成,就像书法一样难以改变 • 是最易获得和实践的软件工程规则 • 对设计程序结构、培养团队精神都大有帮助 • 不给学生看到任何一个风格糟糕的例子
标识符命名 宏全部大写 Windows风格和Unix风格 VariableName variable_name 缩进 “{”位置的两种风格 用4格tab还是用空格 空格 增强单行清晰度 每行代码长不要超过80 空行 自然段 代码风格
表达式尽量简单 • 下面程序在不同编译器可能产生不同结果,而且可读性差 • a = i++ + i++ + i++; • printf("%d, %d, %d", i++, i++, i++); • for (i = 0; i != 0 && i++; ); • 很多教科书自作聪明地创造了很多复杂的题目来难为学生,就算它们的用法正确,实践中也未必用得到
全局变量要避免使用吗? • 全局变量增大了模块之间的耦合度,而且不利于排错,罪大恶极 • 这罪恶不能怪全局变量,只能怪无限制的对全局变量的改写 • 不要让全局变量有复杂的数据结构 • 一旦数据结构变了,真的大祸临头了 • 最好利用static特性用函数对其进行封装
不要把goto判处死刑 • 问题不是出在goto,而是出在对标号的滥用 • 结构化程序设计中一个被忽视的原则 • 单入口,单出口 • 只要符合此原则,什么都可以用 • goto在处理异常流程问题时,非常好用 • 退出多重循环 • 统一的错误处理
吓死人的指针 • “指针”出现,“难”字当头 • 老师吓学生,学生再吓学生的学生…… • 从原理上了解指针,它是那么简单 • 一个普通变量,其值是一个内存地址 • 格守下列原则,指针使用永不出错 • 永远要清楚每个指针指向了哪里 • 永远要清楚指针指向的位置是什么
指针的兄弟:数组 • 不要把数组和指针分开,它们是紧密相连的 • 数组最简单 • 数组名是指针,数组成员是变量 • 多维数组麻烦些 • 关键要知道它在内存中是怎么分布的
脑细胞可贵,千万别用来背 • 算符优先级 • 知道先算括号足以 • 这样方便自己,也方便他人 • 库函数用法 • 会查联机帮助、手册最重要
变量占用的字节数 • 不同平台,不同编译器,可能会迥然不同 • struct占字节数由编译参数决定 • 凡是需要字节数的地方,一律用sizeof获得
没有“真”“假” • 逻辑运算的结果只有整型数“0”和“非0” • 很多编译器给出的非0结果是1,但这是特例 • if (0) printf(“永远不会被执行”); • while (1){ /* 死循环 */}
指针指向不明 数组下标越界 数值运算溢出 除数为0 不检查函数的返回值 变量不初始化就使用 比较相等时用=,没用== 用==比较两个浮点数是否相等 返回局部变量的指针 malloc不free open不close 下列问题,要上升到阶级斗争的高度 它们编译不出错,运行很可能也不出错,但一旦出错,就让人焦头烂额
危险的scanf • scanf简便好用 • 不做参数类型匹配检查 • 不限制用户输入字符串长度 • 很多黑客攻击都是从这里开始的
\0给字符串处理带来的 • 危险 • 假如\0不存在,printf、strcpy、strcmp等都将越界访存 • n族函数可以解决此问题 • 处理字符串时,时刻要警惕\0是否在其该出现的位置
C语言三大定律 • 表达式定律 • 任何能产生数值结果的运算、操作都可以作为表达式,并可以放到任何需要数值结果的地方,只要数值类型能够匹配 • 常见的可以产生数值结果的运算和操作 • 算术、逻辑、位运算等 • ? :、&、*等 • 有返回值的函数 • 赋值 • 常见的需要数值的地方有: • 赋值 • 条件判断 • 函数调用
C语言三大定律 • 类型定律 • 任何类型都可以在任何需要类型的地方使用;用任何类型定义的变量都要占用内存 • 已知特例 • 函数返回值不能定义为数组类型 • 函数参数定义为数组类型,此时该参数不占用内存,而是共享函数调用者传入的数组空间 • 常用类型 • 基本数据类型、指针、数组、结构…… • 常见的需要类型的地方 • 定义变量 • 定义指针、数组和结构 • 函数参数和返回值 • sizeof
C语言三大定律 • 参数传递定律 • 函数调用时的参数传递永远都是传值调用,把实参的值拷贝给形参 • 实参:调用者提供的参数 • 形参:函数定义的参数 • 基本数据类型无容置疑 • struct也无容置疑 • 指针作为参数时,把指针变量的内容(就是其指向的内存地址)做了拷贝 • 数组名作为参数时,把它等同于指针看待了
要点 • 简单为美 • 宣扬“简单为美”的科学思想,摒弃刻意的复杂 • 原理为纲 • C语言复杂的表面都是简单的原理的外在表现 • 人性为本 • 计算机是人设计的,具有人性 • 面向应用 • 避免“学是一回事,使用是另一回事” • 无需背诵 • 该记的,用着就记住了;用不着的,背下来也会忘 • 没有绝对 • Match is best!
为什么追求“简单为美”? • C语言没有权威,什么都不可信 • 书当然不可信,任何书都是 • 背书更可悲 • 编译器也不可信,它只是一种实现而已 • 不同编译器、不同平台,表现往往会大相径庭 • C语言诞生的主要目标之一就是让UNIX可以跨平台。我们书写的C程序也应该极力争取跨平台 • 有些本来就是错误的用法,在某些平台上却还可以正确运行 • ANSI C也不可信 • 这个标准本身并不完备,而且并不是所有编译器都对它100%支持
为什么追求“简单为美”? • 那我们还能信什么? • 相信“简单”!!! • 最简单的用法,是被编译器支持得最好的 • “简单”易于理解、交流,便于维护
非计算机专业需要了解深入的“原理”吗? • 只要使用C语言,就必须知道“原理” • 浮于表面的使用,是无法发挥C语言的优势的 • 如果他不需要知道“原理”,肯定他不用C语言,那么就不该让他学C语言 • “原理”涉及到 • 计算机原理 • 编译原理 • 操作系统 • 算法与数据结构 • 软件工程
原理为纲 • 计算机原理 • 冯·诺依曼机 • 二进制、八进制、十六进制和十进制 • b、B、KB、MB、GB、TB • 寄存器、内存、外存的基本原理 • 流 • 编译原理 • 编译、链接过程 • 预处理指令、外部变量 • 函数的参数传递和局部变量定义 • 栈
操作系统 内存保护 数组下标越界、野指针 内存管理 动态内存分配(堆)和栈 文件管理、进程互斥 算法与数据结构 栈 结构体 软件工程 分析、设计、程序结构 结构体 协作 原理为纲
原理为纲 • C语言自身的原理 • 指针的原理 • 数组的原理 • 函数调用的原理 • 内存分配的原理 • 栈和堆 • 了解原理,就能从根上分析出一些纷繁复杂的语法规则的合理性。此外,还需要一点点人性
人性为本 • 在原理基础上,C语言为了让人使用方便,有很多人性化的设计 • 比如: • char sz[] = “A String”; • + - * / • if-else • 逻辑运算 • 不要让学生“记住”这些,而要让他们知道这些有多么地顺乎自然
面向应用 • C语言是用来实践的。能应用,比掌握一些生僻的用法更重要 • 应用中最信奉的就是“简单为美” • 软件工程思想在应用中也非常重要 • 结果正确不能说明程序好
无需背诵 • 记忆力经过漫长的12年中小学应试教育,已经锻炼到极致了 • 如果教学中指明要学生机械背诵什么,那么这个教学是失败的 • 如果考卷中有需要机械背诵才能做答的题,那么这个考卷是失败的 • 通过作业、上机,把知识自然而然地变成学生身体的一部分 • 锻炼学生查资料、联机帮助和手册等的能力
没有绝对 • 科学没有金科玉律,计算机科学更是如此 • 在不同的环境下,相同的观点会产生不同的效果 • 简单为美是基本准则,但是在用C书写像OS核心这样的代码时,效率很关键,就不能追求“简单”了 • 把选择权留给学生自己,让他们有自己的观点
C语言教学最终目的 • 让学生知道自己还远没有学会 • 让学生知道自己以后怎样继续学 • 让学生知道自己肯定能自己学会,并找到学习的乐趣与动力 • 让教师知道,自己还有不会的