c程序中,指针一般用来:
引用动态分配的数据结构
#define new(type) (type*) calloc(sizeof((type),1)
[...]
node = new(struct codeword_entry)
实现引用调用(call by reference)
访问和迭代数据元素
传递数组参数
在c和c++程序中,将数组传递到函数和作为结果返回,都要用到指针。在c代码中,将数组名作为函数参数时,实际上传递给函数的是数组第一个元素的地址。因而,函数执行时对数组中的数据做出的任何修改都将影响到数组中的元素。
类似函数返回也只是返回数组的指针。因此当函数在数组中生成结果并返回相应的指针时,一定要确保该数组不是在函数的栈上分配的局部变量。如果数组是局部变量要记得确保该数组不是在函数栈上分配的局部变量。避免这一问题的方法是将这类数组声明为static
引用函数
作为其他指的别名
代表字符串
直接访问系统内存
结构还是指向结构的指针?
把指针作为参数的方法的两个优点:既可以工作在较新的c上,也可以工作较旧的c上;只传递一个地址信息。
缺点:缺少对数据的保护。
把结构作为参数传递的一个优点是函数处理的原始数据的副本,这就比直接处理原始数据安全。
以面向对象方式编程
可以将数据元素和函数指针聚合成结构,模拟类的字段和方法,创建与类相仿的实体。
struct domain{
int dom_family;
char *dom_name;
void (*dom_init)(void);
[...]
int (*dom_rtattach)(void **,int);
int dom_rtoffset;
int dom_maxrtkey;
};
//after init the struct,used like class
for(dom = domains;dom;dom = dom -> dom_next){
if(dom -> dom_family == i && dom -> dom_rtattach){
dom -> dom_rtattach((void **)&nep ->ne_rtable[i],
dom -> dom_rtoffset);
break;
}
}
实际上,由于同一类别的不同对象共享它们的方法,所以,程序常常在“对象”结构中只存储指向另外结构的指针。由这个结构给出指向实际方法的指针,从而达到不同对象间共享方法指针的目的。-》面向对象语言中的“虚方法”和“多态编程”
将共享同一块存储区域的项聚合起来。某一时刻,共享该区域的这些项中只有一项可以访问。
主要用途:
实现多态
多态数据
enum msg_type{
CALL = 0;
REPLY = 1;
};
配置(configuration)可以控制的软件系统,允许开发者编译、维护和发展源代码的单一正式版本
根据依赖关系隔离的原则,配置信息一般分为几个文件。影响系统如何编译的配置信息(例如,安装目录、工具名称和路径、是否存在可执行文件中包括调试富豪、应用的优化级别、使用的库和目标文件),经常以变量定义的形式表示在项目的制作文件中。
如
我们可以将系统的源代码想象成在空间和时间两个方向上的延伸。代码,组织成文件和目录的形式,占据空间;同时,同一代码还随着时间的推移不断演化。
修订控制--版本控制
设计良好的项目,都会预先为测试系统的全部或部分功能提供相应的措施。这些措施可能隶属于一份经过深思熟虑,用来验证系统运作的计划,也可能是系统的开发者在实现系统的过程中实施的非正式测试活动的残余。
最简单的测试代码是一条生成日志(logging)或调试(debugging)输出的语句。跟踪语句所在的地点一般也是算法运行的重要部分。
[...]
软件系统并非知识代码。因此,许多编码指导原则都延伸到开发过程的其他领域,包括文档、生成和发布过程的组织。
至少,许多指导原则都会规定标准的文档,以及编写它们的格式。
阅读一小时代码所得到的信息只不过相当于阅读一分钟文档
列出几种最具代表的:
系统规格说明文档:详细叙述系统的目标、系统的功能需求、管理和技术上的限制、以及成本和日程等要素。通过系统的规格说明文档能够了解所阅读代码的实际运行环境。
软件需求规格说明:提供对用户需求和系统总体构架的高层描述,并且详细记述系统的功能和非功能性需求,比如数据处理、外部接口、数据库的逻辑模式以及设计上的各种约束。是阅读和评估代码的基准
设计规格说明:一般描述系统的架构、数据和代码结构,还有不同模块之间的接口。面向对象的设计会勾画出系统的基本类型以及公开方法。细化的设计规格一般还包括每个模块(或类)的具体信息,比如它执行的具体处理任务、提供的接口,以及与其他模块或类之间的关系。还会描述采用的数据结构,适用的数据库模式等。认知代码结构的路线图、阅读具体代码的指引
系统的测试规格说明:包括测试计划、具体的测试过程、以及实际的测试结果。每个测试过程都会详细说明它所针对的模块以及测试用例使用的数据。
许多用户文档:功能描述、安装说明、介绍性的导引、参考手册和管理员手册。而且常常是我们唯一有可能获得的文档。。。在接触一个未知系统时,功能性的描述和用户指南可以提供重要的背景信息,从而更好地理解阅读代码所处的上下文。从用户参考手册中,我们可以快速获取应用程序的外观与逻辑上的背景知识。从管理员手册可以得知代码的接口、文件格式和错误消息的详细信息。
文档有可能提供不恰当的信息,误导我们对源代码的理解。
从系统的源代码洞悉系统的架构,不是一件容易的事。然而,在识别出重要的架构元素之后,那么,浏览整个系统,了解系统的结构和属性,以及规划增加、修改和重构活动都会变得更为容易。这是因为,一旦提取出系统的架构行特征,我们就立即与系统的创建者共享一套语义丰富的词汇。另外,对系统架构的理解,能够帮助我们了解交互的类型、通信模式和代码结构。
常见、重要的结构可以归类为少数迥然相异的架构类型:集中式存储库(centralized repository)、数据流(data-flow)、面向对象(object-oriented)或分层(layered)架构。
集中式存储库:web应用
面向对象:建立在维护自身状态并相互作用的对象上。系统的架构由不同的类或对象之间的关系,以及对象交互的方式来定义。UML来表达系统的模型。
这关心的层次是系统中的控制流程和数据流。分析系统架构时,可以关注:
切片:将程序片(program slice)看作能够影响变量的值的一段程序。(dashplayer修改原则,我的理解)
事件驱动的系统
许多系统中,控制决策通过响应外部生成的事件来完成。(嵌入式开发,关系型数据库的触发器)
实现方式可以有许多种:
事件广播给一系列的事件侦听者
for(int i = 0;i < list.length;i ++){
((ContainerListener)list[i]).containerEvent(event);
}
硬件中断
围绕事件循环构建,该循环不断地查询事件并执行相应的处理
while(XtAppPending(appCtx))
XtAppProcessEvent(appCtx,XtIMALL);
基于类的事件处理给应用程序带来两个明显优点:
* 事件可以以属性的形式承载附加信息,消除了无类型、通用的事件参数
* 通过继承可以实现一个事件层次,事件层次又能够驱动事件分派策略 ??没搞懂
下面通过代码理据下(反正就这两句话我是不懂)
public abstract class ArgoEvent extends EventObject implements ArgoEventTypes{
protected int _eventType = 0;
public ArgoEvent(int eventType,Object src){
super(src);
_eventType = eventType;
}
}
//上面的ArgoEvent类扩展了Java EventObject,ArgoEvent接下来又被ArgoModuleEvent和ArgoNotationEvent类所扩展
系统管理器
需要多个进程并发执行的系统,经常采用系统管理器控制模型。一个单独的系统组件起到集中式管理器的作用,负责启动、停止和协调其他系统进程和任务的执行。
模块和命名空间
对象是一个运行期间的实体
范型(数据结构或算法)
抽象数据类型
库是模块的有组织集合
进程和过滤器(过滤器是一种特殊的进程)
软件组件(程序构成中典型的自包含单元)(JavaBeans)
许多系统在设计时就遵循已经确立的架构。框架
因为可重用的架构,因为要满足一系列各种各样的应用程序,所以会比量身定做的应用的结构更为复杂。