一、基础研究
之前基于tcc、tlink实现一个新的编译连接工具cc.exe,用到的文件有cs.lib、c0s.obj、main.obj,其中main.obj是我们自己加入的文件,它可以实现开始显示彩色字符串“welcome to c”,等待用户按键后执行程序,现在我们要把它替换为下面的程序编译成的obj文件:
观察程序,发现在定义指针code和函数指针f的时候用到了extern关键字。extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。这是一个声明语句,但是在当前程序中没有定义,所以我们要在其他文件中对它们进行定义。
这里main函数的功能为用户输入字符串a和b以及符号ch,判断输入的符号并调用相应函数进行计算。
写一个程序mc.c,用cc编译后运行。
这需要我们把实现“+、-、*、/”的函数和函数指针的定义在mc.c中实现。
编写程序如下:
结果编译出现错误。这说明**f和*f[4]在这里是不一样的,这是为什么呢?
既然不能直接初始化指针f,那么我们就定义一个函数指针数组来存放函数的首地址,再把这个数组的首地址赋给指针f。即指针f存储的是函数数组元素的地址。程序如下:
运行结果和程序a.c编译连接的结果是一样的。
那么应该怎么理解这种开发模式呢?在这里我们的程序里甚至不用写主函数,只需要写子函数以及对一些变量进行初始化,而要执行的主函数、要执行的语句都已经封装在编译工具里,这是比较高度地封装,但是它也有局限性,比如只能实现操作符的扩展,只能对两个数进行计算等。
二、扩展研究
(1)**f和*f[4]在这里是不一样的,这是为什么呢?
答:只有*f和f[]能够随意互相替换,因为它们的数据都是顺序存储的,而数组和指针的一个最大的区别就是数组能够注明数据存储的顺序,比如f[][3]={{1},{2,3},{4,5,6}}在内存中的存储数据是100230456.一维以上的数组和一级以上的指针的存储数据的方式已经是不同的了,所以不能互换了。
三、研究总结
我觉得我现在对封装的理解是它可以使程序更具有针对性,专门用来解决一个问题或者一系列问题。它在一定程度上减少了程序的可扩展性,但是加强了程序的精简度和针对性。也就是说,实现一个功能变得更加简单和快速了,而要丰富一个项目程序,我们要做的是增加它的功能模块而不是加大单个程序。这正是符合电脑组成原理、编程原理、人类社会的运行规律,即有序,分工明确,各部分专精,使单个单位的效率达到最大。