开源项目:新编电类专业《C语言程序设计》教材
0赞
发表于 8/26/2010 7:13:45 PM
阅读(35687)
继发表《卓越的教练是如何训练高手》博文之后,在初学者中引起了很大的反响。经过很长时间的思考和斗争之后,于是决定开始写作《C语言程序设计》教材。
**************************************************************************************************
☛ 特别声明:为了更好地普及C语言,让更多的人受益,因此从一开始我就将这本书定位为开源的《C语言程序设计》教材,希望更多的热心人参与,将这本书修改得更好。
虽然本书可以免费下载,但还是决定以PDF文件格式提供给读者,由我统一来维护和更新,这样就不会出现多个不同的版本。凡是对本书做出实际性价值的作者,我将一一在本书的附录中公布贡献者的名字等关键信息。
**************************************************************************************************
每一种编程语言都有它自己的各种语法和语义,对于电类专业来说,其中一些特性在为实时嵌入式系统编写的软件中比在桌面应用程序中更重要。比如,为实时嵌入式系统写软件需要充分理解整型数据类型,以及用于操作位和字节的功能。本书详细地描述了如何使用C的特性来实现这些功能,这些特性在为计算机专业编写的C语言教程中,往往讲得不够详细,通常只有经过一定的实践后才能彻底掌握。
1. “/”与“%”
对于初学者来说,千万别小看“/”与“%”等运算符的使用,而往往大多数教科书上给出的示例非常简单(比如,5/3和7%4),但由于缺乏针对性与实用性,到头来初学者还是不会编程。如果针对8位微控制器的话,其最佳的示例如下:
*pucBuf++ = bp;
*pucBuf++ = ((unsigned int)pfuncTask) / 256 ; // 保存返回地址的高8位字节
*pucBuf = ((unsigned int)pfuncTask) % 256 ; // 保存返回地址的低8位字节
并详细解释如下:
右移一位相当于除以2,那么右移n位相当于除以2n。由此可见,如果仅需截取16位地址的高8位字节,那么只需要除以28(256)即右移8次,其高8位为0,低8位就是所要的返回地址。与此同时,对于低8位地址数据来说,即便它的每一位都为“ 1”,也就是说其最大值为255,那么只要采用求余运算(模运算),即可截取16位地址的低8位字节。
2. pucBuf[i]与*(pucBuf+i)
由于++和*同优先级,其结合方向为“自右而左”,因此“*pucBuf++= bp;”等价于“*(pucBuf++)=bp;”,同样也等价于“*pucBuf= bp;pucBuf++”。也就是说,先得到“pucBuf指向的变量的值(即*pucBuf)”,然后再使“pucBuf+1—>pucBuf”,这样在下一次循环时,*pucBuf就是下一个元素的值,即“先保存bp的当前值,然后再使pucBuf值加1”。因此一个用“数组和下标”实现的表达式可等价地用“指针和偏移量”来实现,那么表达式中可使用具有下标的指针pucBuf[i],即pucBuf[i]与*(pucBuf+i)的含义是一样的,其示例如下:
pucBuf[0] = bp;
pucBuf[1] = *((data unsigned char*)SP); // 保存返回地址的高8位字节
pucBuf[2] = *((data unsigned char*)((char)(SP-1))); // 保存返回地址的低8位字节
尽管这种风格的代码可阅读性更好,但是通过分析反汇编代码可以明显地看出来,在80C51上执行效率更低。而对于其它的CPU,则可能执行效率很接近,比如,32位ARM处理器。
3. 对于初学者来说,如何恰当地写出if与while语句括号中的表达式也是一个难点,但必须熟练掌握和运用,因此希望能够引起初学者的充分重视。
4. 以往的经验表明,如果仅仅以结果为导向,而不深究“用多种方法实现同一个功能之间的细微差别”,犹如“练拳不练功、到老一场空”,其结果必然导致“知其然而不知其所以然”。
……
由于本人并非C语言专家与程序设计高手,因此在写作过程中难免会出现错误,因为编程与写作毕竟是两回事,敬请大家谅解,并来信(zlg3@zlgmcu.com)帮助指正,以免误人子弟。
周立功
2010年8月23日
