<?xml version="1.0" encoding="gb2312"?>

<!-- RSS generated by oioj.net on 4/16/2004 ; 感谢LeXRus提供 RSS 2.0 文档; 此文件可自由使用，但请保留此行信息 --> 
<!-- Source download URL: http://blogger.org.cn/blog/rss2.asp       -->
<rss version="2.0">

<channel>
<title>我的IT人生</title>
<link>http://blogger.org.cn/blog/blog.asp?name=zc9706</link>
<description>zc9706的博客</description>
<copyright>blogger.org.cn</copyright>
<generator>W3CHINA Blog</generator>
<webMaster>webmaster@blogger.org.cn</webMaster>
<item>
<title><![CDATA[何谓数据结构]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=72497</link>
<author>zc9706</author>
<pubDate>2012/3/15 22:44:34</pubDate>
<description><![CDATA[<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="FONT-SIZE: 15pt; COLOR: black; FONT-FAMILY: &#1676;廍">何谓数据结构</span></b></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">数
据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成，即一个数据由那些成分数据构成，以什么方式构成，呈什么结构。数
据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系，而物理上的数据结构反映成分数据在计算机内部的存储安
排。数据结构是数据存在的形式。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">数据结构是信息的一种组织方式，其目的是为了提高算法的效率，它通常与一组算法的集合相对应，通过这组算法集合可以对数据结构中的数据进行某种操作。</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"> </span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="FONT-SIZE: 15pt; COLOR: black; FONT-FAMILY: &#1676;廍">数据结构主要研究什么？</span></b></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构，以及对数据的各种操作。因此，主要有三个方面的内容：数据的逻辑结构；数据的物理存储结构；对数据的操作（或算法）。通常，算法的设计取决于数据的逻辑结构，算法的实现取决于数据的物理存储结构。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="FONT-SIZE: 15pt; COLOR: black; FONT-FAMILY: &#1676;廍">什么是数据结构？什么是逻辑结构和物理结构？</span></b></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: 宋体">数据</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">是指由有限的符号（比如，</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">"0"</span><span style="COLOR: black; FONT-FAMILY: 宋体">和</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">"1"</span><span style="COLOR: black; FONT-FAMILY: 宋体">，具有其自己的结构、操作、和相应的语义）组成的元素的集合。</span><b><span style="COLOR: black; FONT-FAMILY: 宋体">结构</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">是元素之间的关系的集合。通常来说，一个</span><b><span style="COLOR: black; FONT-FAMILY: 宋体">数据结构</span></b><b><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i></b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"> </span><span style="COLOR: black; FONT-FAMILY: 宋体">可以表示为一个二元组：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS=(D,S)</span></i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">, //i.e., <i>data-structure=(data-part,logic-structure-part)</i></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">这里</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">D</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">是数据元素的集合（或者是</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">“</span><span style="COLOR: black; FONT-FAMILY: 宋体">结点</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">”</span><span style="COLOR: black; FONT-FAMILY: 宋体">，可能还含有</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">“</span><span style="COLOR: black; FONT-FAMILY: 宋体">数据项</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">”</span><span style="COLOR: black; FONT-FAMILY: 宋体">或</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">“</span><span style="COLOR: black; FONT-FAMILY: 宋体">数据域</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">”</span><span style="COLOR: black; FONT-FAMILY: 宋体">），</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">S</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">是定义在</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">D</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">（或其他集合）上的关系的集合，</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">S </span></i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">= { <i>R </i>| <i>R </i>: <i>D</i>×<i>D</i>×...}</span><span style="COLOR: black; FONT-FAMILY: 宋体">，称之为元素的</span><b><span style="COLOR: black; FONT-FAMILY: 宋体">逻辑结构</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">逻辑结构有四种基本类型：集合结构、线性结构、树状结构和网络结构。</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/list/chapter1.htm"><span style="FONT-FAMILY: 宋体">表</span></a></span><span style="COLOR: black; FONT-FAMILY: 宋体">和</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/tree/chapter1.htm"><span style="FONT-FAMILY: 宋体">树</span></a></span><span style="COLOR: black; FONT-FAMILY: 宋体">是最常用的两种高效数据结构，许多高效的算法可以用这两种数据结构来设计实现。</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/list/chapter1.htm"><span style="FONT-FAMILY: 宋体">表</span></a></span><span style="COLOR: black; FONT-FAMILY: 宋体">是线性结构的（全序关系），</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/tree/chapter1.htm"><span style="FONT-FAMILY: 宋体">树</span></a>(</span><span style="COLOR: black; FONT-FAMILY: 宋体">偏序或层次关系</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">)</span><span style="COLOR: black; FONT-FAMILY: 宋体">和</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/graph/chapter1.htm"><span style="FONT-FAMILY: 宋体">图</span></a></span><span style="COLOR: black; FONT-FAMILY: 宋体">（局部有序</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">(weak/local orders)</span><span style="COLOR: black; FONT-FAMILY: 宋体">）是非线性结构。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">数据结构的物理结构是指逻辑结构的存储镜像</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">(image)</span><span style="COLOR: black; FONT-FAMILY: 宋体">。数据结构</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">DS</span></i><span lang="EN-US"> </span></span><span style="COLOR: black; FONT-FAMILY: 宋体">的物理结构</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">P</span></i><span lang="EN-US"> </span></span><span style="COLOR: black; FONT-FAMILY: 宋体">对应于从</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">DS </span></i></span><span style="COLOR: black; FONT-FAMILY: 宋体">的数据元素到存储区</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">M</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">（维护着逻辑结构</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">S</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">）的一个映射：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">P</span></i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">:(<i>D</i>,<i>S</i>)<i> </i>--&gt;<i> M</i></span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: 宋体">存储器模型：</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">一个存储器</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"> M</span></i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"> </span><span style="COLOR: black; FONT-FAMILY: 宋体">是一系列固定大小的存储单元，每个单元</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">U</span></i><span lang="EN-US"> </span></span><span style="COLOR: black; FONT-FAMILY: 宋体">有一个唯一的地址</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">A</span></i><span lang="EN-US">(<i>U</i>)</span></span><span style="COLOR: black; FONT-FAMILY: 宋体">，该地址被连续地编码。每个单元</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">U </span></i></span><span style="COLOR: black; FONT-FAMILY: 宋体">有一个唯一的后继单元</span><span style="COLOR: black; FONT-FAMILY: Arial"> <i><span lang="EN-US">U'</span></i><span lang="EN-US">=succ(<i>U</i>)</span></span><span style="COLOR: black; FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">P </span></i></b><b><span style="COLOR: black; FONT-FAMILY: 宋体">的四种基本映射模型：</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">顺序（</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">sequential</span><span style="COLOR: black; FONT-FAMILY: 宋体">）、链接（</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">linked</span><span style="COLOR: black; FONT-FAMILY: 宋体">）、索引（</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">indexed</span><span style="COLOR: black; FONT-FAMILY: 宋体">）和散列（</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">hashing</span><span style="COLOR: black; FONT-FAMILY: 宋体">）映射。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">因此，我们至少可以得到</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">4×4</span><span style="COLOR: black; FONT-FAMILY: 宋体">种可能的物理数据结构：</span></p>
<table class="MsoNormalTable" style="WIDTH: 213pt" width="284" border="1" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 69.75pt; PADDING-TOP: 0cm" width="93">
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">&nbsp;&nbsp;&nbsp; </span></b></p>
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">sequential</span></b></p></td>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 76.5pt; PADDING-TOP: 0cm" width="102">
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">(sets)</span></b></p></td></tr>
<tr>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 69.75pt; PADDING-TOP: 0cm" width="93">
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">&nbsp;&nbsp;&nbsp; </span></b></p>
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">linked</span></b></p></td>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 76.5pt; PADDING-TOP: 0cm" width="102">
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">lists</span></b></p></td></tr>
<tr>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 69.75pt; PADDING-TOP: 0cm" width="93">
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">&nbsp;&nbsp;&nbsp; </span></b></p>
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">indexed</span></b></p></td>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 76.5pt; PADDING-TOP: 0cm" width="102">
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">trees</span></b></p></td></tr>
<tr>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 69.75pt; PADDING-TOP: 0cm" width="93">
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">&nbsp;&nbsp;&nbsp; </span></b></p>
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">hash</span></b></p></td>
<td style="PADDING-RIGHT: 0cm; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; WIDTH: 76.5pt; PADDING-TOP: 0cm" width="102">
<p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">graphs</span></b></p></td></tr></tbody></table>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><br></span><span style="COLOR: black; FONT-FAMILY: 宋体">（并不是所有的可能组合都合理）</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"> </span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: 宋体">数据结构</span></b><b><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i></b><b><span style="COLOR: black; FONT-FAMILY: 宋体">上的操作：</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">所有的定义在</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">上的操作在改变数据元素（节点）或节点的域时必须保持</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">的逻辑和物理结构。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></b><b><span style="COLOR: black; FONT-FAMILY: 宋体">上的基本操作：</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">任何其他对</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">的高级操作都可以用这些基本操作来实现。最好将</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span><span style="COLOR: black; FONT-FAMILY: 宋体">和他的所有基本操作看作一个整体</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">——</span><span style="COLOR: black; FONT-FAMILY: 宋体">称之为</span><b><span style="COLOR: black; FONT-FAMILY: 宋体">模块</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">。我们可以进一步将该模块抽象为数据类型（其中</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">的存储结构被表示为私有成员，基本操作被表示为公共方法），称之为</span><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">ADT</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">。作为</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">ADT</span><span style="COLOR: black; FONT-FAMILY: 宋体">，堆栈和队列都是一种特殊的表，他们拥有表的操作的子集。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">对于</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DATs</span><span style="COLOR: black; FONT-FAMILY: 宋体">的高级操作可以被设计为（不封装的）算法，利用基本操作对</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">进行处理。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="COLOR: black; FONT-FAMILY: 宋体">好的和坏的</span></b><b><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></b><b><span style="COLOR: black; FONT-FAMILY: 宋体">：</span></b><span style="COLOR: black; FONT-FAMILY: 宋体">如果一个</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">可以通过某种</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">“</span><span style="COLOR: black; FONT-FAMILY: 宋体">线性规则</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">”</span><span style="COLOR: black; FONT-FAMILY: 宋体">被转化为线性的</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">（例如线性表），则称它为好的</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">。好的</span><i><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS</span></i><span style="COLOR: black; FONT-FAMILY: 宋体">通
常对应于好的（高效的）算法。这是由计算机的计算能力决定的，因为计算机本质上只能存取逻辑连续的内存单元，因此如何没有线性化的结构逻辑上是不可计算
的。比如对一个图进行操作，要访问图的所有结点，则必须按照某种顺序来依次访问所有节点（要形成一个偏序），必须通过某种方式将图固有的非线性结构转化为
线性结构才能对图进行操作。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/tree/chapter1.htm"><span style="FONT-FAMILY: 宋体">树</span></a></span><span style="COLOR: black; FONT-FAMILY: 宋体">是好的</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">DS——</span><span style="COLOR: black; FONT-FAMILY: 宋体">它有非常简单而高效的线性化规则，因此可以利用树设计出许多非常高效的算法。树的实现和使用都很简单，但可以解决大量特殊的复杂问题，因此树是实际编程中最重要和最有用的一种数据结构。树的结构本质上有递归的性质</span><span style="COLOR: black; FONT-FAMILY: Arial" lang="EN-US">——</span><span style="COLOR: black; FONT-FAMILY: 宋体">每一个叶节点可以被一棵子树所替代，反之亦然。实际上，每一种递归的结构都可以被转化为（或等价于）树形结构。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><b><span style="FONT-SIZE: 15pt; COLOR: black; FONT-FAMILY: &#1676;廍">计算机中数据的描述方式</span></b></p>
<p class="MsoNormal" style="TEXT-INDENT: 22.5pt; TEXT-ALIGN: left" align="left"><span style="COLOR: black; FONT-FAMILY: 宋体">我们知道，数据可以用不同的形式进行描述或存储在计算机存储器中。最常见的数据描述方法有：公式化描述、链接描述、间接寻址和模拟指针。</span></p>
<ul type="square"><li class="MsoNormal" style="COLOR: black; TEXT-ALIGN: left"><span style="FONT-FAMILY: 宋体">公
式化描述借助数学公式来确定元素表中的每个元素分别存储在何处，也就通过公式计算元素的存储器地址。最简单的情形就是把所有元素依次连续存储在一片连续的
存储空间中，这就是通常所说的连续线性表，即数组。复杂一点的情形是利用复杂的函数关系根据元素的某些特征来计算元素在内存中的位置，这种技术称为散列技
术</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US">(Hash</span><span style="FONT-FAMILY: 宋体">，经常音译为哈希技术</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US"> </span>
</li><li class="MsoNormal" style="COLOR: black; TEXT-ALIGN: left"><span style="FONT-FAMILY: 宋体">在链接描述中，元素表中的每个元素可以存储在存储器的不同区域中，每个元素都包含一个指向下一个元素的指针。这就是通常所说的</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/list/chapter3_2.htm"><span style="FONT-FAMILY: 宋体">链表</span></a></span><span style="FONT-FAMILY: 宋体">。这种描述方法的好处是，知道了第一个元素的位置，就可以依次找到第</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US">n</span><span style="FONT-FAMILY: 宋体">个元素的位置，而且在其中插入元素非常方便，缺点是查找某个元素要遍历所有在该元素之前的元素，实际应用中经常和公式化描述结合起来使用。</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US"> </span>
</li><li class="MsoNormal" style="COLOR: black; TEXT-ALIGN: left"><span style="FONT-FAMILY: 宋体">在间接寻址方式中，元素表中的每个元素也可以存储在存储器的不同区域中，不同的是，此时必须保存一张表，该表的第</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US">i</span><span style="FONT-FAMILY: 宋体">项指向元素表中的第</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US">i</span><span style="FONT-FAMILY: 宋体">个元素，所以这张表是一个用来存储元素地址的表。指针数组（元素为指针的数组）就是这种描述法的应用。这种描述方法是公式化描述和链接描述的一种折衷方案，同时具有两种描述方法的优点，但是需要额外的内存开销。</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US"> </span>
</li><li class="MsoNormal" style="color: black; text-align: left;"><span style="FONT-FAMILY: 宋体">模
拟指针非常类似于链接描述，区别在于它用整数代替了指针，整数所扮演的角色与指针所扮演的角色完全相同。模拟指针的描述方式是链接描述和公式化描述的结
合，元素被存储在不同的区域中，每个元素包含一个指示下一个元素位置的整数，可以通过某种公式由该整数计算出下一个元素的存储器地址。</span><span style="FONT-FAMILY: &#718;&#805;" lang="EN-US"><a href="http://algorithm.myrice.com/datastructure/basic/list/chapter3_3.htm"><span style="FONT-FAMILY: 宋体">线性表的游标实现</span></a></span><span style="font-family: 宋体;">就是模拟指针描述法。</span></li></ul><p>转自：http://www.programfan.com/blog/article.asp?id=5306<br></p>]]></description>
</item><item>
<title><![CDATA[陈老师的BLOG]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=51752</link>
<author>zc9706</author>
<pubDate>2011/7/24 17:45:08</pubDate>
<description><![CDATA[http://home.lupaworld.com/space-uid-26540.html<br>&nbsp; http://www.kerneltravel.net/<br>]]></description>
</item><item>
<title><![CDATA[iptables 规则的保存]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=51356</link>
<author>zc9706</author>
<pubDate>2011/5/4 9:49:10</pubDate>
<description><![CDATA[<a>　转自：http://hi.baidu.com/%D0%C0%D3%EA%D6%AE%C3%CE/blog/item/8369c5edb4bb563027979152.html</a><div id="blog_text" class="cnt"><p><font color="#ff0000"><strong>iptables的配置文件保存在/etc/sysconfig/iptables-config下</strong></font>，
书写了iptables规则以后如果需要保存规则，则可以使用命令：iptables-save，使用此命令保存的规则位置可以是任意的，此时保存的规则
在重启机器后无法自动生效，需要使用命令iptables-restore恢复，或者写入开机启动脚本/etc/rc.d/rc.local里面。</p>
<p>以下为教材里使用的命令：</p>
<p><font color="#ff0000"><strong>保存规则：#iptables-save &gt;/etc/iptables-script</strong></font></p>
<p><font color="#ff0000"><strong>恢复规则：#iptables-restore&gt;/etc/iptables-script</strong></font></p>
<p>保存和恢复的位置只要是两者一致就可以了，如果iptables-script没有则需要创建。</p>
<font color="#ff0000"><strong>
<p><font color="#ff0000"><strong><em>若想开机自动启用脚本，则可以使用以下命令放到系统初始化Shell脚本/etc/rc.d/rc.local中</em></strong></font></p>
<p><font color="#ff0000"><strong><em>#echo '/sbin/iptables-restore /etc/iptables-script' &gt;&gt;/etc/rc.d/rc.local</em></strong></font></p>
<p>但近日查看一些资料，发现规则保存的位置在/etc/sysconfig/iptables下，所以一些资料就有了</p>
<p><font color="#ff0000"><strong><em>保存规则：#iptables-save &gt;/etc/sysconfig/iptables</em></strong></font></p>
<p><font color="#ff0000"><strong><em>恢复规则：#iptables-restore&gt;/etc/sysconfig/iptables</em></strong></font></p>
<p><font color="#ff0000"><strong><em>若想开机自动启用脚本，则可以使用以下命令放到系统初始化Shell脚本/etc/rc.d/rc.local中</em></strong></font></p>
<p><font color="#ff0000"><strong><em>#echo '/sbin/iptables-restore /etc/sysconfig/iptables' &gt;&gt;/etc/rc.d/rc.local</em></strong></font></p>
<p>此外还有一命令保存规则 <font color="#ff0000"><strong>#service iptables save</strong></font>，如下图：</p>
<p><span><img class="blogimg" src="http://hiphotos.baidu.com/%D0%C0%D3%EA%D6%AE%C3%CE/pic/item/eaffe319730981884bedbcf3.jpg" width="708" border="0"><br>
<font color="#ff0000"><em><strong>规则自动保存到了/etc/sysconfig/iptables，<font color="#0000ff">用此命令保存的规则开机会自动生效</font>，所以为了统一期间，建议以后规则的保存都保存在/etc/sysconfig/iptables下。</strong></em></font></span></p>
</strong></font></div>]]></description>
</item><item>
<title><![CDATA[compatible , enhanced ide, enhanced ahci 模式]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=51323</link>
<author>zc9706</author>
<pubDate>2011/4/18 16:28:36</pubDate>
<description><![CDATA[<a><!--[if gte mso 9]><xml>
 <w:WordDocument>
  <w:View>Normal</w:View>
  <w:Zoom>0</w:Zoom>
  <w:TrackMoves/>
  <w:TrackFormatting/>
  <w:PunctuationKerning/>
  <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
  <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
  <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
  <w:ValidateAgainstSchemas/>
  <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
  <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
  <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
  <w:DoNotPromoteQF/>
  <w:LidThemeOther>EN-US</w:LidThemeOther>
  <w:LidThemeAsian>ZH-CN</w:LidThemeAsian>
  <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
  <w:Compatibility>
   <w:SpaceForUL/>
   <w:BalanceSingleByteDoubleByteWidth/>
   <w:DoNotLeaveBackslashAlone/>
   <w:ULTrailSpace/>
   <w:DoNotExpandShiftReturn/>
   <w:AdjustLineHeightInTable/>
   <w:BreakWrappedTables/>
   <w:SnapToGridInCell/>
   <w:WrapTextWithPunct/>
   <w:UseAsianBreakRules/>
   <w:DontGrowAutofit/>
   <w:SplitPgBreakAndParaMark/>
   <w:DontVertAlignCellWithSp/>
   <w:DontBreakConstrainedForcedTables/>
   <w:DontVertAlignInTxbx/>
   <w:Word11KerningPairs/>
   <w:CachedColBalance/>
   <w:UseFELayout/>
  </w:Compatibility>
  <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
  <m:mathPr>
   <m:mathFont m:val="Cambria Math"/>
   <m:brkBin m:val="before"/>
   <m:brkBinSub m:val="--"/>
   <m:smallFrac m:val="off"/>
   <m:dispDef/>
   <m:lMargin m:val="0"/>
   <m:rMargin m:val="0"/>
   <m:defJc m:val="centerGroup"/>
   <m:wrapIndent m:val="1440"/>
   <m:intLim m:val="subSup"/>
   <m:naryLim m:val="undOvr"/>
  </m:mathPr></w:WordDocument>
</xml><![endif]--></a>compatible: 常用于在SATA硬盘上安装XP；<br>enhanced ide: 加强版的IDE硬盘；<br>enhanced ahci: SATA硬盘的读取模式，安装系统时需要SATA驱动；<br><br>详细如下：<br><br><!--[if gte mso 9]><xml>
 <w:WordDocument>
  <w:View>Normal</w:View>
  <w:Zoom>0</w:Zoom>
  <w:TrackMoves/>
  <w:TrackFormatting/>
  <w:PunctuationKerning/>
  <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
  <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
  <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
  <w:ValidateAgainstSchemas/>
  <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
  <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
  <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
  <w:DoNotPromoteQF/>
  <w:LidThemeOther>EN-US</w:LidThemeOther>
  <w:LidThemeAsian>ZH-CN</w:LidThemeAsian>
  <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
  <w:Compatibility>
   <w:SpaceForUL/>
   <w:BalanceSingleByteDoubleByteWidth/>
   <w:DoNotLeaveBackslashAlone/>
   <w:ULTrailSpace/>
   <w:DoNotExpandShiftReturn/>
   <w:AdjustLineHeightInTable/>
   <w:BreakWrappedTables/>
   <w:SnapToGridInCell/>
   <w:WrapTextWithPunct/>
   <w:UseAsianBreakRules/>
   <w:DontGrowAutofit/>
   <w:SplitPgBreakAndParaMark/>
   <w:DontVertAlignCellWithSp/>
   <w:DontBreakConstrainedForcedTables/>
   <w:DontVertAlignInTxbx/>
   <w:Word11KerningPairs/>
   <w:CachedColBalance/>
   <w:UseFELayout/>
  </w:Compatibility>
  <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
  <m:mathPr>
   <m:mathFont m:val="Cambria Math"/>
   <m:brkBin m:val="before"/>
   <m:brkBinSub m:val="--"/>
   <m:smallFrac m:val="off"/>
   <m:dispDef/>
   <m:lMargin m:val="0"/>
   <m:rMargin m:val="0"/>
   <m:defJc m:val="centerGroup"/>
   <m:wrapIndent m:val="1440"/>
   <m:intLim m:val="subSup"/>
   <m:naryLim m:val="undOvr"/>
  </m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
 <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
  DefSemiHidden="true" DefQFormat="false" DefPriority="99"
  LatentStyleCount="267">
  <w:LsdException Locked="false" Priority="0" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 1"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 2"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 3"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 4"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 5"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 6"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 7"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 8"/>
  <w:LsdException Locked="false" Priority="39" Name="toc 9"/>
  <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
  <w:LsdException Locked="false" Priority="10" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Title"/>
  <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
  <w:LsdException Locked="false" Priority="11" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
  <w:LsdException Locked="false" Priority="0" Name="Hyperlink"/>
  <w:LsdException Locked="false" Priority="22" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
  <w:LsdException Locked="false" Priority="20" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
  <w:LsdException Locked="false" Priority="59" SemiHidden="false"
   UnhideWhenUsed="false" Name="Table Grid"/>
  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
  <w:LsdException Locked="false" Priority="1" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List Accent 1"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
  <w:LsdException Locked="false" Priority="34" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
  <w:LsdException Locked="false" Priority="29" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
  <w:LsdException Locked="false" Priority="30" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List Accent 1"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List Accent 2"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List Accent 2"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List Accent 3"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List Accent 3"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List Accent 4"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List Accent 4"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List Accent 5"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List Accent 5"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
  <w:LsdException Locked="false" Priority="60" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
  <w:LsdException Locked="false" Priority="61" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light List Accent 6"/>
  <w:LsdException Locked="false" Priority="62" SemiHidden="false"
   UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
  <w:LsdException Locked="false" Priority="63" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
  <w:LsdException Locked="false" Priority="64" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="65" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
  <w:LsdException Locked="false" Priority="66" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="67" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
  <w:LsdException Locked="false" Priority="68" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="69" SemiHidden="false"
   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
  <w:LsdException Locked="false" Priority="70" SemiHidden="false"
   UnhideWhenUsed="false" Name="Dark List Accent 6"/>
  <w:LsdException Locked="false" Priority="71" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
  <w:LsdException Locked="false" Priority="72" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
  <w:LsdException Locked="false" Priority="73" SemiHidden="false"
   UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
  <w:LsdException Locked="false" Priority="19" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
  <w:LsdException Locked="false" Priority="21" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
  <w:LsdException Locked="false" Priority="31" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
  <w:LsdException Locked="false" Priority="32" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
  <w:LsdException Locked="false" Priority="33" SemiHidden="false"
   UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
 </w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
 /* Style Definitions */
 table.MsoNormalTable
	{mso-style-name:普通表格;
	mso-tstyle-rowband-size:0;
	mso-tstyle-colband-size:0;
	mso-style-noshow:yes;
	mso-style-priority:99;
	mso-style-qformat:yes;
	mso-style-parent:"";
	mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
	mso-para-margin:0cm;
	mso-para-margin-bottom:.0001pt;
	mso-pagination:widow-orphan;
	font-size:10.5pt;
	mso-bidi-font-size:11.0pt;
	font-family:"Calibri","sans-serif";
	mso-ascii-font-family:Calibri;
	mso-ascii-theme-font:minor-latin;
	mso-fareast-font-family:宋体;
	mso-fareast-theme-font:minor-fareast;
	mso-hansi-font-family:Calibri;
	mso-hansi-theme-font:minor-latin;
	mso-bidi-font-family:"Times New Roman";
	mso-bidi-theme-font:minor-bidi;
	mso-font-kerning:1.0pt;}
</style>
<![endif]-->

<p class="MsoNormal" style="text-align: left; line-height: 33.3pt;" align="left"><b style=""><span style="font-size: 24pt; font-family: 黑体; color: black;" lang="EN-US">AHCI</span></b></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，全称为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Serial ATA Advanced Host Controller Interface</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（串行</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">高级主控接口</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">/</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">高级主机控制器接口），是在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Intel</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的指导下，由多家公司联合研发的接口标准，它允许存储驱动程序启用高级串行</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能，如本机命令队列和热插拔，其研发小组成员主要包括</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Intel</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AMD</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、戴尔、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Marvell</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、迈拓、微软、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Red Hat</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、希捷和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">StorageGear</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">等著名企业。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">本质是一种</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">类设备，在系统内存总线和串行</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">设备内部逻辑之间扮演一种通用接口的角色（即它在不同的操作系统和硬件中是通用的）。这个类设备描述了一个含控制和状态区域、命令序列入口表的通用系统内存结构；每个命令表入口包含</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">设备编程信息，和一个指向（用于在设备和主机传输数据的）描述表的指针。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">通过包含一个</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PCI BAR</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（基址寄存器），来实现原生</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能。由于</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">统一接口的研发成功，使得支持串行</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">产品的开发工作大为简化，操作系统和设备制造商省去了单独开发接口的工作，取而代之的是直接在统一接口上进行操作，可以实现包括</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">NCQ</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Native Command Queuing</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）在内的诸多功能。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式则与</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式相反，装系统时需要安装</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动（而且貌似只有这个模式才能打开</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">NCQ</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能）。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">RAID</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式是要有两块硬盘才能实现的，具体情况可以参照一下网上组建</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">RAID</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的文章，如果你只有一块硬盘就可以忽略它了。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　补充：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> NCQ</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">是一种新的硬盘技术，简单来说开启它之后从一个程序跳到另一个程序时速度会更快，要实现它首先就要在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">BIOS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">里选择</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式，然后在装系统时安装相应的驱动（一般在主板驱动盘里有），安装好系统之后基本上就可以实现了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;"> </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　一直以来</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SCSI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘在多任务负载下的表现能力为人称道，其根本的原因除了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SCSI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口惊人的接口速率外，便是它的指令排序功能。以往的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘也正是因为缺少一种指令优化执行功能而在性能上落后于</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SCSI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘。针对这一困境，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Intel</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI 1.0</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">规范首次引入的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">NCQ</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Native Command Qu</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">），它的应用能够大幅度减少硬盘无用的寻道次数和数据查找时间，这样就能显著增强多任务情况下硬盘的性能。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　另外，作为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">标准的改进版，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Intel</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">完善了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Serial ATA II</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口的详细规格，并表示串行</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA II</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的研发将属于</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">统一接口的第二个阶段。而其中第一阶段从</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">06</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">年已经开始，不少厂商也推出</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Serial ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口的产品，包括硬盘和主板。但这仅仅是作为过渡，在第二阶段，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Serial
ATA II</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">将会凭借更高的信号传输速度直接取代</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA. </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">————————————</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">理论结束，现在看看你的电脑是不是支持它</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　注：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">需要英特尔</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">? </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">应用程序加速器</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> 4.1 </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">或更高版本，并与下列控制器集线器一同置入芯片组：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　英特尔</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">? 82801GBM I/O </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">控制器集线器</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> (ICH7M) - </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">仅限</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AHCI </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　英特尔</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">? 82801GR I/O </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">控制器集线器</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> (ICH7R) - RAID </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AHCI </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　英特尔</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">? 82801GH I/O </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">控制器集线器</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> (ICH7DH) - RAID </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AHCI </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　英特尔</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">? 82801FR I/O </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">控制器集线器（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ICH6R</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">- RAID </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AHCI </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　英特尔</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">? 82801FBM I/O </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">控制器集线器</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> (ICH6M) - </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">仅限</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AHCI </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　基于</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ICH7 </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ICH6 </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的芯片组，以及基于</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ICH5 </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ICH5R </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的芯片组，未使用</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　如果你的芯片不支持，千万不要乱用哦！</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<div style="border-width: medium medium 1pt; border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color rgb(222, 223, 225); padding: 0cm 0cm 4pt;">

<p class="MsoNormal" style="margin-bottom: 13.6pt; text-align: left; line-height: 16.3pt; border: medium none; padding: 0cm;" align="left"><a name="1"></a><b style=""><span style="font-size: 12.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span></b><b style=""><span style="font-size: 12.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的解决方法！！</span></b><b style=""><span style="font-size: 12.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></b></p>

</div>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">01.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">何谓</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能？</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　全名</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> Advanced Host Controller Interface</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，中译：进阶主机</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　控制器介面，它是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> Intel </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">所主导的一项技术，可以发挥</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　硬碟的潜在加速功能，大约可增加</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">30%</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的硬碟读写速度。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">02.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">何谓</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟？</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　指</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> Serial ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟，是由</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Parellel ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">演进；</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">目</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　前为主流，排线细、传输速度快，而</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">排线宽，速度较慢</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　，旧电脑硬碟都是用此架构，将被世代交替，俗称</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　故新买电脑要选择</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟，且需是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的规格。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">03.AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">所需具备之要件？</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-1.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟机必须有</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">NCQ(Native Command Queuing )</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">原生伫列之</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　功能，一般都是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的硬碟，目前市面上所贩卖的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　硬碟应该都是此规格。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-2.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">电脑主机板南桥晶片，要有支援</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的能力，故旧电脑是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　无法享受。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-3.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">电脑</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">BIOS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">要将</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能打开，未打开也是无法享受。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">04.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">如何开启</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能？新安装作业系统</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">(OS)</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">XP</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">光碟开机安装系统，必须先按下</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">F6</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">载入具备</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　之</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动程式</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> F6FLPY32.ZIP</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">；那事先已经安装好</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">XP</span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　的电脑，未载入正确</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Driver</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">之人士，不就要重灌电脑了吗？</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">05.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">作业系统已经存在，想补救，开启</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">功能？</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-1.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">先将</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟，插在非南桥晶片所支援的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">插槽座，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　例如</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">JMicron</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">晶片，不知外插卡可以吗？</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-2.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">进入</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">BIOS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">将</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">JMicron</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">晶片由</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">BASIC</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">改成</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-3.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">进入</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">BIOS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">将</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">INTEL</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">晶片由</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">改成</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AHCI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-4.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">进入</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">XP</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，安装</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IMSM(Intel Matrix Storage Manager)</span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Intel&amp;reg; </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">矩阵储存技术</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> IATA621.EXE Driver</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">-5.</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">将</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬碟插回南桥</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ICH</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">插槽，就可</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">OK</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">了！</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal"><span lang="EN-US">&nbsp;</span></p>

<p class="MsoNormal"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">是以韩国</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"><a href="http://baike.baidu.com/view/9536.htm" target="_blank"><span style="font-family: 宋体;" lang="EN-US"><span lang="EN-US">三星</span></span></a></span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"><a href="http://baike.baidu.com/view/30641.htm" target="_blank">LG</a></span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">为首的一批厂商开发的一种所谓的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Super-Multi</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">刻录机，目的是将所有的刻录标准一网打尽。这种所谓的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Super-Multi</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">产品就称为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">RAMBO(</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">在三星选择进入</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">刻录领域时，它最先看中的是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD-RAM</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，这可能是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">RAMBO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">一词的由来）。它是过去几种</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">刻录标准的集合，只是一种现行的叫法，而非一种新的刻录标准，它包含了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD-Multi</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">和</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD-Dual</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Rambo</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">光驱支持刻录盘片的格式包括</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CD-R/RW</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD+R/RW</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD-R/RW</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DVD-RAM</span></p>

<p class="MsoNormal"><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">&nbsp;</span></p>

<p class="MsoNormal" style="text-align: left; line-height: 33.3pt;" align="left"><b style=""><span style="font-size: 24pt; font-family: 黑体; color: black;" lang="EN-US">IDE</span></b><span style="font-size: 8pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: rgb(102, 102, 102);" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><b style=""><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span></b><b style=""><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">有多种含义</span></b><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　<b style="">解释一：</b></span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　集成设备电路，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Integrated Device Electronics</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，一般会作为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬件的接口，它的本意是指把</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">“</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘控制器</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">”</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">与</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">“</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">盘体</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">”</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">集成在一起的硬盘驱动器。把盘体与控制器集成在一起的做法减少了硬盘接口的电缆数目与长度，数据传输的可靠性得到了增强，硬盘制造起来变得更容易，因为硬盘生产厂商不需要再担心自己的硬盘是否与其它厂商生产的控制器兼容。对用户而言，硬盘安装起来也更为方便。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">这一接口技术从诞生至今就一直在不断发展，性能也不断的提高，其拥有的价格低廉、兼容性强的特点，为其造就了其它类型硬盘无法替代的地位。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">&nbsp;</span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　　</span><b style=""><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE
ATA/ATAPI</span></b><b style=""><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">控制器</span></b><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"></span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的英文拼写是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">“Programming Input/Output Model”</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式是一种通过</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">执行</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">I/O</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">端口指令来进行数据的读写的数据交换模式。是最早先的硬盘数据传输模式，数据传输速率低下，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">占有率也很高，大量传输数据时会因为占用过多的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">资源而导致系统停顿，无法进行其它的操作。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">数据传输模式又分为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO mode 0</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO mode 1</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO mode 2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO mode 3</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">、</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO mode 4</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">几种模式，数据传输速率从</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">3.3MB/s</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">到</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">16.6MB/s</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">不等。受限于传输速率低下和极高的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">占有率，这种数据传输模式很快就被淘汰。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">架构剖析与发展趋势</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口历史</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">(</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">一</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">) </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">1</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> AT ATTACHMENT </span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口是个人电脑上最具有实力的存储接口，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口早先被广泛应用于</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IBM</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">及其兼容机，它被定义为标准的硬盘接口。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA-1</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘接口的第一代标准</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ANSI X3.279-1994</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，也就是早期的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">3</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA-2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘接口的第二代标准</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ANSI X3.279-1995</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，就是大家所知道的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Fast ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">或者称之为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">EIDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）接口。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">4</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> Apple-ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Apple</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">上使用的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口，当然也是由标准的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口演化而来的，在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ANSI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的国际标准提案申请为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">X3T9.2/90-143.Revision 3.1</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，这一个由标准</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口规格演化而来</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Apple-ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">支持</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口的硬盘</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">LBA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式，但是没有支持</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATATP</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">5</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA-3</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘接口的第三代标准</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ANSI X3T13/2008D Revision 7</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">draft</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">），同样包含在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Fast ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">或</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的接口之中，一般使用者大多都知道</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Fast ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">或是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口，而对原来</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Fast ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">或</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口居然还包括了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA-2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">以及</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA-3</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">两组国际标准。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">6</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATAPI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">AT Attachment Packet Interface</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，这是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA Protocol</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的延伸，被定义用来支持</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CD-ROM</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">光驱以及</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Tape</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">磁带机，这一个</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATAPI Protocol</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">容许硬盘以外的设备使用</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">数据线。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">7</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA/ATAPI-4</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘接口的第四代标准</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ANSI X3T13/D96153</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">draft</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">），也就是大家所知道的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Ultra ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">或是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Ultra DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，这一个版本支持</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">33MB/sec</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的数据传输率（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">in burst mode</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">），相信各位读者对</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA-4/Ultra DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">都是比较熟悉的了。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">8</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA/ATAPI-5</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：这是目前</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">硬盘接口的比较新的一代标准，这一规格里规定的数据流传输速率（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">in
burst mode</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">66MB/sec</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，并且加强了内部资料的检查与错误修正的算法，强化了资料的完整性和可靠性。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">9</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">．</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> ATA/ATAPI-6</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">：还有更新的一个标准，是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA/ATAPI-5</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的改进，这一规格里规定的数据流传输速率（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">in
burst mode</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">100MB/sec</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　表一：</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式的资料传输速率</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode Cycle time Transfer Rate </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 0 600ns 3.3Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 1 383ns 5.2Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 2 240ns 8.3Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 3 180ns 11.1Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 4 120ns 16.6Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口发展至今，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ULTRA DIRECT MEMORY
ACCESS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">（</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ULTRA-DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">）的是目前最新的目前大家最为熟悉的就是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Ultra-DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的资料传输率最高可以达到</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">ATA-3</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">标准的四倍，也就是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">66.6Mbytes/sec</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　实际上硬盘接口的鼻祖，除了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SCSI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">界面以外，就是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">MFM/ST-506 Bus</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口了，后来经过不断的演变才演进成为今天的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced
IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口，而在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">之前的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE/AT-BUS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口，则仅仅提供了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式，而没有</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式，这两种驱动模式简单来讲区别主要是在数据传输时是否需要</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">来控制。在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式下，任何一个硬盘的读取动作，都必须经过</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">来控制管理，所以只要硬盘读写动作频繁的时候，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的资源就被大量的消耗，今儿降低了电脑整体的效率。而在</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式下，硬盘和内存之间的数据可以直接交换，这样就不会占用</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的资源，提高了电脑的整体效率。读者千万不要忽略掉从</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">到</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的进步，事实上个人电脑内的任何一个动作都必须运用系统的内存，毕竟</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">内部的缓存器容量太小了，所以凡是程序的读取、运算都必须在内存上操作，这样从硬盘到内存的数据交换就会非常频繁，所以简化这么一步对于电脑整体性能的提高还是非常突出的。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　以前硬盘采用</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式的时候，只要一开始大量的硬盘读写操作，就会使得电脑的性能急剧下降，让人感觉电脑总在等待什么似的，实际上</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">SCSI</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口一开始也是采用</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式，后来也演变成了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">模式，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE/AT-BUS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口也不例外，到了</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 4</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式之后，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE/AT-BUS</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口已经成功的演化成为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口，驱动模式也由</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 4</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">升级为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Multi</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">－</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">word DMA Mode2</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">，原本预计还有一个</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode 5</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">会问世的，但是</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA Mode</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">已经出现，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">PIO Mode</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">已经没有市场了。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　所以读者可以认为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Enhanced IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">接口的特点主要在于：驱动模式的改变，增加了对非硬盘存储设备的支持等，而且原本是一组的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">IDE</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">界面现在也增加到了两组。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的全名为</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Direct Memory Access</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">直接内存存取，采用</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式以后，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">不再象往常那样需要花费相当多的时间在硬盘的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">O/I</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">操作上，</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的意义就是在于让硬盘和内存直接沟通，所有的硬盘操作都不需要占用太多的</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">CPU</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">时间。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　接着让我们来看看</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA Mode</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">的相关资料。</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA</span><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">驱动模式资料传输速率</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US"> </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">DMA Mode I/O Cycle time Transfer Rate </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Single-word DMA Mode 0 900ns 2.1 Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Single-word DMA Mode 1 480ns 4.2 Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Single-word DMA Mode 2 240ns 8.4 Mbytes/sec </span></p>

<p class="MsoNormal" style="text-align: left; line-height: 16.3pt;" align="left"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　　</span><span style="font-size: 9.5pt; font-family: &quot;Arial&quot;,&quot;sans-serif&quot;; color: black; letter-spacing: 0.35pt;" lang="EN-US">Multi-word DMA Mode 0 480ns 4.2 Mbytes/sec</span></p>

<p class="MsoNormal"><span style="font-size: 9.5pt; font-family: 宋体; color: black; letter-spacing: 0.35pt;">　</span></p>

<br>]]></description>
</item><item>
<title><![CDATA[重装windows后，修复Fedora的grub]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=37168</link>
<author>zc9706</author>
<pubDate>2008/6/25 17:39:17</pubDate>
<description><![CDATA[
<DIV><FONT size=4><FONT size=2>我的机器上装有2套系统，一是windowsxp,另一套是RedHat，我装的是Fedora core 3，由于windowsXP<BR>系统不小心崩溃了，从新安装XP后，linux引导界面没有了，怎么办。本人是linux的初学者，从网上查找<BR>资料，知道是从装xp后，linux的grub破坏了，需要修复。<BR>1.把安装盘的第一张放到光驱，然后重新启动机器，在BOIS中把系统用光驱来引导<BR>2.等安装界面出来后选择F5(Linux Rescue)(会有提示)，linux以前版本好像是F4,Fedora core 3中F5是修复<BR>3.出现boot：提示符，在此处输入linux rescue回车，接着会提示你选择安装的语言你可以选择中文也可以是英文，<BR>一直回车，当出现提示配置网络的时候，你选择NO。<BR>4.会出现sh 3.0# 提示符，输入grub后回车，进入grub&gt;<BR>5.在grub&gt;下输入 grub&gt;root (hdX,Y) <BR>grub&gt;setup (hd0) <BR>（x,y的值根据实际情况赋值，我只有一个硬盘，windows和linux都安装在这个盘上，所以x=0,linux下我有2个分区hd0，<BR>hd1,0是交换分区，1安装linux，所以y=1）<BR>6.回车以后，出现提示信息，如果都是succeed，那么就修复成功了，接着我们退出和重起系统<BR>7.在grub&gt;下输入reboot后，退到boot：提示符下面，接着输入exit，重启系统后，进入grub<BR>又出现了windows和linux的选择页面。</FONT></FONT></DIV>
<P><FONT size=4><FONT size=2></FONT></FONT>&nbsp;</P>
<P><FONT size=4><FONT size=2>在不记得硬盘结构的情况下可以使用 </FONT></FONT></P>
<P><FONT size=4><FONT size=2>grub&gt; root (hd0,按下TAB&nbsp;&nbsp;&nbsp; </FONT></FONT></P>
<P><FONT size=4><FONT size=2>的方式来查看硬盘情况，选择EXT格式得硬盘作为引导。进入LINUX系统后修改系统可以通过修改/BOOT/grub.conf文件来进行。</FONT></P>
<DIV><BR>部分转自：<A href="http://blog.chinaunix.net/u1/59043/showart_459792.html">http://blog.chinaunix.net/u1/59043/showart_459792.html</A></DIV></FONT>]]></description>
</item><item>
<title><![CDATA[著名的SQL注入攻击法 (转)]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=36317</link>
<author>zc9706</author>
<pubDate>2008/6/2 17:12:10</pubDate>
<description><![CDATA[<P><A>　我们在编程过程中，经常会把用户输入的数据拼成一个SQL语句，然后直接发送给服务器执行，比如：<BR><BR>string SqlStr = "select * from customers where CompanyName Like '%" + textBox1.Text&nbsp;+&nbsp;"%'";<BR><BR>这样的字符串连接可能会带来灾难性的结果，比如用户在文本框中输入：<BR><BR>a' or 1=1 --<BR><BR>那么SqlStr的内容就是：<BR><BR>select * from customers where CompanyName like '%a' or 1=1 --%'<BR><BR>这样，整个customers数据表的所有数据就会被全部检索出来，因为1=1永远true，而且最后的百分号和单引号被短横杠注释掉了。<BR><BR>如果用户在文本框中输入：<BR><BR>a' EXEC sp_addlogin 'John' ,'123' EXEC sp_addsrvrolemember 'John','sysadmin' --<BR><BR>那么SqlStr的内容就是：<BR><BR>select * from customers where CompanyName like '%a' EXEC sp_addlogin 'John','123' EXEC sp_addsrvrolemember 'John','sysadmin' --<BR><BR>这个语句是在后台数据库中增加一个用户John，密码123，而且是一个sysadmin账号，相当于sa的权限。<BR><BR>如果用户在文本框中输入：<BR><BR>a' EXEC xp_cmdShell('format c:/y') --<BR><BR>运行之后好像是格式化C盘！<BR><BR>还有很多更危险的操作，不过都没试过。还是存储过程好用啊，存储过程的参数把用户的输入当成真正的字符串处理，既安全，又快速！</A></P>
<P>&nbsp;</P>
<P>转自：<A href="http://blog.sina.com.cn/s/blog_4a668047010005d7.html">http://blog.sina.com.cn/s/blog_4a668047010005d7.html</A></P>]]></description>
</item><item>
<title><![CDATA[PE病毒技术剖析[转载]]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=36050</link>
<author>zc9706</author>
<pubDate>2008/5/27 16:54:57</pubDate>
<description><![CDATA[
<P><FONT face=宋体>* 编程语言</FONT></P>
<P><FONT face=宋体>任何语言只要表达能力足够强，都可用于编写PE病毒。但现存的绝大部分PE病毒都是直接用汇编编写的，一方面是因为汇编编译后的代码短小精悍，可以充分进行人工优化，以满足隐蔽性的要求；另外一方面之所以用汇编是因为其灵活和可控，病毒要同系统底层有时甚至是硬件打交道，由于编译器的特点不尽相同，用高级语言实现某些功能甚至会更加麻烦，比如用汇编很方便地就可以直接进行自身重定位、自身代码修改以及读写IO端口等操作，而用高级语言实现则相对烦琐。用汇编还可以充分利用底层硬件支持的各种特性，限制非常少。但是用汇编编写病毒的主要缺点就是编写效率低，加上使用各种优化手段使得代码阅读起来相当困难，不过作为一种极限编程技术，对病毒作者而言，这些似乎都已经不再重要。本文假设读者熟悉汇编语言，各种举例使用Intel格式的汇编代码，编译器可使用MASM或FASM进行编译，由于汇编语言表述算法较为不便，因此算法和原理性表述仍然采用C语言。在讲述各种技术时，部分代码直接取自病毒Elkern的源代码，该病毒在2002年曾经大规模流行，其代码被收录于著名病毒杂志29A第7期中，有兴趣的读者可参阅其完整代码。</FONT></P>
<P><FONT face=宋体>* 重定位</FONT></P>
<P><FONT face=宋体>病毒自身的重定位是病毒代码在得以顺利运行前应解决的最基本问题。病毒代码在运行时同样也要引用一些数据，比如API函数的名字、杀毒软件的黑名单、系统相关的特殊数据等，由于病毒代码在宿主进程中运行时的内存地址是在编译汇编代码时无法预知的，而病毒在感染不同的宿主时其位于宿主中的准确位置同样也无法提前预知，因此病毒就要在运行时动态确定其引用数据的地址，否则，引用数据时几乎肯定会发生错误。对于普通的PE文件比如动态链接库而言，在被加载到不同地址处时由加载器根据PE中一个被称为重定位表的特殊结构动态修正引用数据指令的地址，而重定位表是由编译器在编译阶段生成的，因此动态链接库本身无需为此做任何额外处理。病毒代码则不同，必须自己动态确定需引用数据的地址。比如一段病毒代码被加载在0x400000处，地址0x401000处的一条语句及其引用的数据定义如下所示，相关地址是编译器在编译时计算得到的，这里假设编译时预设的基地址也是0x400000：<BR>401000:<BR>mov eax,dword ptr [402035]<BR>......<BR>402035:<BR>db "hello world!",0<BR>　　如果病毒代码在宿主中也加载到基地址0x400000，显然是能够正常执行的，但如果这段代码被加载在基地址0x500000运行时则出错，对病毒而言，这是大多数时候都会遇到的情况，因为指令中引用的仍然是0x402035这个地址。如果病毒代码不是在宿主进程中而是作为一个具有重定位表的独立PE文件运行，正常情况下由系统加载器根据重定位表表项将 mov eax,dword ptr [402035]中的0x402035修改为正确值0x502305，这样这句代码就变成了mov eax,dword ptr [5402035]，程序也就能准确无误地运行了。不过很可惜，对在其它进程内运行病毒代码而言，必须采取额外的手段、付出额外的代价感染宿主PE文件时就及时加以解决，否则将导致宿主进程无法正常运行。</FONT></P>
<P><FONT face=宋体>至少有两种方法可以解决重定位的问题：</FONT></P>
<P><FONT face=宋体>A）第一种方法就是利用上述PE文件重定位表项的特殊作用构造相应的重定位表项。在感染目标PE文件时，将引用自身数据的需要被重定位的地址全部写入目标PE文件的重定位表中，如果目标PE无任何重定位表项（如用MS linker的/fixed）则创建重定位表节并插入新的重定位项；若已经存在重定位表项，则在修改已存在的重定位表节，在其中插入包含了这些地址的新表项。重定位的工作就完全由系统加载器在加载PE文件的时候自动进行了。重定位表项由PE文件头的DataDirectory数据中的第6个成员IMAGE_DIRECTORY_ENTRY_BASERELOC指向。该方法需要的代码稍多，实现起来也相对比较复杂，另外如果目标文件无重定位表项（为了减小代码体积，这种情况也不少见），处理起来就比较麻烦，只有用高级语言编写病毒才常用该种方法，在一般的PE病毒中很少使用。</FONT></P>
<P><FONT face=宋体>B）利用Intel X86体系结构的特殊指令，call或fnstenv等指令动态获取当前指令的运行时地址，计算该地址与编译时预定义地址的差值（被称为delta offset），再将该差值加到原编译时预定的地址上，得到的就是运行时数据的正确地址。对于intel x86指令集而言，在书写代码时，通过将delta offset放在某个寄存器中，然后通过变址寻址引用数据就可以解决引用数据重定位的难题。还以上例说明，假如上述指令块被操作系统映射在0x500000处那么代码及其在内存中的地址将变为：<BR>501000:<BR>mov eax,dword ptr [402035]<BR>......<BR>502035:<BR>db "hello world!",0</FONT></P>
<P><FONT face=宋体>　　显然，mov指令引用的操作数地址是不正确的，如果我们知道了mov指令运行时地址是0x501000，那么计算该地址和编译时该指令预设地址的差值：0x501000-0x401000 = 0x100000。很显然指令引用的实际数据地址应该为0x402035+0x100000 = 0x502035。从上例可以看出，只要能够在运行时确定某条指令动态运行时的地址，而其编译时地址已知，我们就能够通过将delta offset加到相应的地址上正确重定位任何代码或数据的运行时地址。原理如图4所示：</FONT></P>
<P><FONT face=宋体><BR>图4 delta iffset</FONT></P>
<P>通常只要在病毒代码的开始计算出delta offset，通过变址寻址的方式书写引用数据的汇编代码，即可保证病毒代码在运行时被正确重定位。假设ebp包含了delta offset，使用如下变址寻址指令则可保证在运行时引用的数据地址是正确的：<BR>;ebp包含了delta offset值<BR>401000:<BR>mov eax,dword ptr [ebp+0x402035]<BR>......<BR>402035:<BR>db "hello world!",0<BR>在书写源程序时可以采用符号来代替硬编码的地址值，上述的例子中给出的不过是编译器对符号进行地址替换后的结果。现在的问题就转换成如何获取delta offset的值了，显然：<BR>call delta<BR>delta:<BR>pop ebp<BR>sub ebp,offset delta<BR>在运行时就动态计算出了delta offset值，因为call要将其后的第一条指令的地址压入堆栈，因此pop ebp执行完毕后ebp中就是delta的运行时地址，减去delta的编译时地址“offset delta”就得到了delta offset的值。除了用明显的call指令外，还可以使用不那么明显的fstenv、fsave、fxsave、fnstenv等浮点环境保存指令进行，这些指令也都可以获取某条指令的运行时地址。以fnstenv为例，该指令将最后执行的一条FPU指令相关的协处理器的信息保存在指定的内存中，结构如下图5所示：</P>
<P>图5 浮点环境块的结构</P>
<P>该结构偏移12字节处就是最后执行的浮点指令的运行时地址，因此我们也可以用如下一段指令获取delta offset：<BR>fpu_addr:<BR>fnop<BR>call GetPhAddr<BR>sub ebp,fpu_addr</P>
<P>GetPhAddr:<BR>sub esp,16<BR>fnstenv [esp-12]<BR>pop ebp<BR>add esp,12<BR>ret</P>
<P>　　delta offset也不一定非要放在ebp中，只不过是ebp作为栈帧指针一般过程都不将该寄存器用于其它用途，因此大部分病毒作者都习惯于将delta offset保存在ebp中，其实用其他寄存器也完全可以。<BR>　　在优化过的病毒代码中并不经常直接使用上述直接计算delta offset的代码，比如在Elkern开头写成了类似如下的代码：<BR>call _start_ip<BR>_start_ip:<BR>pop ebp<BR>;...<BR>;使用<BR>call [ebp+addrOpenProcess-_start_ip]<BR>;...<BR>addrOpenProcess dd 0<BR>;而不是<BR>call _start_ip<BR>_start_ip:<BR>pop ebp<BR>sub ebp,_start_ip<BR>call [ebp+addrOpenProcess]</P>
<P>　　为什么不采用第二种书写代码的方式？其原因在于尽管第一种格式在书写源码时显得比较罗嗦，但是addrOpenProcess-_start_ip是一个较小相对偏移值，一般不超过两个字节，因此生成的指令较短，而addrOpenProcess在32 Win32编译环境下一般是4个字节的地址值，生成的指令也就较长。有时对病毒对大小要求很苛刻，更多时候也是为了显示其超俗的编程技巧，病毒作者大量采用这种优化，对这种优化原理感兴趣的读者请参阅Intel手册卷2中的指令格式说明。</P>
<P>* API函数地址的获取</P>
<P>在能够正确重定位之后，病毒就可以运行自己代码了。但是这还远远不够，要搜索文件、读写文件、进行进程枚举等操作总不能在有Win32 API的情况下自己用汇编完全重新实现一套吧，那样的编码量过大而且兼容性很差。Win9X/NT/2000/XP/2003系统都实现了同一套在各个不同的版本上都高度兼容的Win32 API，因此调用系统提供的Win32 API实现各种功能对病毒而言就是自然而然的事情了。<BR>　　所以接下来要解决的问题就是如何动态获取Win32 API的地址。最早的PE病毒采用的是预编码的方法，比如Windows 2000中CreateFileA的地址是0x7EE63260，那么就在病毒代码中使用call [7EE63260h]调用该API，但问题是不同的Windows版本之间该API的地址并不完全相同，使用该方法的病毒可能只能在Windows 2000的某个版本上运行。因此病毒作者自然而然地回到PE结构上来探求解决方法，我们知道系统加载PE文件的时候，可以将其引入的特定DLL中函数的运行时地址填入PE的引入函数表中，那么系统是如何为PE引入表填入正确的函数地址的呢？答案是系统解析引入DLL的导出函数表，然后根据名字或序号搜索到相应引出函数的的RVA（相对虚拟地址），然后再和模块在内存中的实际加载地址相加，就可以得到API函数的运行时真正地址。在研究操作系统是如何实现动态PE文件链接的过程中，病毒作者找到了以下两种解决方案：</P>
<P>A)在感染PE文件的时候，可以搜索宿主的函数引入表的相关地址，如果发现要使用的函数已经被引入，则将对该API的调用指向该引入表函数地址，若未引入，则修改引入表增加该函数的引入表项，并将对该API的调用指向新增加的引入函数地址。这样在宿主程序启动的时候，系统加载器已经把正确的API函数地址填好了，病毒代码即可正确地直接调用该函数。</P>
<P>B）系统可以解析DLL的导出表，自然病毒也可以通过这种手段从DLL中获取所需要的API地址。要在运行时解析搜索DLL的导出表，必须首先获取DLL在内存中的真实加载地址，只有这样才能解析从PE的头部信息中找到导出表的位置。应该首先解析哪个DLL呢？我们知道Kernel32.DLL几乎在所有的Win32进程中都要被加载，其中包含了大部分常用的API，特别是其中的LoadLibrary和GetProcAddress两个API可以获取任意DLL中导出的任意函数，在迄今为止的所有Windows平台上都是如此。只要获取了Kernel32.DLL在进程中加载的基址，然后解析Kernel32.DLL的导出表获取常用的API地址，如需要可进一步使用Kernel32.DLL中的LoadLibrary和GetProcAddress两个API更简单地获取任意其他DLL中导出函数的地址并进行调用。</P>
<P>* 获取Kernel32.DLL基址</P>
<P>　　获取Kernel32.DLL基址的方法很多，最常见的一种是搜索法，如果已知Kernel32.DLL加载的大致地址，那么可由该地址向高地址或低地址进行搜索可以找到其基址。另外一种方法是搜索NT PEB结构中的模块列表获取Kernel32.DLL的准确加载基址。下面看一下具体的实现代码：</P>
<P>方法1：暴力搜索获取Kernel32.DLL的基址</P>
<P>最初的病毒是指定一个大致的加载地址，比如根据实验在9X下其加载地址是0xBFF70000；在Windows 2000下加载基址是0x77E80000；在XP和2003下其加载基址是0x77E60000，因此在NT系统下就可以从0x77e00000开始向高地址搜索，在9X下可以从0xBFF00000开始向高地址搜索，如果搜索到Kernel32.DLL的加载地址，其头部一定是“MZ”标志，由模块起始偏移0x3C的双字确定的PE头部标志必然是“PE”标志，因此可根据这两个标志判断是否找到了模块加载地址，也许有人认为该方法不可靠，因为如果恰好有某段数据符合这两个特征，那么找到的基址可能就是错误的，但经实验证明，该判断方法非常可靠，基本不会出现错误。有一点需要注意的是，在所有版本的Windows系统下Kernel32.DLL的加载基址都是按照0x10000对齐的，根据这一特点可以不必逐字节搜索，按照64K对齐的边界地址搜索即可。<BR>从大致的一个地址开始搜索Kernel32.DLL基址可能会出现读写到未映射内存区域的情况，因此需要和SEH配合使用。如果有在各个版本下准确获取Kernel32.DLL中某地址的通用方法，那么就可以更可靠地从该地址开始向低地址搜索，显然会更加通用。事实上，这种方法是存在的。在系统加载PE文件跳转到PE入口点第一条指令的时候，堆栈顶保存的就是Kernel32.DLL中的某个地址，Elkern中采用的就是这种方法：<BR>_start:<BR>pushfd ;If some flags,especial DF,changed,some APIs can crash down!!!<BR>pushad<BR>_start_@1 equ $<BR>;......<BR>mov ebx,[esp+9*4] ;前面已经由pushfd和pushad压入了9个双字<BR>and ebx,0ffe00000h ;该地址为Kernel32.dll模块下方的某个地址<BR>　　　　　　　　　　　　　　　　;先减去0x100000确保该地址处于Kernel32.dll的下方<BR>　　　　　　　　　　　　　　　　;向高地址搜索如果将来Windows的发行版本中Kernel32.dll<BR>　　　　　　　　　　　　　　　　;大小和代码结构发生变化，该方法可能无效</P>
<P>　　ebx中现在已经是Kernel32.DLL基址之前某个地址了，后续代码可以向高地址搜索其基址。该方法有一个缺点，就是必须明确知道程序入口的堆栈指针值，或间接可计算出该值，对于那些在程序入口获取控制权的病毒代码而言，是可以的，但对于采用EPO技术的病毒而言，该方法则不适用。事实上还有另外一种更加通用的方法，我们知道在Win32程序执行过程中fs段寄存器的基址总是指向进程的TEB，TEB的第一个成员指向SEH链表，该链表每个节点都是一个EXCEPTION_REGISTRATION结构，该结构定义如下：<BR>struct EXCEPTION_REGISTRATION{<BR>struct EXCEPTION_REGISTRATION *prev;<BR>void* handler;<BR>};<BR>在Windows下SEH链表最后一个成员的handler指向Kernel32.DLL中函数UnhandledExceptionFilter的起始地址，利用这一特性我们可以写出更通用的代码：<BR>xor esi,esi<BR>lods dword [fs:esi];取得SEH链表的头指针<BR>@@:<BR>inc eax ;是否是最后一个SEH节点，检查prev是否为0xFFFFFFFF<BR>je @F<BR>dec eax<BR>xchg esi,eax<BR>LODSD ;下一个SEH节点<BR>jmp near @B<BR>@@:<BR>LODSD ;取得Kernel32.dll中UnhandledExceptionFilter的地址</P>
<P>在有的病毒直接以0x7FFDE000作为TEB的指针值，其原因在于在Windows 2003 SP1、Windows XP SP2以前的NT类系统上，该值是固定的，这样的确可以节省一两个字节。但是在Windows 2003 SP1、Windows XP SP2中，情况已经发生了变化，出于安全性的考虑，Windows系统开始动态映射TEB了，也就是说，指向TEB的指针值不再固定，因此这种硬编码的方法也就走到了尽头。此时可以按照前面的方法向低地址搜索判断直到找到Kernel32.dll的基址为止。Elkern中判断是否找到了Kernel32.dll基址的相关代码如下：<BR>search_api_addr_@1:<BR>add ebx,10000h<BR>jz short search_api_addr_seh_restore<BR>cmp word ptr [ebx],'ZM' ;是否是MZ标志<BR>jnz short search_api_addr_@1<BR>mov eax,[ebx+3ch]<BR>add eax,ebx<BR>cmp word ptr [eax],'EP' ;是否具有PE标志<BR>jnz short search_api_addr_@1<BR>;找到了kernel32.dll的基址</P>
<P>方法2：搜索PEB的相关结构获取Kernel32.DLL的基址</P>
<P>前述TEB偏移0x30处，亦即FS:[0x30]地址处保存着一个重要的指针，该指针指向PEB（进程环境块），PEB成员很多，这里并不介绍PEB的详细结构。我们只需要知道PEB结构的偏移0xC处保存着另外一个重要指针ldr，该指针指向PEB_LDR_DATA结构：<BR>typedef struct _PEB_LDR_DATA<BR>{</P>
<P>ULONG Length; // +0x00<BR>BOOLEAN Initialized; // +0x04<BR>PVOID SsHandle; // +0x08<BR>LIST_ENTRY InLoadOrderModuleList; // +0x0c<BR>LIST_ENTRY InMemoryOrderModuleList; // +0x14<BR>LIST_ENTRY InInitializationOrderModuleList;// +0x1c<BR>} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24<BR>　　该结构的后三个成员是指向LDR_MODULE链表结构中相应三条双向链表头的指针，分别是按照加载顺序、在内存中的地址顺序和初始化顺序排列的模块信息结构的指针。LDR_MODULE结构如下所示：<BR>typedef struct _LDR_MODULE<BR>{<BR>LIST_ENTRY InLoadOrderModuleList; // +0x00<BR>LIST_ENTRY InMemoryOrderModuleList; // +0x08<BR>LIST_ENTRY InInitializationOrderModuleList; // +0x10<BR>PVOID BaseAddress; // +0x18<BR>PVOID EntryPoint; // +0x1c<BR>ULONG SizeOfImage; // +0x20<BR>UNICODE_STRING FullDllName; // +0x24<BR>UNICODE_STRING BaseDllName; // +0x2c<BR>ULONG Flags; // +0x34<BR>SHORT LoadCount; // +0x38<BR>SHORT TlsIndex; // +0x3a<BR>LIST_ENTRY HashTableEntry; // +0x3c<BR>ULONG TimeDateStamp; // +0x44<BR>// +0x48<BR>} LDR_MODULE, *PLDR_MODULE;</P>
<P>　　Peb-&gt;Ldr-&gt;InInitializationOrderModuleList指向按照初始化顺序排序的第一个LDR_MODULE节点的InInitializationOrderModuleList成员的指针，在WinNT平台（不包含Win9X）下，该链表头节点的LDR_MODULE结构包含的是NTDLL.DLL的相关信息，而链表的下一个节点所包含的就是Kernel32.dll相关的信息了，该节点LDR_MODULE结构中的BaseAddress不正是我们所苦苦寻找的吗。注意InInitializationOrderModuleList是LDR_MODULE的第3个成员，因此要获取BaseAddress的地址，只需将其指针加8再derefrence即可。因此下面的汇编代码即可获取Kernel32.DLL的基址：</P>
<P>mov eax, dword ptr fs:[30h] ;获取PEB基址<BR>mov eax, dword ptr [eax+0ch] ;获取PEB_LDR_DATA结构指针<BR>mov esi, dword ptr [eax+1ch]<BR>;获取InInitializationOrderModuleList链表头第一个LDR_MODULE节点<BR>InInitializationOrderModuleList成员的指针<BR>lodsd ;获取双向链表当前节点后继的指针<BR>mov ebx, dword ptr [eax+08h] ;取其基地址，该结构当前包含的是<BR>　　　　　　　　　　　　　　　　　　　　　;kernel32.dll相关的信息</P>
<P>该方法在所有的Windows NT（包括Windows 2003 SP1和Windows XP SP2）操作系统上都是有效的，唯一的缺憾是由于PEB结构不同，该方法在Win9X系统上无效。听起来可能比较费解，还是用一张图更加清晰一些：</P>
<P><BR>图6 利用PEB搜索kernel32.dll基地址的过程</P>
<P>* 解析PE文件的导出函数表</P>
<P>　　PE文件的函数导出机制是进行模块间动态调用的重要机制，对于正常的程序，相关操作是由系统加载器在程序加载前自动完成的，对用户程序是透明的。但要想在病毒代码中实现函数地址的动态解析以取代加载器，那就有必要了解函数导出表的结构了。在图1中可以看到在PE头结构IMAGE_OPTIONAL_HEADER32结构中包含一个DataDirectory数组结构，该结构包含16个成员，每个成员都是一个IMAGE_DATA_DIRECTORY结构：<BR>　　typedef struct _IMAGE_DATA_DIRECTORY {<BR>　　 DWORD VirtualAddress;<BR>　　 DWORD Size;<BR>　　} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;<BR>　　DataDirectory数组的每个结构都指向一个重要的数据结构，第一个成员指向导出函数表（索引0），第2个成员指向PE文件的引入函数表（索引1）。DataDirectory中的第一个成员指向导出函数表的IMAGE_EXPORT_DIRECTORY结构：<BR>typedef struct _IMAGE_EXPORT_DIRECTORY {<BR>DWORD Characteristics;<BR>DWORD TimeDateStamp;<BR>WORD MajorVersion;<BR>WORD MinorVersion;<BR>DWORD Name;<BR>DWORD Base;<BR>DWORD NumberOfFunctions;<BR>DWORD NumberOfNames;<BR>DWORD AddressOfFunctions; // RVA from base of image<BR>DWORD AddressOfNames; // RVA from base of image<BR>DWORD AddressOfNameOrdinals; // RVA from base of image<BR>} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;<BR>AddressOfFunctions是一个双字数组，包含了所有导出函数的RVA，另外两个成员AddressOfNames也是一个双字数组，包含了指向导出函数名字的字符串的RVA，AddressOfNameOrdinals是一个字数组（16bit），和AddressOfNames数组是并行的，和AddressOfNames数组一起确定了相应引出函数的序号，该序号可直接用于索引AddressOfFunctions数组获取导出函数的地址。因此病毒搜索指定的API就包含了如下步骤：</P>
<P>a)获取NumberOfNames的值以及AddressOfNames、AddressOfNameOrdinals和AddressOfFunctions的数组的地址。<BR>b)搜索AddressOfNames数组，按字符串对比，若找到相应的API，转d<BR>c)若NumberOfNames名字尚未全部搜索完毕，转b继续搜索，若搜索完毕，则表明未找到进行错误处理，这一步通常可以省略，因为我们已经知道相应的DLL中肯定导出了相应的函数。<BR>d）获取当前函数名字指针在AddressOfNames数组中的索引，在AddressOfNameOrdinals数组中取出以该值索引的函数序号，以该序号值作为AddressOfFunctions数组的索引，在AddressOfFunctions数组中取出导出函数的RVA值，加上基址就得到了运行时导出函数的地址。</P>
<P>看起来似乎比较罗嗦，实际上这是PE设计时为考虑灵活性而做出的牺牲。不过实现起来还是比较简单的，通常汇编代码编译后不到100字节。以下是在Kernel32搜索GetProcAddress的完整代码：</P>
<P>push esi<BR>;esi=VA Kernel32.BASE<BR>;edi=RVA K32.pehdr<BR>mov ebp,esi<BR>mov edi,[ebp+edi+peh.DataDirectory]</P>
<P>push edi esi</P>
<P>mov eax,[ebp+edi+peexc.AddressOfNames]<BR>mov edx,[ebp+edi+peexc.AddressOfNameOrdinals]<BR>call @F<BR>db "GetProcAddress",0<BR>@@:<BR>pop edi<BR>mov ecx,15<BR>sub eax,4<BR>next_:<BR>add eax,4<BR>add edi,ecx<BR>sub edi,15<BR>mov esi,[ebp+eax]<BR>add esi,ebp<BR>mov ecx,15<BR>repz cmpsb ;进行字符串比较，判断是否为要查找的函数<BR>jnz next_</P>
<P>pop esi edi</P>
<P>sub eax,[ebp+edi+peexc.AddressOfNames]<BR>shr eax,1<BR>add edx,ebp<BR>movzx eax,word [edx+eax]<BR>add esi,[ebp+edi+peexc.AddressOfFunctions]<BR>add ebp,[esi+eax*4] ;ebp=Kernel32.GetProcAddress.addr<BR>;use GetProcAddress and hModule to get other func<BR>pop esi ;esi=kernel32 Base<BR>在前面解析导出函数表获取API地址的时候，采用的是直接比较字符串的方法判断是不是找到了相应的API，其实还可以计算函数名字的hash，然后同预计算的hash进行比对，现代的PE病毒更多采用的hash的方法，其原因在于一般的函数名字长度都大于4字节，而用hash只要占用4个字节或2个字节，可以节省空间，此外还有抗病毒分析的作用，因为hash要比字符串名字费解得多。hash算法的设计只要能保证无冲突即可，可以用crc等成熟算法，也可以设计自己的简单算法。在Elkern中就使用了crc16算法。<BR></P>
<DIV class=invisible id=reference>文章转帖自：<A href="" target=_blank></A> </DIV>
<DIV class=invisible><A href="http://blog.sina.com.cn/s/blog_4aa56ad9010008oe.html">http://blog.sina.com.cn/s/blog_4aa56ad9010008oe.html</A></DIV>]]></description>
</item><item>
<title><![CDATA[auto  register  static  extern  const]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=34136</link>
<author>zc9706</author>
<pubDate>2008/4/19 17:04:02</pubDate>
<description><![CDATA[
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="COLOR: red">auto</SPAN><SPAN lang=EN-US>:</SPAN></FONT><SPAN lang=EN-US style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt"> </SPAN><SPAN style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">这个这个关键字用于声明变量的生存期为自动，即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局变量，而在函数中定义的变量视为局部变量。这个关键字不怎么多写，因为所有的变量默认就是<SPAN lang=EN-US>auto</SPAN>的。<SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="COLOR: red">static</SPAN><SPAN lang=EN-US>: </SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">static</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用来修饰全局变量时，它就改变了全局变量的作用域，使其不能被别的程序</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">extern</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，限制在了当前文件里，当依然存放在全局存储区。</SPAN><FONT face="Times New Roman"> </FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">两种用途：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1，<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">宏观性统计变量。（全局统计时）</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2，<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">减少局部数组建立和赋值的开销。（经常调用时）</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="COLOR: red"><FONT face="Times New Roman">const<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用途：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 17.95pt; TEXT-INDENT: -17.95pt; mso-list: l0 level1 lfo2; tab-stops: list 18.0pt; mso-char-indent-count: -1.71"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1，<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰输入参数：①对于非内部数据类型的输入参数，应该将“值传递”的方式改为“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">引用传递”，目的是提高效率，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">e.g.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>void Fun(A a)</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改为</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">void Func(const A &amp;a)</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN><FONT face="Times New Roman"> </FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">②对于内部数据类型的输入参数，不要将“值传递”的方式改为“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">引用传递”，否则提高不了效率反而降低了函数可读性。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">e.g. void Fun(int x) </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不要改为</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> void Fun(const int &amp;x)</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo2; tab-stops: list 18.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2，<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰函数返回结果：①以“指针传递”方式的函数返回值加</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰，那么函数返回值的内容不能被修改，该返回值只能被赋给加</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰的同类型指针。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">e.g. const char *str=getstring(); </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">②若函数返回值采用“值传递方式”，由于函数会把返回值复制到外部临时的存储单元中，加</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰没有任何价值。③</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">成员函数的声明中，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">const</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字只能放在函数声明的尾部，表示该类成员不修改对象。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo2; tab-stops: list 18.0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">3，<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>Extern</SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">意味着“外来的”，它的作用在于告诉编译器：有这个变量，它可能不存在当前的文件中，但肯定存在于工程的其他文件中。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><SPAN lang=EN-US style="COLOR: red">register</SPAN><SPAN lang=EN-US>: </SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个关键字命令编译器尽可能的将变量存在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">CPU</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内部寄存器中而不是通过内存寻址访问以提高效率。</SPAN></P>]]></description>
</item><item>
<title><![CDATA[调节WINDOWS为保护眼睛的颜色！]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33819</link>
<author>zc9706</author>
<pubDate>2008/4/11 12:54:11</pubDate>
<description><![CDATA[桌面-&gt;右键-&gt;属性-&gt;外观-&gt;高级－&gt;项目选择（窗口）、颜色1（L）选择（其它）将色调改为：85。饱和度：123。亮度：205。－&gt;添加到自定义颜色－&gt;在自定义颜色选定点确定－&gt;确定<BR>这样所有的文档都不再是刺眼的白底黑字，而是非常柔和的豆沙绿色，这个色调是眼科专家配置的，长时间使用会很有效的缓解眼睛疲劳保护眼睛。]]></description>
</item><item>
<title><![CDATA[类似深构造函数的运算符‘=’重载用法]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33685</link>
<author>zc9706</author>
<pubDate>2008/4/9 20:25:00</pubDate>
<description><![CDATA[
<P>当类中包含指针成员*P而使用默认的赋值运算符‘=’来进行赋值操作的时候，会出现该类的这两个对象的*P指向内存中（堆中）同一片区域的现象，这时，如果这两个对象调用析构函数来释放空间，则会出现同一个内存区域被反复释放的危险操作。（=操作类似于浅析构函数。）</P>
<P>解决方法：重载‘=’操作符，并在函数中重新new空间，以方便析构函数释放。</P>
<P>e.g.</P>
<P>sample &amp;operator=(sample &amp;s)</P>
<P>{</P>
<P>delete p;&nbsp; //清除原来的指针</P>
<P>p=new char[strlen(s.p)+1];//重新申请指针及空间</P>
<P>strcpy(p,s.p);//拷贝构造过程</P>
<P>return *this;</P>
<P>}</P>]]></description>
</item><item>
<title><![CDATA[SDK简介]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33508</link>
<author>zc9706</author>
<pubDate>2008/4/6 10:21:48</pubDate>
<description><![CDATA[<A></A>
<P><FONT size=2>&nbsp;&nbsp;&nbsp; SDK是Software Development Kit的缩写，中文意思是“软件开发工具包”。这是一个覆盖面相当广泛的名词，可以这么说：辅助开发某一类软件的相关文档、范例和工具的集合都可以叫做“SDK”。具体到我们这个系列教程，我们后面只讨论广义 SDK 的一个子集——即开发 Windows 平台下的应用程序所使用的 SDK。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;其实上面只是说了一个 SDK 大概的概念而已，理解什么是 SDK 真有这么容易吗？恐怕没这么简单！为了解释什么是 SDK 我们不得不引入 API、动态链接库、导入库等等概念。^_^，不要怕，也就是几个新的名词而已，我也是到了大学快结束的时候才体会到其实学习新知识就是在学习新名词、新概念和新术语。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;首先要接触的是“API”，也就是 Application Programming Interface，其实就是操作系统留给应用程序的一个调用接口，应用程序通过调用操作系统的 API 而使操作系统去执行应用程序的命令（动作）。其实早在 DOS 时代就有 API 的概念，只不过那个时候的 API 是以中断调用的形式（INT 21h）提供的，在 DOS 下跑的应用程序都直接或间接的通过中断调用来使用操作系统功能，比如将 AH 置为 30h 后调用 INT 21h 就可以得到 DOS 操作系统的版本号。而在 Windows 中，系统 API 是以函数调用的方式提供的。同样是取得操作系统的版本号，在 Windows 中你所要做的就是调用 GetVersionEx() 函数。可以这么说，DOS API 是“Thinking in 汇编语言”的，而 Windows API 则是“Thinking in 高级语言”的。DOS API 是系统程序的一部分，他们与系统一同被载入内存并且可以通过中断矢量表找到他们的入口，那么 Windows API 呢？要说明白这个问题就不得不引入我们下面要介绍得这个概念——DLL。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;DLL（又是一个缩写，感觉 IT 这个行业里三字头缩写特别多），即 Dynamic Link Library（动态链接库）。我们经常会看到一些 .dll 格式的文件，这些文件就是动态链接库文件，其实也是一种可执行文件格式。跟 .exe 文件不同的是，.dll 文件不能直接执行，他们通常由 .exe 在执行时装入，内含有一些资源以及可执行代码等。其实 Windows 的三大模块就是以 DLL 的形式提供的（Kernel32.dll，User32.dll，GDI32.dll），里面就含有了 API 函数的执行代码。为了使用 DLL 中的 API 函数，我们必须要有 API 函数的声明（.H）和其导入库（.LIB），函数的原型声明不难理解，那么导入库又是做什么用的呢？我们暂时先这样理解：导入库是为了在 DLL 中找到 API 的入口点而使用的。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;所以，为了使用 API 函数，我们就要有跟 API 所对应的 .H 和 .LIB 文件，而 SDK 正是提供了一整套开发 Windows 应用程序所需的相关文件、范例和工具的“工具包”。到此为止，我们才真正的解释清楚了 SDK 的含义。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;由于 SDK 包含了使用 API 的必需资料，所以人们也常把仅使用 API 来编写 Windows 应用程序的开发方式叫做“SDK 编程”。而 API 和 SDK 是开发 Windows 应用程序所必需的东西，所以其它编程框架和类库都是建立在它们之上的，比如 VCL 和 MFC，虽然他们比起“SDK 编程”来有着更高的抽象度，但这丝毫不妨碍它们在需要的时候随时直接调用 API 函数。</FONT></P>
<P><FONT size=2>&nbsp;</FONT></P>
<P><FONT size=2><STRONG>说说SDK</STRONG></FONT></P>
<P>&nbsp;</P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;时下学计算机的大多想学编程，且大部分都是在Windows下工作的，而目前学得最热门的是VC，大多数人一开始就开始学习VC，VC是以C++为语言基础的开发工具，而C++是C语言的扩充，故要学好VC最好是先学好C和C++。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;用VC编写Windows程序有两种：1. Windwos c方式(SDK)，2. C++方式:即对SDK函数进行包装，如VC的MFC,BCB的OWL等。SDK编程就是直接调用Windows的API进行编程，平时人们常说"用 SDK写程序"就是指用Windows的API函数来写程序，API由上千个API函数组成(Win95的API有两千多个)。而MFC是API的封闭，结合面向对象程序设计的继承性和多态性组成一个个的"类"，共由一百多个类组成。尽管MFC比SDK方便，但要深入VC，直接去学MFC却是不明智的选择。只有在熟悉了MFC的运行机制的情况下，才有可能深入下去。所以学VC最好是先学用SDK编写程序，在此期间掌握Windows操作系统的工作原理和各API函数的应用，然后再深入MFC。</FONT></P>
<P>&nbsp;</P>
<P><FONT size=2><STRONG>编程环境</STRONG></FONT></P>
<P>&nbsp;</P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;我们仍然用VC6的IDE(集成开发环境)来编写SDK程序，启动VC6后选择File菜单的New...选项，在出现的New对话框的Projects标签内选择Win32 Application，然后在Projects Name指定项目的名字，在Location中指定路径后按OK按钮，在出现的对话框中，如果你想要用C语言来写程序可以选择An emtpy project，如果你想创建一个带有WinMain入口函数和普通参数的设定的项目，可以选择A simple Win32 application，如果您想创建一个简单典型的“Hello World!”Win32SDK application应用程序，可以选择A typical "Hello World!" application。确定项目类型后按Finish完成。</FONT></P>
<P><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp;在VC6环境下，你依然可以使用资源编辑器和ClassWizar等工具完成程序的编写。用SDK编写程序关键是能够程序的来龙去脉，当然那样效率会很低，不比VB、PB那么快，任何东西都是有得有失，如你熟悉用SDK写程序后，对MFC会比较容易上手的，关键要熟悉C++的三大特性。</FONT></P>
<P>转自：<A href="http://blog.chinaunix.net/u1/51097/showart_422616.html">http://blog.chinaunix.net/u1/51097/showart_422616.html</A></P>]]></description>
</item><item>
<title><![CDATA[死锁]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33491</link>
<author>zc9706</author>
<pubDate>2008/4/5 10:11:32</pubDate>
<description><![CDATA[<P>一，产生死锁<FONT color=#ff0000>必要条件</FONT><BR>1，互斥<BR>2，请求和保持<BR>3，不剥夺<BR>4，环路等待</P>
<P>二，死锁<FONT color=#ff0000>预防</FONT>（排除必要条件中的一个）<BR>1，排除请求和保持<BR>&nbsp;一次性申请所有的需要的资源，即一次请求。<BR>&nbsp;缺点：资源独占，利用率低。<BR>2，排除不剥夺<BR>&nbsp;当二次请求得不到满足时，释放已经占用的资源。<BR>&nbsp;缺点：增加了系统开销，降低了吞吐率。<BR>3，排除环路等待<BR>&nbsp;为所有的资源进行线形排队，并赋予不同的序号，所有进程对资源的访问必须严格</P>
<P>按照资源序号递增的次序提出。</P>
<P>三，死锁<FONT color=#ff0000>避免</FONT><BR>&nbsp;银行家算法<BR>四，死锁<FONT color=#ff0000>解除</FONT><BR>&nbsp;按照树的顺序从树根开始，对各子进程的资源剥夺以解除死锁的开销进行评估，不</P>
<P>断评估以选择出代价最小的资源剥夺进程，然后剥夺其资源，解除整个系统的死锁。夺该进程</P>
<P>的资源，使死锁被解除。</P>
<P>&nbsp;</P>]]></description>
</item><item>
<title><![CDATA[银行家算法]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33490</link>
<author>zc9706</author>
<pubDate>2008/4/5 9:55:43</pubDate>
<description><![CDATA[<SPAN id=ArticleContent1_ArticleContent1_lblContent> 转自：<A href="http://dev.csdn.net/article/52/52226.shtm">http://dev.csdn.net/article/52/52226.shtm</A>
<P>特别申明：转载一位大哥的程序<BR>一．算法介绍:<BR>**数据结构:<BR>1.可利用资源向量Available<BR>2.最大需求矩阵Max<BR>3.分配矩阵Allocation<BR>4.需求矩阵Need<BR>&nbsp; **功能介绍:<BR>模拟实现Dijkstra的银行家算法以避免死锁的出现.分两部分组成:<BR>第一部分:银行家算法(扫描)<BR>1．如果Request&lt;=Need,则转向2;否则,出错<BR>2．如果Request&lt;=Available,则转向3,否则等待<BR>3．系统试探分配请求的资源给进程<BR>4．系统执行安全性算法<BR>第二部分:安全性算法<BR>1.设置两个向量<BR>(1).工作向量:Work=Available(表示系统可提供给进程继续运行所需要的各类资源数目)<BR>(2).Finish:表示系统是否有足够资源分配给进程(True:有;False:没有).初始化为False<BR>2.若Finish[i]=False&amp;&amp;Need&lt;=Work,则执行3;否则执行4(I为资源类别)<BR>3.进程P获得第i类资源,则顺利执行直至完成!并释放资源:<BR>Work=Work+Allocation;<BR>Finish[i]=true;<BR>转2<BR>4.&nbsp; 若所有进程的Finish[i]=true,则表示系统安全;否则,不安全!</P>
<P>二.原代码及注释:<BR>#include&lt;iostream.h&gt;<BR>#include&lt;fstream.h&gt;<BR>#include&lt;stdlib.h&gt;<BR>#include "windows.h"<BR>#define MAX_PROCESS 32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //最大进程数<BR>#define MAX_COURCE 64&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //最大资源类别</P>
<P>int MAX_FACT_PROCESS;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实际总进程数<BR>int MAX_FACT_COURCE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实际资源类别数<BR>int Available[MAX_COURCE];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //可利用资源向量<BR>int Max[MAX_PROCESS][MAX_COURCE];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //最大需求矩阵<BR>int Allocation[MAX_PROCESS][MAX_COURCE];&nbsp;&nbsp; //分配矩阵<BR>int Need[MAX_PROCESS][MAX_COURCE];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //需求矩阵</P>
<P>int Request_PROCESS;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //发出请求的进程<BR>int Request_COURCE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //被请求资源类别<BR>int Request_COURCE_NEMBER;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //请求资源数</P>
<P>struct COMP{<BR>int value;<BR>int num;<BR>int next;<BR>};<BR>int flag=0;<BR>void Read_Initiate(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //读入初始化文档<BR>ifstream infile("Initiate.txt");<BR>&nbsp;&nbsp; if(!infile){<BR>cout&lt;&lt;"不能打开输入文件:"&lt;&lt;"Initiate.txt"&lt;&lt;'\n';<BR>exit(1);<BR>}<BR>cout&lt;&lt;"开始读入初始化文档"&lt;&lt;'\n';<BR>int ch;<BR>int Array[MAX_PROCESS*MAX_COURCE*2];<BR>int num=0;<BR>while(infile&gt;&gt;ch)<BR>&nbsp;&nbsp;&nbsp; Array[num++]=ch;<BR>num=0;<BR>&nbsp;&nbsp; MAX_FACT_COURCE=Array[num++];<BR>&nbsp;&nbsp; for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>Available[j]=Array[num++];<BR>&nbsp;&nbsp; MAX_FACT_PROCESS=Array[num++];<BR>for(int i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>Max[i][j]=Array[num++];<BR>}<BR>infile.close();<BR>}</P>
<P>void Write_Initiate(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //写入初始化文档(分配资源<BR>ofstream outfile("Initiate.txt");<BR>if(!outfile){<BR>cout&lt;&lt;"不能打开初始化文档："&lt;&lt;'\n';<BR>exit(1);<BR>}<BR>int Array[MAX_PROCESS*MAX_COURCE*2];<BR>int num=0;<BR>Array[num++]=MAX_FACT_COURCE;<BR>&nbsp;&nbsp; for(int i=0;i&lt;MAX_FACT_COURCE;i++)<BR>Array[num++]=Available[i];<BR>Array[num++]=MAX_FACT_PROCESS;<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>Array[num++]=Max[i][j];</P>
<P>num=0;<BR>outfile&lt;&lt;Array[num++]&lt;&lt;" ";<BR>for(i=0;i&lt;MAX_FACT_COURCE;i++)<BR>outfile&lt;&lt;Array[num++]&lt;&lt;" ";<BR>outfile&lt;&lt;'\n'&lt;&lt;Array[num++]&lt;&lt;endl;<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>outfile&lt;&lt;Array[num++]&lt;&lt;" ";<BR>outfile&lt;&lt;endl;<BR>}<BR>DWORD m_delay=3000;<BR>Sleep(m_delay);<BR>outfile.close();<BR>cout&lt;&lt;"修改初始化文档成功!"&lt;&lt;endl;<BR>}</P>
<P>void Allocated_list(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //读入已分配资源列表<BR>ifstream infile("Allocated_list.txt");<BR>&nbsp;&nbsp; if(!infile){<BR>cout&lt;&lt;"不能打开输入文件:"&lt;&lt;"Allocated_list.txt"&lt;&lt;'\n';<BR>exit(1);<BR>}<BR>cout&lt;&lt;"开始读入已分配资源列表"&lt;&lt;'\n';<BR>int ch,num=0;<BR>int Array[MAX_PROCESS*MAX_COURCE];<BR>while(infile&gt;&gt;ch)<BR>Array[num++]=ch;<BR>num=0;<BR>for(int i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>Allocation[i][j]=Array[num++];<BR>infile.close();<BR>}</P>
<P>void Set_Need(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置需求矩阵<BR>cout&lt;&lt;"设置需求矩阵"&lt;&lt;'\n';<BR>for(int i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>Need[i][j]=Max[i][j]-Allocation[i][j];<BR>}</P>
<P>void Read_Request(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //读入请求向量<BR>ifstream infile("Request_list.txt");<BR>&nbsp;&nbsp; if(!infile){<BR>cout&lt;&lt;"不能打开输入文件:"&lt;&lt;"Request_list.txt"&lt;&lt;'\n';<BR>exit(1);<BR>}<BR>&nbsp;&nbsp; cout&lt;&lt;"开始读入请求向量"&lt;&lt;'\n';<BR>int Array[3];<BR>int num=0,ch;<BR>while(infile&gt;&gt;ch)<BR>&nbsp;&nbsp;&nbsp; Array[num++]=ch;<BR>&nbsp;&nbsp; Request_PROCESS=Array[0];<BR>&nbsp;&nbsp; Request_COURCE=Array[1];<BR>&nbsp;&nbsp; Request_COURCE_NEMBER=Array[2];<BR>infile.close();<BR>}</P>
<P>void Write_Allocation(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //修改资源分配列表(资源分配)<BR>ofstream outfile("Allocated_list.txt");<BR>if(!outfile){<BR>cout&lt;&lt;"不能打开资源分配列表："&lt;&lt;'\n';<BR>exit(1);<BR>}<BR>for(int i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>outfile&lt;&lt;Allocation[i][j]&lt;&lt;" ";<BR>outfile&lt;&lt;endl;<BR>}<BR>&nbsp;&nbsp; DWORD m_delay=3000;<BR>Sleep(m_delay);<BR>cout&lt;&lt;"修改资源分配列表成功!"&lt;&lt;endl;<BR>outfile.close();<BR>}</P>
<P>void Allocate_Source(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //开始分配(已通过扫描和安全性检测)<BR>cout&lt;&lt;'\n'&lt;&lt;"开始给第"&lt;&lt;Request_PROCESS&lt;&lt;"个进程分配第"&lt;&lt;Request_COURCE<BR>&lt;&lt;"类资源"&lt;&lt;Request_COURCE_NEMBER&lt;&lt;"个"&lt;&lt;endl;<BR>Write_Initiate();<BR>Write_Allocation();<BR>DWORD m_delay=3000;<BR>Sleep(m_delay);<BR>cout&lt;&lt;'\n'&lt;&lt;"祝贺您，资源分配已成功!"&lt;&lt;endl;<BR>}</P>
<P>void Test_Safty(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //安全性检测<BR>cout&lt;&lt;'\n'&lt;&lt;"进入安全性检测!"&lt;&lt;endl;<BR>&nbsp;&nbsp; int Work[MAX_COURCE];<BR>for(int i=0;i&lt;MAX_FACT_COURCE;i++){<BR>Work[i]=Available[i];<BR>}<BR>&nbsp;&nbsp; bool Finish[MAX_PROCESS][MAX_COURCE];<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>Finish[i][j]=false;<BR>COMP Array[32];<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>{<BR>Array[i].value=Need[i][Request_COURCE-1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array[i].num=i;<BR>}<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>for(int j=i+1;j&lt;MAX_FACT_PROCESS;j++){<BR>if(Array[i].value&gt;=Array[j].value){<BR>int t;<BR>t=Array[j].value;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array[j].value=Array[i].value;<BR>Array[i].value=t;<BR>t=Array[j].num;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array[j].num=Array[i].num;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array[i].num=t;<BR>}<BR>else continue;<BR>}<BR>DWORD m_delay=3000;<BR>Sleep(m_delay);<BR>/*for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>cout&lt;&lt;Need[i][j]&lt;&lt;'\t';<BR>cout&lt;&lt;endl;<BR>}<BR>*/<BR>if(Finish[Request_PROCESS-1][Request_COURCE-1]==false&amp;&amp;Need[Request_PROCESS-1][Request_COURCE-1]&lt;=Work[Request_COURCE-1])<BR>{<BR>Work[Request_COURCE-1]=Work[Request_COURCE-1]+Allocation[Request_PROCESS-1][Request_COURCE-1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Finish[Request_PROCESS-1][Request_COURCE-1]=true;<BR>}<BR>else<BR>{<BR>cout&lt;&lt;"未通过安全性测试，不与以分配"&lt;&lt;endl;<BR>exit(0);<BR>}<BR>&nbsp;&nbsp; for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>if(Array[i].num==Request_PROCESS-1)<BR>continue;<BR>if(Array[i].num!=Request_PROCESS-1&amp;&amp;Finish[Array[i].num][Request_COURCE-1]==false&amp;&amp;Need[Array[i].num][Request_COURCE-1]&lt;=Work[Request_COURCE-1]){<BR>Work[Request_COURCE-1]=Work[Request_COURCE-1]+Allocation[Array[i].num][Request_COURCE-1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Finish[Array[i].num][Request_COURCE-1]=true;<BR>}<BR>}<BR>&nbsp;&nbsp; for(i=0;i&lt;MAX_FACT_PROCESS;i++)<BR>{<BR>if(Finish[i][Request_COURCE-1]==true)<BR>continue;<BR>else<BR>{<BR>cout&lt;&lt;"未通过安全性测试，不与以分配"&lt;&lt;endl;<BR>&nbsp;&nbsp; exit(0);<BR>}<BR>}<BR>cout&lt;&lt;'\n'&lt;&lt;"找到一个安全序列:"&lt;&lt;"P"&lt;&lt;Request_PROCESS&lt;&lt;"---&gt;";<BR>&nbsp;&nbsp; for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>if(Array[i].num==Request_PROCESS)<BR>continue;<BR>else<BR>cout&lt;&lt;"P"&lt;&lt;Array[i].num&lt;&lt;"---&gt;";<BR>}<BR>cout&lt;&lt;'\n'&lt;&lt;"已通过安全性测试!"&lt;&lt;endl;<BR>Allocate_Source();<BR>}</P>
<P>void RUN(void){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //执行银行家算法</P>
<P>&nbsp;&nbsp; cout&lt;&lt;"*************************************************"&lt;&lt;'\n'&lt;&lt;"点击1执行!"<BR>&lt;&lt;'\n'&lt;&lt;"点击2退出!"<BR>&lt;&lt;'\n'&lt;&lt;"*************************************************"&lt;&lt;endl;<BR>cin&gt;&gt;flag;<BR>if(flag==2)<BR>exit(0);<BR>if(flag==1)<BR>{<BR>cout&lt;&lt;"开始扫描请求信息!"&lt;&lt;endl;<BR>DWORD m_delay=3000;<BR>Sleep(m_delay);<BR>if(Request_COURCE_NEMBER&gt;Need[Request_PROCESS-1][Request_COURCE-1])<BR>{<BR>cout&lt;&lt;'\n'&lt;&lt;"第"&lt;&lt;Request_PROCESS&lt;&lt;"个进程请求第"&lt;&lt;Request_COURCE&lt;&lt;"类资源"&lt;&lt;Request_COURCE_NEMBER&lt;&lt;"个"&lt;&lt;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"可是已超出该进程尚需的该类资源的最大数量,所以不予以分配!!"&lt;&lt;endl;<BR>exit(0);<BR>}<BR>if(Request_COURCE_NEMBER&gt;Available[Request_COURCE-1])<BR>{<BR>cout&lt;&lt;'\n'&lt;&lt;"第"&lt;&lt;Request_PROCESS&lt;&lt;"个进程请求第"&lt;&lt;Request_COURCE&lt;&lt;"类资源"&lt;&lt;Request_COURCE_NEMBER&lt;&lt;"个"&lt;&lt;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"可是系统中尚无足够的资源,所以进入等待队列!!"&lt;&lt;endl;<BR>exit(0);<BR>}<BR>&nbsp;&nbsp; else{<BR>Available[Request_COURCE-1]=Available[Request_COURCE-1]-Request_COURCE_NEMBER;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Allocation[Request_PROCESS-1][Request_COURCE-1]=Allocation[Request_PROCESS-1][Request_COURCE-1]+Request_COURCE_NEMBER;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Need[Request_PROCESS-1][Request_COURCE-1]=Need[Request_PROCESS-1][Request_COURCE-1]-Request_COURCE_NEMBER;<BR>cout&lt;&lt;"扫描通过"&lt;&lt;endl;<BR>Sleep(m_delay);<BR>Test_Safty();<BR>}<BR>}<BR>else {<BR>cout&lt;&lt;"输入错误,请重新输入!"&lt;&lt;'\n';<BR>RUN();<BR>}<BR>}</P>
<P>&nbsp;</P>
<P>void main(void){<BR>&nbsp;&nbsp; Read_Initiate();<BR>cout&lt;&lt;MAX_FACT_COURCE&lt;&lt;'\t';<BR>for(int i=0;i&lt;MAX_FACT_COURCE;i++)<BR>cout&lt;&lt;Available[i]&lt;&lt;'\t';<BR>cout&lt;&lt;endl&lt;&lt;MAX_FACT_PROCESS&lt;&lt;endl;<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>cout&lt;&lt;Max[i][j]&lt;&lt;'\t';<BR>cout&lt;&lt;endl;<BR>}<BR>DWORD m_delay=3000;<BR>Sleep(m_delay);<BR>cout&lt;&lt;"读入成功"&lt;&lt;'\n';</P>
<P>Allocated_list();<BR>for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>cout&lt;&lt;Allocation[i][j]&lt;&lt;'\t';<BR>cout&lt;&lt;endl;<BR>}<BR>Sleep(m_delay);<BR>cout&lt;&lt;"读入成功"&lt;&lt;'\n';</P>
<P>Set_Need();<BR>&nbsp;&nbsp; for(i=0;i&lt;MAX_FACT_PROCESS;i++){<BR>for(int j=0;j&lt;MAX_FACT_COURCE;j++)<BR>cout&lt;&lt;Need[i][j]&lt;&lt;'\t';<BR>cout&lt;&lt;endl;<BR>}<BR>&nbsp;&nbsp; Sleep(m_delay);<BR>cout&lt;&lt;"设置成功"&lt;&lt;'\n';</P>
<P>&nbsp;&nbsp; Read_Request();<BR>cout&lt;&lt;'\n'&lt;&lt;"第"&lt;&lt;Request_PROCESS&lt;&lt;"个进程请求第"&lt;&lt;Request_COURCE&lt;&lt;"类资源"&lt;&lt;Request_COURCE_NEMBER&lt;&lt;"个"&lt;&lt;endl;<BR>cout&lt;&lt;'\n'&lt;&lt;"读入成功"&lt;&lt;'\n';</P>
<P>RUN();<BR>}</P>
<P>三．数据测试<BR>注:数组Array[I]表示第I+1个实际意义量<BR>&nbsp;&nbsp;&nbsp;&nbsp; 需要创建三个txt文本。<BR>1.Initiate.txt文本<BR>3 3 3 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //共有3类资源,Available[0]=3; Available[1]=3; Available[2]=2<BR>5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //当前系统中有个进程<BR>7 5 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Max[0][0]=7<BR>3 2 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Max[1][1]=3<BR>9 0 2<BR>2 2 2 <BR>4 3 3<BR>2.Allocated_list.txt文本<BR>0 1 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Allocation[0][1]=1<BR>2 0 0<BR>3 0 2<BR>2 1 1<BR>0 0 2<BR>3.Request_list.txt文本<BR>2 1 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //第2个进程请求第1类资源1个Request[1][0]=1<BR>四．程序说明:<BR>本程序假设当前时刻只有一个进程请求某一类资源n个.<BR>若要满足某个进程当前时刻同时请求不止一类资源,则需要为最大需求矩阵Max,分配矩阵Allocation和需求矩阵Need增加维数,当然代码量也将大大增加,但是算法逻辑本身并无变化.</P></SPAN>]]></description>
</item><item>
<title><![CDATA[关于printf的另类用法]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33468</link>
<author>zc9706</author>
<pubDate>2008/4/4 21:12:56</pubDate>
<description><![CDATA[
<P>main()<BR>{<BR>&nbsp;char a[]="a";<BR>&nbsp;char b='b';<BR>&nbsp;int c=0x12ff7c;<BR>&nbsp;printf("%x\n",a);&nbsp; //输出&nbsp; 12ff7c<BR>&nbsp;printf("%c\n",a);&nbsp; //输出&nbsp; |<BR>&nbsp;printf("%d\n",b);&nbsp; //输出&nbsp; 98<BR>&nbsp;printf("%c\n",b);&nbsp; //输出&nbsp; b<BR>&nbsp;printf("%c\n",c);&nbsp; //输出&nbsp; |<BR>&nbsp;printf("%x\n","wefd"); //输出&nbsp; ？<BR>&nbsp;printf("%c\n","dfdfd"); //输出&nbsp; ？<BR>&nbsp;printf("%c\n","fd");&nbsp;&nbsp;&nbsp; //输出&nbsp; ？<BR>&nbsp;printf("%c\n","jku");&nbsp;&nbsp; //输出&nbsp; ？<BR>&nbsp;int aa=020,ba=0x10; <BR>&nbsp;printf("%d\n",aa);&nbsp; //输出16<BR>&nbsp;printf("%d\n",ba);&nbsp; //输出16</P>
<P>}</P>
<P><BR>1, a是一个数组，所以a为地址，即0x12ff7c，所以%c输出时为将该地址当成单个字符处理，即对地位的0x7c以%c格式输出，即输出“|”(因为|的ASCII码是0x7C)。<BR>2, b是一个字符，所以b在内存中为b的ASCII码98，所以很好理解为什么输出的是98 和b。<BR>3, c是一个数字，0x7c为低位，所以输出0x7c的ASCII码"|"。<BR>4, 最后四个为将字符串以%c的格式输出，输出为“？”，不知道该如何理解。。。。。。</P>
<P>5，aa和ba一个是8进制一个是16进制。</P>]]></description>
</item><item>
<title><![CDATA[祝贺MY BLOG访问量达到88888次！]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33277</link>
<author>zc9706</author>
<pubDate>2008/3/31 22:17:10</pubDate>
<description><![CDATA[blog名称:我的IT人生<BR>日志总数:64<BR>评论数量:55<BR>留言数量:0<BR>访问次数:88888<BR>建立时间:2006年4月5日]]></description>
</item><item>
<title><![CDATA[如何用栈实现递归与非递归的转换（2）（转 GOOD）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33276</link>
<author>zc9706</author>
<pubDate>2008/3/31 22:03:18</pubDate>
<description><![CDATA[<P><BR>三.三个例子 <BR>好了上面的理论知识已经足够了,下面让我们看看几个例子,结合例子加深我们对问题的认识 <BR>.即使上面的理论你没有完全明白,不要气馁,对事物的认识总是曲折的,多看多想你一定可以明 <BR>白(事实上我也是花了两个星期的时间才弄得比较明白得). </P>
<P>1)例子一: </P>
<P>f(n) = 　n + １;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (n &lt;２)　<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　　　 f[n/2] + f[n/4](n &gt;;= 2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个例子相对简单一些,递归程序如下:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; f_recursive(int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int u1, u2, f;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (n &lt; 2) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f = n + 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u1 = f_recursive((int)(n/2));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u2 = f_recursive((int)(n/4));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f = u1 * u2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;</P>
<P>下面按照我们上面说的,确定好递归调用树的结构,这一步是最重要的.首先,什么是叶子结点 <BR>,我们看到当n &lt; 2时f = n + 1,这就是返回的语句,有人问为什么不是f = u1 * u2,这也是一个 <BR>返回的语句呀?答案是:这条语句是在u1 = exmp1((int)(n/2))和u2 = exmp1((int)(n/4))之后 <BR>执行的,是这两条语句的父结点. 其次,什么是当前结点,由上面的分析,f = u1 * u2即是父结点 <BR>.然后,顺理成章的u1 = exmp1((int)(n/2))和u2 = exmp1((int)(n/4))就分别是左子树和右子 <BR>树了.最后,我们可以看到,这个递归函数可以表示成后序遍历的二叉调用树.好了,树的情况分析 <BR>到这里,下面来分析一下栈的情况,看看我们要把什么数据保存在栈中,在上面给出的后序遍历的如果这个过程你没 <BR>非递归程序中我们已经看到了要加入一个标志域,因此在栈中要保存这个标志域;另外,u1,u2和 <BR>每次调用递归函数时的n/2和n/4参数都要保存,这样就要分别有三个栈分别保存:标志域,返回量 <BR>和参数,不过我们可以做一个优化,因为在向上一层返回的时候,参数已经没有用了,而返回量也 <BR>只有在向上返回时才用到,因此可以把这两个栈合为一个栈.如果对于上面的分析你没有明白,建 <BR>议你根据这个递归函数写出它的递归栈的变化情况以加深理解,再次重申一点:前期对树结构和 <BR>栈的分析是最重要的,如果你的程序出错,那么请返回到这一步来再次分析,最好把递归调用树和 <BR>栈的变化情况都画出来,并且结合一些简单的参数来人工分析你的算法到底出错在哪里. <BR>ok,下面给出我花了两天功夫想出来的非递归程序(再次提醒你不要气馁,大家都是这么过来 <BR>的). </P>
<P>int&nbsp;&nbsp;&nbsp;&nbsp; f_nonrecursive(int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int stack[20], flag[20], cp;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 初始化栈和栈顶指针 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack[0] = n;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[0] = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (cp &gt;;= 0) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch(flag[cp]) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问的是根结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (stack[cp] &gt;;= 2) { /* 左子树入栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp] = 1; /* 修改标志域 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack[cp] = (int)(stack[cp - 1] / 2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp] = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 否则为叶子结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack[cp] += 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp] = 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问的是左子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (stack[cp] &gt;;= 2) { /* 右子树入栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp] = 2; /* 修改标志域 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp += 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack[cp] = (int)(stack[cp - 2] / 4);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp] = 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 否则为叶子结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack[cp] += 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp] = 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flag[cp - 1] == 2) { /* 当前是右子树吗? */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 如果是右子树, 那么对某一棵子树的后序遍历已经<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 结束,接下来就是对这棵子树的根结点的访问<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack[cp - 2] = stack[cp] * stack[cp - 1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag[cp - 2] = 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp = cp - 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 否则退回到后序遍历的上一个结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp--;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return stack[0];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>算法分析:a)flag只有三个可能值:0表示第一次访问该结点,1表示访问的是左子树,2表示 <BR>已经结束了对某一棵子树的访问,可能当前结点是这棵子树的右子树,也可能是叶子结点.b)每 <BR>遍历到某个结点的时候,如果这个结点满足叶子结点的条件,那么把它的flag域设为2;否则根据 <BR>访问的是根结点,左子树或是右子树来设置flag域,以便决定下一次访问该节点时的程序转向. </P>
<P>&nbsp;</P>
<P><BR>2)例子二 </P>
<P>快速排序算法 <BR>递归算法如下: </P>
<P>void&nbsp;&nbsp;&nbsp; swap(int array[], int low, int high)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int temp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = array[low];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array[low] = array[high];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array[high] = temp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; partition(int array[], int low, int high)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = array[low];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (low &lt; high) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (low &lt; high &amp;&amp; array[high] &gt;;= p) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; high--;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swap(array,low,high);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (low &lt; high &amp;&amp; array[low]&nbsp; &lt;= p) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; low++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swap(array,low,high);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return low;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp; qsort_recursive(int array[], int low, int high)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(low &lt; high) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = partition(array, low, high);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qsort_recursive(array, low, p - 1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qsort_recursive(array, p + 1, high);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>需要说明一下快速排序的算法: partition函数根据数组中的某一个数把数组划分为两个部分, <BR>左边的部分均不大于这个数,右边的数均不小于这个数,然后再对左右两边的数组再进行划分.这 <BR>里我们专注于递归与非递归的转换,partition函数在非递归函数中同样的可以调用(其实 <BR>partition函数就是对当前结点的访问). <BR>再次进行递归调用树和栈的分析: <BR>递归调用树:a)对当前结点的访问是调用partition函数;b)左子树: <BR>qsort_recursive(array, low, p - 1);c)右子树:qsort_recursive(array, p + 1, high); <BR>d)叶子结点:当low &lt; high时;e)可以看出这是一个先序调用的二叉树 <BR>栈:要保存的数据是两个表示范围的坐标. </P>
<P>void&nbsp;&nbsp;&nbsp; qsort_nonrecursive(int array[], int low, int high)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m[50], n[50], cp, p; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 初始化栈和栈顶指针 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m[0] = low;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n[0] = high;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (m[cp] &lt; n[cp]) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (m[cp] &lt; n[cp]) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 向左走到尽头 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = partition(array, m[cp], n[cp]); /* 对当前结点的访问 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m[cp] = m[cp - 1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n[cp] = p - 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 向右走一步 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m[cp + 1] = n[cp] + 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n[cp + 1] = n[cp - 1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>3)例子三 <BR>阿克曼函数: </P>
<P>akm(m, n) = n + 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (m = 0时)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; akm(m - 1, 1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (n = 0时)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; akm(m - 1, akm(m, n - 1)); (m != 0且n != 0时)</P>
<P>递归算法如下: </P>
<P>int&nbsp;&nbsp;&nbsp;&nbsp; akm_recursive(int m, int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int temp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m == 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (n + 1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (n == 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return akm_recursive(m - 1, 1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = akm_recursive(m, n - 1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return akm_recursive(m - 1, temp);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>这个例子相对难一些,不过只要正确的分析递归调用树和栈的变化情况就不难解决,先卖个关子,晚上再来公布答案,感兴趣的可以先想想.</P>
<P>好了,让我们回到递归与非递归的世界中,继续未完的旅途. </P>
<P>这道题的难点就是确定递归调用树的情况,因为从akm函数的公式可以看到,有三个递归调用,一般 <BR>而言,有几个递归调用就会有几棵递归调用的子树,不过这只是一般的情况,不一定准确,也不一定非要 <BR>机械化的这么作,因为通常情况下我们可以做一些优化,省去其中的一些部分,这道题就是一个例子. <BR>递归调用树的分析:a)是当m=0时是叶子结点;b)左子树是akm(m - 1, akm(m, n - 1))调用中的 <BR>akm(m, n - 1)调用,当这个调用结束得出一个值temp时,再调用akm(m - 1, temp),这个调用是右子树 <BR>.c)从上面的分析可以看出,这个递归调用树是后序遍历的树. <BR>栈的分析:要保存的数据是m, n,当n = 0 或 m = 0时开始退栈,当n = 0时把上一层栈的m值变为 <BR>m - 1,n变为1，当m = 0时把上一层栈的m值变为0,n变为n + 1.从这个分析过程可以看出,我们省略了 <BR>当n = 0时的akm(m - 1, 1)调用,原来在系统机械化的实现递归调用的过程中,这个调用也是一棵子树, <BR>不过经过分析,我们用修改栈中数据的方式进行了改进. </P>
<P>int&nbsp;&nbsp;&nbsp;&nbsp; akm_nonrecursive(int m, int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m1[50], n1[50], cp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m1[0] = m;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n1[0] = n;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (m1[cp] &gt;; 0) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 压栈, 直到m1[cp] = 0 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (n1[cp] &gt;; 0) { /* 压栈, 直到n1[cp] = 0 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m1[cp] = m1[cp - 1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n1[cp] = n1[cp - 1] - 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 计算akm(m - 1, 1),当n = 0时 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m1[cp] = m1[cp] - 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n1[cp] = 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 改栈顶为akm(m - 1, n + 1),当m = 0时 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cp--;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m1[cp] = m1[cp] - 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n1[cp] = n1[cp + 1] + 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } while (cp &gt;; 0 || m1[cp] &gt;; 0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return n1[0] + 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>三.递归程序的分类及用途</P>
<P>&nbsp;</P>
<P>&nbsp;&nbsp; 递归程序分为两类:尾部递归和非尾部递归.上面提到的几个例子都是非尾部递归,在一个选择分支中有至少</P>
<P>一个的递归调用.相对而言,尾部递归就容易很多了,因为与非尾部递归相比,每个选择分支只有一个递归调用,</P>
<P>我们在解决的时候就不需要使用到栈,只要循环和设置好循环体就可以了.下面再举几个尾部递归的例子吧,比较</P>
<P>简单我就不多说什么了.</P>
<P><BR>&nbsp;&nbsp; 1)例子一</P>
<P>g(m, n) = 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (m = 0, n &gt;;= 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = g(m - 1, 2n) + n; (m &gt;; 0, n &gt;;= 0)</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; a)递归程序<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_recursive(int m, int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m == 0 &amp;&amp; n &gt;;= 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (g_recurse(m - 1, 2*n) + n);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; b)非递归程序</P>
<P><BR>int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_nonrecursive(int m, int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (p = 0; m &gt;; 0 &amp;&amp; n &gt;;= 0; m--, n *= 2) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p += n;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return p;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 2)例子二</P>
<P><BR>&nbsp;f(n) = n + 1 (n = 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n * f(n/2)&nbsp; (n &gt;; 0)</P>
<P>&nbsp;&nbsp;&nbsp; a)递归程序<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f_recursive(int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (n == 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (n * f_recurse(n/2));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; b)非递归程序</P>
<P><BR>int&nbsp;&nbsp;&nbsp;&nbsp; f_nonrecursive(int n)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (m = 1; n &gt;; 0; n /= 2) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m *= n;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return m++;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 分析完了递归程序的分类,让我们回头看看在向非递归转换的过程中用到了什么来实现转换:</P>
<P>&nbsp;&nbsp; 1)循环,因为程序要在某个条件下一直执行下去,要代替递归程序,循环必不可少,对于尾部递归,循环结束的</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 条件十分容易确定,只要按照不同分支的条件写出来就可以了.而对于非尾部递归程序,循环结束的条件一</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 般是当栈为空时或者是结束了对递归调用树的遍历从树的根结点退出时,而且有的时候写成while()的形式</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; ,有时写成do ...while的形式(如上面的akm函数),具体怎样,很难说清楚,取决于你对整个递归程序的分析</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; .</P>
<P>&nbsp;&nbsp; 2)递归调用树,树的结构在转换的过程中是不可见的,你不必为转换专门写一个树结构,不过能不能把递归调用</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 中的树遍历方式以及叶子结点,左子树,右子树等元素确定好是你能否正确解决问题的关键(这一点已经在</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 上面的分析过程中展露无疑),确定好这些后,剩下的工作大部分就是按照给出的几种不同的遍历树的方式</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 把程序进行改写,这个过程就考验你对树结构还有遍历方式是否很好的掌握了(看出基础的重要了吗?如果</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 回答是,那么和我一样好好的打好基础吧,一切都还不晚!!).对于尾部递归而言,可以看作没有递归调用树,</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 所以尾部递归的难度大大降低了.</P>
<P>&nbsp;&nbsp; 3)栈,非尾部调用中需要栈来保存数据,这一点已经很清楚了,需要注意几个问题:a)栈有时可能会出现不够的</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 情况,拿上面的akm函数来说,我用的50个元素的数组,你如果把m和n值设置得大一些,这个栈就不能用了,有</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 时你的算法正确了,不过没有注意到这个问题还是会出错的;反过来说,在递归调用中,系统或者编译器的优</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 化功能不够好的化,在这个栈上可能会消耗很多空间,这个时候如果你把程序改成非递归的形式,然后再用</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 动态分配技术分配栈可能就会把程序的性能提高一大块--这也是我们学习这门技术的意义之一,因为系统</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 是机械化的,你如果知道更好的优化办法,为什么不用呢?</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp; 什么时候可以用递归解决问题?到了这一步,如果你对于上面说的已经相当明白的话,这个问题不难回答,如果</P>
<P>&nbsp;&nbsp; 我们要解决的问题要分成几个小的部分,而其中的一些与你要解决的问题是一样的,只不过是问题的规模(如</P>
<P>&nbsp;&nbsp; 参数等)小了,那么这样的问题可以用递归来解决.根据问题设计好一个递归是所有这些的基础,转换也是在原</P>
<P>&nbsp;&nbsp; 来的递归程序上进行的,所以这一步一定要做好.通常,设计一个递归程序要注意一下几个问题:a)可以递归解</P>
<P>&nbsp;&nbsp; 决的问题是什么?b)入口和出口参数是什么--即要明确好出入的接口.</P>
<P>&nbsp;&nbsp; </P>
<P>四.学习过程中参考到的一些资料</P>
<P>&nbsp;</P>
<P>&nbsp;&nbsp; 1)&lt;&lt;算法导论&gt;;&gt;;&nbsp; 国防科大出版社&nbsp; 张益新 沈雁编著</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 这本书比较老了,也许很难找了,不过参考价值不大,里面专门用了一章来讲这个问题,可惜用的是goto来实</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 现递归调用的选择分支(所以我说参考价值不大),如果没有也无所谓的.</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp; 2)http://db.pku.edu.cn/mzhang/&nbsp; 北京大学张铭老师的主页.</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 上面可以找到一个张老师讲解递归和非递归转换的视频,有大概50多分钟吧,我没有听完,原先看第一本书</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 的对于如何不用goto实现选择分支十分不解,张老师讲到的递归调用树真正让我豁然开朗,从此以后虽然还</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 是有很多问题,不过明白了这个大体的解决思路就有了.</P>
<P>&nbsp;&nbsp; 3)&lt;&lt;数据结构&gt;;&gt;;&nbsp; 清华大学出版社&nbsp; 严蔚敏著</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 这本书讲到栈的时候略微讲到了一些这方面的内容,网上可以找到一位叫一具的仁兄写的这本书的习题解答</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; ,可以自己去找一找,我的中序和后序遍历的算法完全看的他写的.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4) <A href="http://www.tztvu.edu.cn/kfjy/bkjy/jsj/bxk/sjjg/kcdh/">http://www.tztvu.edu.cn/kfjy/bkjy/jsj/bxk/sjjg/kcdh/</A>忘了是什么的网页了<BR>&nbsp;&nbsp;&nbsp;&nbsp; 里面的一个dn5.doc的文件中有讲解转换akm函数的方法,给我的启发很大,如果你对于我说的akm函数还有疑<BR>&nbsp;&nbsp;&nbsp;&nbsp; 问,那么可以看看人家写的,他把递归调用树和栈的变化情况都写出来了,非常直观.</P>]]></description>
</item><item>
<title><![CDATA[如何用栈实现递归与非递归的转换（1）（转 GOOD）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33273</link>
<author>zc9706</author>
<pubDate>2008/3/31 21:31:09</pubDate>
<description><![CDATA[
<P><BR>如何用栈实现递归与非递归的转换</P>
<P><A href="http://www.chinaunix.net/">http://www.chinaunix.net</A> 作者:converse 发表于：2006-08-24 09:00:06</P>
<P>原文：<A href="http://www.chinaunix.net/jh/23/331522.html">http://www.chinaunix.net/jh/23/331522.html</A><BR>　　　<A href="http://blog.csdn.net/dragondwy/archive/2006/06/30/855391.aspx">http://blog.csdn.net/dragondwy/archive/2006/06/30/855391.aspx</A>&nbsp; <A href="http://liqunsun.spaces.live.com/blog/cns!285A08B51269F219!114.entry">http://liqunsun.spaces.live.com/blog/cns!285A08B51269F219!114.entry</A><BR>如何用栈实现递归与非递归的转换 </P>
<P>一.为什么要学习递归与非递归的转换的实现方法? <BR>1)并不是每一门语言都支持递归的. <BR>2)有助于理解递归的本质. <BR>3)有助于理解栈,树等数据结构. </P>
<P>二.递归与非递归转换的原理. <BR>递归与非递归的转换基于以下的原理:所有的递归程序都可以用树结构表示出来.需要说明的是, <BR>这个"原理"并没有经过严格的数学证明,只是我的一个猜想,不过在至少在我遇到的例子中是适用的. <BR>学习过树结构的人都知道,有三种方法可以遍历树:前序,中序,后序.理解这三种遍历方式的递归和非 <BR>递归的表达方式是能够正确实现转换的关键之处,所以我们先来谈谈这个.需要说明的是,这里以特殊的 <BR>二叉树来说明,不过大多数情况下二叉树已经够用,而且理解了二叉树的遍历,其它的树遍历方式就不难 <BR>了. <BR>1)前序遍历 <BR>a)递归方式: </P>
<P>void preorder_recursive(Bitree T)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 先序遍历二叉树的递归算法 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (T) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(T);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问当前结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preorder_recursive(T-&gt;;lchild);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问左子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preorder_recursive(T-&gt;;rchild);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问右子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;</P>
<P>b)非递归方式 </P>
<P>void preorder_nonrecursive(Bitree T)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 先序遍历二叉树的非递归算法 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initstack(S);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,T);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 根指针进栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(!stackempty(S)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(gettop(S,p)&amp;&amp;p) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 向左走到尽头 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(p);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 每向前走一步都访问当前结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,p-&gt;;lchild);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop(S,p);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!stackempty(S)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 向右走一步 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop(S,p);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,p-&gt;;rchild); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>2)中序遍历 </P>
<P>a)递归方式 </P>
<P>void inorder_recursive(Bitree T)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 中序遍历二叉树的递归算法 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (T) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inorder_recursive(T-&gt;;lchild); /* 访问左子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(T);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问当前结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inorder_recursive(T-&gt;;rchild); /* 访问右子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>b)非递归方式 </P>
<P>void&nbsp; inorder_nonrecursive(Bitree T)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initstack(S);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 初始化栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S, T);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 根指针入栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (!stackempty(S)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (gettop(S, p) &amp;&amp; p)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 向左走到尽头 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S, p-&gt;;lchild);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop(S,p);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 空指针退栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!stackempty(S)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop(S, p);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(p);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问当前结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S, p-&gt;;rchild);&nbsp;&nbsp; /* 向右走一步 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>3)后序遍历 </P>
<P>a)递归方式 </P>
<P>void postorder_recursive(Bitree T)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 中序遍历二叉树的递归算法 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (T) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; postorder_recursive(T-&gt;;lchild);&nbsp;&nbsp; /* 访问左子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; postorder_recursive(T-&gt;;rchild);&nbsp;&nbsp; /* 访问右子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(T);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问当前结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>b)非递归方式 </P>
<P>typedef struct {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BTNode* ptr;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum {0,1,2} mark;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } PMType;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 有mark域的结点指针类型 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void postorder_nonrecursive(BiTree T)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 后续遍历二叉树的非递归算法 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PMType a;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initstack(S);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* S的元素为PMType类型 */</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push (S,{T,0});&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 根结点入栈 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(!stackempty(S)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop(S,a);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch(a.mark)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,{a.ptr,1});&nbsp;&nbsp;&nbsp;&nbsp; /* 修改mark域 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(a.ptr-&gt;;lchild) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,{a.ptr-&gt;;lchild,0}); /* 访问左子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,{a.ptr,2});&nbsp;&nbsp;&nbsp;&nbsp; /* 修改mark域 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(a.ptr-&gt;;rchild) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push(S,{a.ptr-&gt;;rchild,0}); /* 访问右子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(a.ptr);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>4)如何实现递归与非递归的转换 <BR>通常,一个函数在调用另一个函数之前,要作如下的事情:a)将实在参数,返回地址等信息传递 <BR>给被调用函数保存; b)为被调用函数的局部变量分配存储区;c)将控制转移到被调函数的入口. <BR>从被调用函数返回调用函数之前,也要做三件事情:a)保存被调函数的计算结果;b)释放被调 <BR>函数的数据区;c)依照被调函数保存的返回地址将控制转移到调用函数. <BR>所有的这些,不论是变量还是地址,本质上来说都是"数据",都是保存在系统所分配的栈中的. <BR>ok,到这里已经解决了第一个问题:递归调用时数据都是保存在栈中的,有多少个数据需要保存 <BR>就要设置多少个栈,而且最重要的一点是:控制所有这些栈的栈顶指针都是相同的,否则无法实现 <BR>同步. <BR>下面来解决第二个问题:在非递归中,程序如何知道到底要转移到哪个部分继续执行?回到上 <BR>面说的树的三种遍历方式,抽象出来只有三种操作:访问当前结点,访问左子树,访问右子树.这三 <BR>种操作的顺序不同,遍历方式也不同.如果我们再抽象一点,对这三种操作再进行一个概括,可以 <BR>得到:a)访问当前结点:对目前的数据进行一些处理;b)访问左子树:变换当前的数据以进行下一次 <BR>处理;c)访问右子树:再次变换当前的数据以进行下一次处理(与访问左子树所不同的方式). <BR>下面以先序遍历来说明: </P>
<P>void preorder_recursive(Bitree T)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 先序遍历二叉树的递归算法 */</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (T) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visit(T);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问当前结点 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preorder_recursive(T-&gt;;lchild);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问左子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preorder_recursive(T-&gt;;rchild);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 访问右子树 */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P><BR>visit(T)这个操作就是对当前数据进行的处理, preorder_recursive(T-&gt;;lchild)就是把当前 <BR>数据变换为它的左子树,访问右子树的操作可以同样理解了. <BR>现在回到我们提出的第二个问题:如何确定转移到哪里继续执行?关键在于一下三个地方:a) <BR>确定对当前数据的访问顺序,简单一点说就是确定这个递归程序可以转换为哪种方式遍历的树结 <BR>构;b)确定这个递归函数转换为递归调用树时的分支是如何划分的,即确定什么是这个递归调用 <BR>树的"左子树"和"右子树"c)确定这个递归调用树何时返回,即确定什么结点是这个递归调用树的 <BR>"叶子结点". <BR></P>
<P>&nbsp;</P>]]></description>
</item><item>
<title><![CDATA[谈VC++对象模型( Good 转)]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33088</link>
<author>zc9706</author>
<pubDate>2008/3/28 19:41:36</pubDate>
<description><![CDATA[一个C++程序员，想要进一步提升技术水平的话，应该多了解一些语言的语意细节。对于使用VC++的程序员来说，还应该了解一些VC++对于C++的诠释。Inside the C++ Object Model虽然是一本好书，然而，书的篇幅多一些，又和具体的VC++关系小一些。因此，从篇幅和内容来看，译者认为本文是深入理解C++对象模型比较好的一个出发点。<BR><BR>　　这篇文章以前看到时就觉得很好，旧文重读，感觉理解得更多一些了，于是产生了翻译出来，与大家共享的想法。虽然文章不长，但时间有限，又若干次在翻译时打盹睡着，拖拖拉拉用了小一个月。<BR><BR>　　一方面因本人水平所限，另一方面因翻译时经常打盹，错误之处恐怕不少，欢迎大家批评指正。<BR><BR>　　<STRONG>前言</STRONG><BR><BR>　 　了解你所使用的编程语言究竟是如何实现的，对于C++程序员可能特别有意义。首先，它可以去除我们对于所使用语言的神秘感，使我们不至于对于编译器干的 活感到完全不可思议；尤其重要的是，它使我们在Debug和使用语言高级特性的时候，有更多的把握。当需要提高代码效率的时候，这些知识也能够很好地帮助 我们。<BR><BR>　　本文着重回答这样一些问题：<BR><BR>　　* 类如何布局？<BR><BR>　　* 成员变量如何访问？<BR><BR>　　* 成员函数如何访问？<BR><BR>　　* 所谓的“调整块”（adjuster thunk）是怎么回事？<BR><BR>　　* 使用如下机制时，开销如何：<BR><BR>　　* 单继承、多重继承、虚继承<BR><BR>　　* 虚函数调用<BR><BR>　　* 强制转换到基类，或者强制转换到虚基类<BR><BR>　　* 异常处理<BR><BR>　 　首先，我们顺次考察C兼容的结构（struct）的布局，单继承，多重继承，以及虚继承；接着，我们讲成员变量和成员函数的访问，当然，这里面包含虚函 数的情况；再接下来，我们考察构造函数，析构函数，以及特殊的赋值操作符成员函数是如何工作的，数组是如何动态构造和销毁的；最后，简单地介绍对异常处理 的支持。<BR><BR>　　对每个语言特性，我们将简要介绍该特性背后的动机，该特性自身的语意（当然，本文决不是“C++入门”，大家对此要有充分认 识），以及该特性在微软的VC++中是如何实现的。这里要注意区分抽象的C++语言语意与其特定实现。微软之外的其他C++厂商可能提供一个完全不同的实 现，我们偶尔也会将VC++的实现与其他实现进行比较。<BR><BR>　　<STRONG>类布局</STRONG><BR><BR>　　本节讨论不同的继承方式造成的不同内存布局。<BR><BR>　　1、C结构（struct）<BR><BR>　 　由于C++基于C，所以C++也“基本上”兼容C。特别地，C++规范在“结构”上使用了和C相同的，简单的内存布局原则：成员变量按其被声明的顺序排 列，按具体实现所规定的对齐原则在内存地址上对齐。所有的C/C++厂商都保证他们的C/C++编译器对于有效的C结构采用完全相同的布局。这里，A是一 个简单的C结构，其成员布局和对齐方式都一目了然。<BR><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C33BFC10740C.gif"><BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct A {<BR>&nbsp;&nbsp; char c;<BR>&nbsp;&nbsp; int i;<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：从上图可见，A在内存中占有8个字节，按照声明成员的顺序，前4个字节包含一个字符（实际占用1个字节，3个字节空着，补对齐），后4个字节包含一个整数。A的指针就指向字符开始字节处。<BR></FONT><FONT size=3><BR>　　2、有C++特征的C结构<BR><BR>　 　当然了，C++不是复杂的C，C++本质上是面向对象的语言：包含继承、封装，以及多态。原始的C结构经过改造，成了面向对象世界的基石——类。除了成 员变量外，C++类还可以封装成员函数和其他东西。然而，有趣的是，除非为了实现虚函数和虚继承引入的隐藏成员变量外，C++类实例的大小完全取决于一个 类及其基类的成员变量！成员函数基本上不影响类实例的大小。<BR><BR>　　这里提供的B是一个C结构，然而，该结构有一些C++特征：控制成员可见 性的“public/protected/private”关键字、成员函数、静态成员，以及嵌套的类型声明。虽然看着琳琅满目，实际上只有成员变量才占 用类实例的空间。要注意的是，C++标准委员会不限制由“public/protected/private”关键字分开的各段在实现时的先后顺序，因 此，不同的编译器实现的内存布局可能并不相同。（在VC++中，成员变量总是按照声明时的顺序排列）。<BR><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C33BFC2386EC.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct B {<BR>public:<BR>&nbsp;&nbsp; int bm1;<BR>protected:<BR>&nbsp;&nbsp; int bm2;<BR>private:<BR>&nbsp;&nbsp; int bm3;<BR>&nbsp;&nbsp; static int bsm;<BR>&nbsp;&nbsp; void bf();<BR>&nbsp;&nbsp; static void bsf();<BR>&nbsp;&nbsp; typedef void* bpv;<BR>&nbsp;&nbsp; struct N { };<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：B中，为何static int bsm不占用内存空间？因为它是静态成员，该数据存放在程序的数据段中，不在类实例中。<BR></FONT><FONT size=3><BR>　　3、单继承<BR><BR>　 　C++提供继承的目的是在不同的类型之间提取共性。比如，科学家对物种进行分类，从而有种、属、纲等说法。有了这种层次结构，我们才可能将某些具备特定 性质的东西归入到最合适的分类层次上，如“怀孩子的是哺乳动物”。由于这些属性可以被子类继承，所以，我们只要知道“鲸鱼、人”是哺乳动物，就可以方便地 指出“鲸鱼、人都可以怀孩子”。那些特例，如鸭嘴兽（生蛋的哺乳动物），则要求我们对缺省的属性或行为进行覆盖。<BR><BR>　　C++中的继承语法很简单，在子类后加上“:base”就可以了。下面的D继承自基类C。<BR><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C33BFC343770.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct C {<BR>&nbsp;&nbsp; int c1;<BR>&nbsp;&nbsp; void cf();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C33BFC44E7F4.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct D : C {<BR>&nbsp;&nbsp; int d1;<BR>&nbsp;&nbsp; void df();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>　 　既然派生类要保留基类的所有属性和行为，自然地，每个派生类的实例都包含了一份完整的基类实例数据。在D中，并不是说基类C的数据一定要放在D的数据之 前，只不过这样放的话，能够保证D中的C对象地址，恰好是D对象地址的第一个字节。这种安排之下，有了派生类D的指针，要获得基类C的指针，就不必要计算 偏移量了。几乎所有知名的C++厂商都采用这种内存安排。在单继承类层次下，每一个新的派生类都简单地把自己的成员变量添加到基类的成员变量之后。看看上 图，C对象指针和D对象指针指向同一地址。<BR><BR>4、多重继承<BR><BR>　　大多数情况下，其实单继承就足够了。但是，C++为了我们的方便，还提供了多重继承。<BR><BR>　　比如，我们有 一个组织模型，其中有经理类（分任务），工人类（干活）。那么，对于一线经理类，即既要从上级经理那里领取任务干活，又要向下级工人分任务的角色来说，如 何在类层次中表达呢？单继承在此就有点力不胜任。我们可以安排经理类先继承工人类，一线经理类再继承经理类，但这种层次结构错误地让经理类继承了工人类的 属性和行为。反之亦然。当然，一线经理类也可以仅仅从一个类（经理类或工人类）继承，或者一个都不继承，重新声明一个或两个接口，但这样的实现弊处太多： 多态不可能了；未能重用现有的接口；最严重的是，当接口变化时，必须多处维护。最合理的情况似乎是一线经理从两个地方继承属性和行为——经理类、工人类。<BR><BR>　　C++就允许用多重继承来解决这样的问题：<BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct Manager ... { ... };<BR>struct Worker ... { ... };<BR>struct MiddleManager : Manager, Worker { ... };</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>　　这样的继承将造成怎样的类布局呢？下面我们还是用“字母类”来举例：<BR><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41573647FB4.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct E {<BR>&nbsp;&nbsp; int e1;<BR>&nbsp;&nbsp; void ef();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C415737C571A.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct F : C, E {<BR>&nbsp;&nbsp; int f1;<BR>&nbsp;&nbsp; void ff();<BR>&nbsp; <BR>&nbsp;};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>　　结构F从C和E多重继承得来。与单继承相同的是，F实例拷贝了每个基类的所有数据。与单继承不同的是，在多重继承下，内嵌的两个基类的对象指针不可能全都与派生类对象指针相同：<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>F f;<BR>// (void*)&amp;f == (void*)(C*)&amp;f;<BR>// (void*)&amp;f &lt;&nbsp; (void*)(E*)&amp;f;</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：上面那行说明C对象指针与F对象指针相同，下面那行说明E对象指针与F对象指针不同。</FONT><FONT size=3><BR><BR>　　观察类布局，可以看到F中内嵌的E对象，其指针与F指针并不相同。正如后文讨论强制转化和成员函数时指出的，这个偏移量会造成少量的调用开销。<BR><BR>　 　具体的编译器实现可以自由地选择内嵌基类和派生类的布局。VC++按照基类的声明顺序先排列基类实例数据，最后才排列派生类数据。当然，派生类数据本身 也是按照声明顺序布局的（本规则并非一成不变，我们会看到，当一些基类有虚函数而另一些基类没有时，内存布局并非如此）。<BR><BR>　　5、虚继承<BR><BR>　　回到我们讨论的一线经理类例子。让我们考虑这种情况：如果经理类和工人类都继承自“雇员类”，将会发生什么？<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct Employee { ... };<BR>struct Manager : Employee { ... };<BR>struct Worker : Employee { ... };<BR>struct MiddleManager : Manager, Worker { ... };</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　如果经理类和工人类都继承自雇员类，很自然地，它们每个类都会从雇员类获得一份数据拷贝。如果不作特殊处理，一线经理类的实例将含有两个雇员类实例， 它们分别来自两个雇员基类。如果雇员类成员变量不多，问题不严重；如果成员变量众多，则那份多余的拷贝将造成实例生成时的严重开销。更糟的是，这两份不同 的雇员实例可能分别被修改，造成数据的不一致。因此，我们需要让经理类和工人类进行特殊的声明，说明它们愿意共享一份雇员基类实例数据。<BR><BR>　　很不幸，在C++中，这种“共享继承”被称为“虚继承”，把问题搞得似乎很抽象。虚继承的语法很简单，在指定基类时加上virtual关键字即可。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct Employee { ... };<BR>struct Manager : virtual Employee { ... };<BR>struct Worker : virtual Employee { ... };<BR>struct MiddleManager : Manager, Worker { ... };</FONT></TD></TR></TBODY></TABLE><FONT size=3>&nbsp; <BR>　 　使用虚继承，比起单继承和多重继承有更大的实现开销、调用开销。回忆一下，在单继承和多重继承的情况下，内嵌的基类实例地址比起派生类实例地址来，要么 地址相同（单继承，以及多重继承的最靠左基类），要么地址相差一个固定偏移量（多重继承的非最靠左基类）。然而，当虚继承时，一般说来，派生类地址和其虚 基类地址之间的偏移量是不固定的，因为如果这个派生类又被进一步继承的话，最终派生类会把共享的虚基类实例数据放到一个与上一层派生类不同的偏移量处。请 看下例：<BR><BR>&nbsp; <IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C415739B5585.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct G : virtual C {<BR>&nbsp;&nbsp; int g1;<BR>&nbsp;&nbsp; void gf();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3>&nbsp; <BR></FONT><FONT color=#0000ff size=3>　 　译者注：GdGvbptrG（In G, the displacement of G’s virtual base pointer to G）意思是：在G中，G对象的指针与G的虚基类表指针之间的偏移量，在此可见为0，因为G对象内存布局第一项就是虚基类表指针； GdGvbptrC（In G, the displacement of G’s virtual base pointer to C）意思是：在G中，C对象的指针与G的虚基类表指针之间的偏移量，在此可见为4。</FONT><FONT size=3><BR><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41573B0CA94.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct H : virtual C {<BR>&nbsp;&nbsp; int h1;<BR>&nbsp;&nbsp; void hf();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41573CFC8FF.gif">&nbsp; <BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct I : G, H {<BR>&nbsp;&nbsp; int i1;<BR>&nbsp;&nbsp; void _if();<BR>}; </FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　暂时不追究vbptr成员变量从何而来。从上面这些图可以直观地看到，在G对象中，内嵌的C基类对象的数据紧跟在G的数据之后，在H对象中，内嵌的C 基类对象的数据也紧跟在H的数据之后。但是，在I对象中，内存布局就并非如此了。VC++实现的内存布局中，G对象实例中G对象和C对象之间的偏移，不同 于I对象实例中G对象和C对象之间的偏移。当使用指针访问虚基类成员变量时，由于指针可以是指向派生类实例的基类指针，所以，编译器不能根据声明的指针类 型计算偏移，而必须找到另一种间接的方法，从派生类指针计算虚基类的位置。<BR><BR>　　在VC++中，对每个继承自虚基类的类实例，将增加一个隐藏的“虚基类表指针”（vbptr）成员变量，从而达到间接计算虚基类位置的目的。该变量指向一个全类共享的偏移量表，表中项目记录了对于该类而言，“虚基类表指针”与虚基类之间的偏移量。<BR><BR>　 　其它的实现方式中，有一种是在派生类中使用指针成员变量。这些指针成员变量指向派生类的虚基类，每个虚基类一个指针。这种方式的优点是：获取虚基类地址 时，所用代码比较少。然而，编译器优化代码时通常都可以采取措施避免重复计算虚基类地址。况且，这种实现方式还有一个大弊端：从多个虚基类派生时，类实例 将占用更多的内存空间；获取虚基类的虚基类的地址时，需要多次使用指针，从而效率较低等等。<BR><BR>　　在VC++中，G拥有一个隐藏的“虚基类 表指针”成员，指向一个虚基类表，该表的第二项是GdGvbptrC。（在G中，虚基类对象C的地址与G的“虚基类表指针”之间的偏移量（当对于所有的派 生类来说偏移量不变时，省略“d”前的前缀））。比如，在32位平台上，GdGvptrC是8个字节。同样，在I实例中的G对象实例也有“虚基类表指 针”，不过该指针指向一个适用于“G处于I之中”的虚基类表，表中一项为IdGvbptrC，值为20。<BR><BR>　　观察前面的G、H和I，我们可以得到如下关于VC++虚继承下内存布局的结论：<BR><BR>　　·首先排列非虚继承的基类实例；<BR><BR>　　·有虚基类时，为每个基类增加一个隐藏的vbptr，除非已经从非虚继承的类那里继承了一个vbptr；<BR><BR>　　·排列派生类的新数据成员；<BR><BR>　　·在实例最后，排列每个虚基类的一个实例。<BR><BR>　　该布局安排使得虚基类的位置随着派生类的不同而“浮动不定”，但是，非虚基类因此也就凑在一起，彼此的偏移量固定不变。<BR><BR><STRONG>成员变量</STRONG><BR><BR>　　介绍了类布局之后，我们接着考虑对不同的继承方式，访问成员变量的开销究竟如何。<BR><BR>　　没有继承。没有任何继承关系时，访问成员变量和C语言的情况完全一样：从指向对象的指针，考虑一定的偏移量即可。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>C* pc;<BR>pc-&gt;c1; // *(pc + dCc1);</FONT></TD></TR></TBODY></TABLE><FONT color=#0000ff size=3><BR>　　译者注：pc是指向C的指针。<BR><BR>　　· 访问C的成员变量c1，只需要在pc上加上固定的偏移量dCc1（在C中，C指针地址与其c1成员变量之间的偏移量值），再获取该指针的内容即可。</FONT><FONT size=3><BR><BR>　　单继承。由于派生类实例与其基类实例之间的偏移量是常数0，所以，可以直接利用基类指针和基类成员之间的偏移量关系，如此计算得以简化。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>D* pd;<BR>pd-&gt;c1; // *(pd + dDC + dCc1); // *(pd + dDc1);<BR>pd-&gt;d1; // *(pd + dDd1);</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：D从C单继承，pd为指向D的指针。<BR><BR>　　·当访问基类成员c1时，计算步骤本来应该为“pd+dDC+dCc1”，即为先计算D对象和C对象之间的偏移，再在此基础上加上C对象指针与成员变量c1之间的偏移量。然而，由于dDC恒定为0，所以直接计算C对象地址与c1之间的偏移就可以了。<BR><BR>　　·当访问派生类成员d1时，直接计算偏移量。</FONT><FONT size=3><BR><BR>　　多重继承。虽然派生类与某个基类之间的偏移量可能不为0，然而，该偏移量总是一个常数。只要是个常数，访问成员变量，计算成员变量偏移时的计算就可以被简化。可见即使对于多重继承来说，访问成员变量开销仍然不大。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>F* pf;<BR>pf-&gt;c1; // *(pf + dFC + dCc1); // *(pf + dFc1);<BR>pf-&gt;e1; // *(pf + dFE + dEe1); // *(pf + dFe1);<BR>pf-&gt;f1; // *(pf + dFf1);</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：F继承自C和E，pf是指向F对象的指针。<BR><BR>　　·访问C类成员c1时，F对象与内嵌C对象的相对偏移为0，可以直接计算F和c1的偏移；<BR><BR>　　·访问E类成员e1时，F对象与内嵌E对象的相对偏移是一个常数，F和e1之间的偏移计算也可以被简化；<BR><BR>　　·访问F自己的成员f1时，直接计算偏移量。</FONT><FONT size=3><BR><BR>　 　虚继承。当类有虚基类时，访问非虚基类的成员仍然是计算固定偏移量的问题。然而，访问虚基类的成员变量，开销就增大了，因为必须经过如下步骤才能获得成 员变量的地址：获取“虚基类表指针”；获取虚基类表中某一表项的内容；把内容中指出的偏移量加到“虚基类表指针”的地址上。然而，事情并非永远如此。正如 下面访问I对象的c1成员那样，如果不是通过指针访问，而是直接通过对象实例，则派生类的布局可以在编译期间静态获得，偏移量也可以在编译时计算，因此也 就不必要根据虚基类表的表项来间接计算了。<BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>I* pi;<BR>pi-&gt;c1; // *(pi + dIGvbptr + (*(pi+dIGvbptr))[1] + dCc1);<BR>pi-&gt;g1; // *(pi + dIG + dGg1); // *(pi + dIg1);<BR>pi-&gt;h1; // *(pi + dIH + dHh1); // *(pi + dIh1);<BR>pi-&gt;i1; // *(pi + dIi1);<BR>I i;<BR>i.c1; // *(&amp;i + IdIC + dCc1); // *(&amp;i + IdIc1);</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：I继承自G和H，G和H的虚基类是C，pi是指向I对象的指针。<BR><BR>　 　·访问虚基类C的成员c1时，dIGvbptr是“在I中，I对象指针与G的“虚基类表指针”之间的偏移”，*(pi + dIGvbptr)是虚基类表的开始地址，*(pi + dIGvbptr)[1]是虚基类表的第二项的内容（在I对象中，G对象的“虚基类表指针”与虚基类之间的偏移），dCc1是C对象指针与成员变量c1之 间的偏移；<BR><BR>　　·访问非虚基类G的成员g1时，直接计算偏移量；<BR><BR>　　·访问非虚基类H的成员h1时，直接计算偏移量；<BR><BR>　　·访问自身成员i1时，直接使用偏移量；<BR><BR>　　·当声明了一个对象实例，用点“.”操作符访问虚基类成员c1时，由于编译时就完全知道对象的布局情况，所以可以直接计算偏移量</FONT><FONT size=3>。<BR><BR>　 　当访问类继承层次中，多层虚基类的成员变量时，情况又如何呢？比如，访问虚基类的虚基类的成员变量时？一些实现方式为：保存一个指向直接虚基类的指针， 然后就可以从直接虚基类找到它的虚基类，逐级上推。VC++优化了这个过程。VC++在虚基类表中增加了一些额外的项，这些项保存了从派生类到其各层虚基 类的偏移量。<BR><BR>　　<STRONG>强制转化</STRONG><BR><BR>　　如果没有虚基类的问题，将一个指针强制转化为另一个类型的指针代价并不高昂。如果在要求转化的两个指针之间有“基类-派生类”关系，编译器只需要简单地在两者之间加上或者减去一个偏移量即可（并且该量还往往为0）。<BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>F* pf;<BR>(C*)pf; // (C*)(pf ? pf + dFC : 0); // (C*)pf;<BR>(E*)pf; // (E*)(pf ? pf + dFE : 0);</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>　 　C和E是F的基类，将F的指针pf转化为C*或E*，只需要将pf加上一个相应的偏移量。转化为C类型指针C*时，不需要计算，因为F和C之间的偏移量 为0。转化为E类型指针E*时，必须在指针上加一个非0的偏移常量dFE。C++规范要求NULL指针在强制转化后依然为NULL，因此在做强制转化需要 的运算之前，VC++会检查指针是否为NULL。当然，这个检查只有当指针被显示或者隐式转化为相关类型指针时才进行；当在派生类对象中调用基类的方法， 从而派生类指针被在后台转化为一个基类的Const “this” 指针时，这个检查就不需要进行了，因为在此时，该指针一定不为NULL。<BR><BR>　　正如你猜想的，当继承关系中存在虚基类时，强制转化的开销会比较大。具体说来，和访问虚基类成员变量的开销相当。<BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>I* pi;<BR>(G*)pi; // (G*)pi;<BR>(H*)pi; // (H*)(pi ? pi + dIH : 0);<BR>(C*)pi; // (C*)(pi ? (pi+dIGvbptr + (*(pi+dIGvbptr))[1]) : 0);</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：pi是指向I对象的指针，G,H是I的基类，C是G,H的虚基类。<BR><BR>　　·强制转化pi为G*时，由于G*和I*的地址相同，不需要计算；<BR><BR>　　·强制转化pi为H*时，只需要考虑一个常量偏移；<BR><BR>　　·强制转化pi为C*时，所作的计算和访问虚基类成员变量的开销相同，首先得到G的虚基类表指针，再从虚基类表的第二项中取出G到虚基类C的偏移量，最后根据pi、虚基类表偏移和虚基类C与虚基类表指针之间的偏移计算出C*。</FONT><FONT size=3><BR><BR>　　一般说来，当从派生类中访问虚基类成员时，应该先强制转化派生类指针为虚基类指针，然后一直使用虚基类指针来访问虚基类成员变量。这样做，可以避免每次都要计算虚基类地址的开销。见下例。<BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>/* before: */&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... pi-&gt;c1 ... pi-&gt;c1 ...<BR>/* faster: */ C* pc = pi; ... pc-&gt;c1 ... pc-&gt;c1 ...</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：前者一直使用派生类指针pi，故每次访问c1都有计算虚基类地址的较大开销；后者先将pi转化为虚基类指针pc，故后续调用可以省去计算虚基类地址的开销。<BR><BR></FONT><FONT size=3><STRONG>成员函数</STRONG><BR><BR>　　一个C++成员函数只是类范围内的又一个成员。X类每一个非静态的成员函数都会接受一个特殊的隐藏参数—— this指针，类型为X* const。该指针在后台初始化为指向成员函数工作于其上的对象。同样，在成员函数体内，成员变量的访问是通过在后台计算与this指针的偏移来进行。<BR><BR>&nbsp;<IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41572ED4AB6.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct P {<BR>&nbsp;&nbsp; int p1;<BR>&nbsp;&nbsp; void pf(); // new<BR>&nbsp;&nbsp; virtual void pvf(); // new<BR>&nbsp; <BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　P有一个非虚成员函数pf()，以及一个虚成员函数pvf()。很明显，虚成员函数造成对象实例占用更多内存空间，因为虚成员函数需要虚函数表指针。 这一点以后还会谈到。这里要特别指出的是，声明非虚成员函数不会造成任何对象实例的内存开销。现在，考虑P::pf()的定义。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>void P::pf() { // void P::pf([P *const this])<BR>&nbsp;&nbsp; ++p1;&nbsp;&nbsp; // ++(this-&gt;p1);<BR>}</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>　 　这里P:pf()接受了一个隐藏的this指针参数，对于每个成员函数调用，编译器都会自动加上这个参数。同时，注意成员变量访问也许比看起来要代价高 昂一些，因为成员变量访问通过this指针进行，在有的继承层次下，this指针需要调整，所以访问的开销可能会比较大。然而，从另一方面来说，编译器通 常会把this指针缓存到寄存器中，所以，成员变量访问的代价不会比访问局部变量的效率更差。<BR><BR>　　</FONT><FONT color=#0000ff size=3>译者注：访问局部变量，需要到SP寄存器中得到栈指针，再加上局部变量与栈顶的偏移。在没有虚基类的情况下，如果编译器把this指针缓存到了寄存器中，访问成员变量的过程将与访问局部变量的开销相似。</FONT><FONT size=3><BR><BR>　　1、覆盖成员函数<BR><BR>　 　和成员变量一样，成员函数也会被继承。与成员变量不同的是，通过在派生类中重新定义基类函数，一个派生类可以覆盖，或者说替换掉基类的函数定义。覆盖是 静态（根据成员函数的静态类型在编译时决定）还是动态（通过对象指针在运行时动态决定），依赖于成员函数是否被声明为“虚函数”。<BR><BR>　　Q从P继承了成员变量和成员函数。Q声明了pf()，覆盖了P::pf()。Q还声明了pvf()，覆盖了P::pvf()虚函数。Q还声明了新的非虚成员函数qf()，以及新的虚成员函数qvf()。<BR><BR><IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41573078473.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct Q : P {<BR>&nbsp;&nbsp; int q1;<BR>&nbsp;&nbsp; void pf();&nbsp; // overrides P::pf<BR>&nbsp;&nbsp; void qf();&nbsp; // new<BR>&nbsp;&nbsp; void pvf(); // overrides P::pvf<BR>&nbsp;&nbsp; virtual void qvf(); // new<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3>&nbsp; <BR>　 　对于非虚的成员函数来说，调用哪个成员函数是在编译时，根据“-&gt;”操作符左边指针表达式的类型静态决定的。特别地，即使ppq指向Q的实例， ppq-&gt;pf()仍然调用的是P::pf()，因为ppq被声明为“P*”。（注意，“-&gt;”操作符左边的指针类型决定隐藏的this参数 的类型。）<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>P p; P* pp = &amp;p; Q q; P* ppq = &amp;q; Q* pq = &amp;q;<BR>pp-&gt;pf();&nbsp; // pp-&gt;P::pf();&nbsp; // P::pf(pp);<BR>ppq-&gt;pf(); // ppq-&gt;P::pf(); // P::pf(ppq);<BR>pq-&gt;pf();&nbsp; // pq-&gt;Q::pf();&nbsp; // Q::pf((P*)pq); （错误!）<BR>pq-&gt;qf();&nbsp; // pq-&gt;Q::qf();&nbsp; // Q::qf(pq);</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：标记“错误”处，P*似应为Q*。因为pf非虚函数，而pq的类型为Q*，故应该调用到Q的pf函数上，从而该函数应该要求一个Q* const类型的this指针。</FONT><FONT size=3><BR><BR>　　对于虚函数调用来说，调用哪个成员函数在运行时决定。不管“-&gt;”操作符左边的指针表达式的类型如何，调用的虚函数都是由指针实际指向的实例类型所决定。比如，尽管ppq的类型是P*，当ppq指向Q的实例时，调用的仍然是Q::pvf()。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>pp-&gt;pvf();&nbsp; // pp-&gt;P::pvf();&nbsp; // P::pvf(pp);<BR>ppq-&gt;pvf(); // ppq-&gt;Q::pvf(); // Q::pvf((Q*)ppq);<BR>pq-&gt;pvf();&nbsp; // pq-&gt;Q::pvf();&nbsp; // Q::pvf((P*)pq); （错误！）</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：标记“错误”处，P*似应为Q*。因为pvf是虚函数，pq本来就是Q*，又指向Q的实例，从哪个方面来看都不应该是P*。</FONT><FONT size=3><BR><BR>　 　为了实现这种机制，引入了隐藏的vfptr成员变量。一个vfptr被加入到类中（如果类中没有的话），该vfptr指向类的虚函数表 （vftable）。类中每个虚函数在该类的虚函数表中都占据一项。每项保存一个对于该类适用的虚函数的地址。因此，调用虚函数的过程如下：取得实例的 vfptr；通过vfptr得到虚函数表的一项；通过虚函数表该项的函数地址间接调用虚函数。也就是说，在普通函数调用的参数传递、调用、返回指令开销 外，虚函数调用还需要额外的开销。<BR><BR>　　回头再看看P和Q的内存布局，可以发现，VC++编译器把隐藏的vfptr成员变量放在P和Q实例 的开始处。这就使虚函数的调用能够尽量快一些。实际上，VC++的实现方式是，保证任何有虚函数的类的第一项永远是vfptr。这就可能要求在实例布局 时，在基类前插入新的vfptr，或者要求在多重继承时，虽然在右边，然而有vfptr的基类放到左边没有vfptr的基类的前面。<BR><BR>　　 许多C++的实现会共享或者重用从基类继承来的vfptr。比如，Q并不会有一个额外的vfptr，指向一个专门存放新的虚函数qvf()的虚函数表。 Qvf项只是简单地追加到P的虚函数表的末尾。如此一来，单继承的代价就不算高昂。一旦一个实例有vfptr了，它就不需要更多的vfptr。新的派生类 可以引入更多的虚函数，这些新的虚函数只是简单地在已存在的，“每类一个”的虚函数表的末尾追加新项。<BR><BR>　　2、多重继承下的虚函数<BR><BR>　　如果从多个有虚函数的基类继承，一个实例就有可能包含多个vfptr。考虑如下的R和S类：<BR><BR>&nbsp; <IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C4157340BC9B.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct R {<BR>&nbsp;&nbsp; int r1;<BR>&nbsp;&nbsp; virtual void pvf(); // new<BR>&nbsp;&nbsp; virtual void rvf(); // new<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; <IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41573516CFC.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct S : P, R {<BR>&nbsp;&nbsp; int s1;<BR>&nbsp;&nbsp; void pvf(); // overrides P::pvf and R::pvf<BR>&nbsp;&nbsp; void rvf(); // overrides R::rvf<BR>&nbsp;&nbsp; void svf(); // new<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　这里R是另一个包含虚函数的类。因为S从P和R多重继承，S的实例内嵌P和R的实例，以及S自身的数据成员S::s1。注意，在多重继承下，靠右的基 类R，其实例的地址和P与S不同。S::pvf覆盖了P::pvf()和R::pvf()，S::rvf()覆盖了R::rvf()。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>S s; S* ps = &amp;s;<BR>((P*)ps)-&gt;pvf(); // (*(P*)ps)-&gt;P::vfptr[0])((S*)(P*)ps)<BR>((R*)ps)-&gt;pvf(); // (*(R*)ps)-&gt;R::vfptr[0])((S*)(R*)ps)<BR>ps-&gt;pvf();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // one of the above; calls S::pvf()</FONT></TD></TR></TBODY></TABLE><FONT color=#0000ff size=3><BR>　　译者注：<BR><BR>　　·调用((P*)ps)-&gt;pvf()时，先到P的虚函数表中取出第一项，然后把ps转化为S*作为this指针传递进去；<BR><BR>　　·调用((R*)ps)-&gt;pvf()时，先到R的虚函数表中取出第一项，然后把ps转化为S*作为this指针传递进去；</FONT><FONT size=3><BR><BR>　 　因为S::pvf()覆盖了P::pvf()和R::pvf()，在S的虚函数表中，相应的项也应该被覆盖。然而，我们很快注意到，不光可以用P*，还 可以用R*来调用pvf()。问题出现了：R的地址与P和S的地址不同。表达式(R*)ps与表达式(P*)ps指向类布局中不同的位置。因为函数S:: pvf希望获得一个S*作为隐藏的this指针参数，虚函数必须把R*转化为S*。因此，在S对R虚函数表的拷贝中，pvf函数对应的项，指向的是一个 “调整块”的地址，该调整块使用必要的计算，把R*转换为需要的S*。<BR></FONT><FONT color=#0000ff size=3><BR>　　译者注：这就是“thunk1: this-= sdPR; goto S::pvf”干的事。先根据P和R在S中的偏移，调整this为P*，也就是S*，然后跳转到相应的虚函数处执行。</FONT><FONT size=3><BR><BR>　　在微软VC++实现中，对于有虚函数的多重继承，只有当派生类虚函数覆盖了多个基类的虚函数时，才使用调整块。<BR><BR>3、地址点与“逻辑this调整”<BR><BR>　　考虑下一个虚函数S::rvf()，该函数覆盖了R::rvf()。我们都知道S::rvf()必须有一个隐藏的S*类型的this参数。但是，因为也可以用R*来调用rvf()，也就是说，R的rvf虚函数槽可能以如下方式被用到：<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>((R*)ps)-&gt;rvf(); // (*((R*)ps)-&gt;R::vfptr[1])((R*)ps)</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　所以，大多数实现用另一个调整块将传递给rvf的R*转换为S*。还有一些实现在S的虚函数表末尾添加一个特别的虚函数项，该虚函数项提供方法，从而 可以直接调用ps-&gt;rvf()，而不用先转换R*。MSC++的实现不是这样，MSC++有意将S::rvf编译为接受一个指向S中嵌套的R实 例，而非指向S实例的指针（我们称这种行为是“给派生类的指针类型与该虚函数第一次被引入时接受的指针类型相同”）。所有这些在后台透明发生，对成员变量 的存取，成员函数的this指针，都进行“逻辑this调整”。<BR><BR>　　当然，在debugger中，必须对这种this调整进行补偿。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>ps-&gt;rvf(); // ((R*)ps)-&gt;rvf(); // S::rvf((R*)ps)</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：调用rvf虚函数时，直接给入R*作为this指针。</FONT><FONT size=3><BR><BR>　　所以，当覆盖非最左边的基类的虚函数时，MSC++一般不创建调整块，也不增加额外的虚函数项。<BR><BR>　　4、调整块<BR><BR>　 　正如已经描述的，有时需要调整块来调整this指针的值（this指针通常位于栈上返回地址之下，或者在寄存器中），在this指针上加或减去一个常量 偏移，再调用虚函数。某些实现（尤其是基于cfront的）并不使用调整块机制。它们在每个虚函数表项中增加额外的偏移数据。每当虚函数被调用时，该偏移 数据（通常为0）,被加到对象的地址上，然后对象的地址再作为this指针传入。<BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>ps-&gt;rvf();<BR>// struct { void (*pfn)(void*); size_t disp; };<BR>// (*ps-&gt;vfptr[i].pfn)(ps + ps-&gt;vfptr[i].disp);</FONT></TD></TR></TBODY></TABLE><FONT color=#0000ff size=3><BR>　　译者注：当调用rvf虚函数时，前一句表示虚函数表每一项是一个结构，结构中包含偏移量；后一句表示调用第i个虚函数时，this指针使用保存在虚函数表中第i项的偏移量来进行调整。</FONT><FONT size=3><BR><BR>　　这种方法的缺点是虚函数表增大了，虚函数的调用也更加复杂。<BR><BR>　　现代基于PC的实现一般采用“调整—跳转”技术：<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>S::pvf-adjust: // MSC++<BR>this -= SdPR;<BR>goto S::pvf()</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　当然，下面的代码序列更好（然而，当前没有任何实现采用该方法）：<BR>&nbsp;<BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>S::pvf-adjust:<BR>this -= SdPR; // fall into S::pvf()<BR>S::pvf() { ... }</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：IBM的C++编译器使用该方法。<BR></FONT><FONT size=3><BR>　　5、虚继承下的虚函数<BR><BR>　 　T虚继承P，覆盖P的虚成员函数，声明了新的虚函数。如果采用在基类虚函数表末尾添加新项的方式，则访问虚函数总要求访问虚基类。在VC++中，为了避 免获取虚函数表时，转换到虚基类P的高昂代价，T中的新虚函数通过一个新的虚函数表获取，从而带来了一个新的虚函数表指针。该指针放在T实例的顶端。<BR><BR>&nbsp;<IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41572A0FFD6.gif"> <BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct T : virtual P {<BR>&nbsp;&nbsp; int t1;<BR>&nbsp;&nbsp; void pvf();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // overrides P::pvf<BR>&nbsp;&nbsp; virtual void tvf(); // new<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; </FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>void T::pvf() {<BR>&nbsp;&nbsp; ++p1; // ((P*)this)-&gt;p1++; // vbtable lookup!<BR>&nbsp;&nbsp; ++t1; // this-&gt;t1++;<BR>}</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　如上所示，即使是在虚函数中，访问虚基类的成员变量也要通过获取虚基类表的偏移，实行计算来进行。这样做之所以必要，是因为虚函数可能被进一步继承的类所覆盖，而进一步继承的类的布局中，虚基类的位置变化了。下面就是这样的一个类：<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct U : T {<BR>&nbsp;&nbsp; int u1;<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　在此U增加了一个成员变量，从而改变了P的偏移。因为VC++实现中，T::pvf()接受的是嵌套在T中的P的指针，所以，需要提供一个调整块，把this指针调整到T::t1之后（该处即是P在T中的位置）。<BR><BR>　　6、特殊成员函数<BR><BR>　　本节讨论编译器合成到特殊成员函数中的隐藏代码。<BR><BR>　　6.1 构造函数和析构函数<BR><BR>　　正如我们所见，在构造和析构过程中，有时需要初始化一些隐藏的成员变量。最坏的情况下，一个构造函数要执行如下操作：<BR><BR>　　* 如果是“最终派生类”，初始化vbptr成员变量，调用虚基类的构造函数；<BR><BR>　　* 调用非虚基类的构造函数<BR><BR>　　* 调用成员变量的构造函数<BR><BR>　　* 初始化虚函数表成员变量<BR><BR>　　* 执行构造函数体中，程序所定义的其他初始化代码<BR><BR>　　（注意：一个“最终派生类”的实例，一定不是嵌套在其他派生类实例中的基类实例）<BR><BR>　　所以，如果你有一个包含虚函数的很深的继承层次，即使该继承层次由单继承构成，对象的构造可能也需要很多针对虚函数表的初始化。<BR><BR>　　反之，析构函数必须按照与构造时严格相反的顺序来“肢解”一个对象。<BR><BR>　　* 合成并初始化虚函数表成员变量<BR><BR>　　* 执行析构函数体中，程序定义的其他析构代码<BR>　 <BR>　　* 调用成员变量的析构函数（按照相反的顺序）<BR><BR>　　* 调用直接非虚基类的析构函数（按照相反的顺序）<BR><BR>　　* 如果是“最终派生类”，调用虚基类的析构函数（按照相反顺序）<BR><BR>　 　在VC++中，有虚基类的类的构造函数接受一个隐藏的“最终派生类标志”，标示虚基类是否需要初始化。对于析构函数，VC++采用“分层析构模型”，代 码中加入一个隐藏的析构函数，该函数被用于析构包含虚基类的类（对于“最终派生类”实例而言）；代码中再加入另一个析构函数，析构不包含虚基类的类。前一 个析构函数调用后一个。<BR><BR>　　6.2 虚析构函数与delete操作符<BR><BR>　　考虑结构V和W。<BR><BR>&nbsp; <IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41572B8D73C.gif"><BR><BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct V {<BR>&nbsp;&nbsp; virtual ~V();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; <IMG alt="" src="http://images.itdb.cn/News/2006/02/28/8C8C41572D0AEA2.gif"><BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct W : V {<BR>&nbsp;&nbsp; operator delete();<BR>};</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR>&nbsp; 　　析构函数可以为虚。一个类如果有虚析构函数的话，将会象有其他虚函数一样，拥有一个虚函数表指针，虚函数表中包含一项，其内容为指向对该类适用的虚析 构函数的地址。这些机制和普通虚函数相同。虚析构函数的特别之处在于：当类实例被销毁时，虚析构函数被隐含地调用。调用地（delete发生的地方）虽然 不知道销毁的动态类型，然而，要保证调用对该类型合适的delete操作符。例如，当pv指向W的实例时，当W::~W被调用之后，W实例将由W类的 delete操作符来销毁。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>V* pv = new V;<BR>delete pv;&nbsp;&nbsp; // pv-&gt;~V::V(); // use ::operator delete()<BR>pv = new W;<BR>delete pv;&nbsp;&nbsp; // pv-&gt;~W::W(); // use W::operator delete()<BR>pv = new W;<BR>::delete pv; // pv-&gt;~W::W(); // use ::operator delete()</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：<BR><BR>　　·V没有定义delete操作符，delete时使用函数库的delete操作符；<BR><BR>　　·W定义了delete操作符，delete时使用自己的delete操作符；<BR><BR>　　·可以用全局范围标示符显示地调用函数库的delete操作符。</FONT><FONT size=3><BR><BR>　 　为了实现上述语意，VC++扩展了其“分层析构模型”，从而自动创建另一个隐藏的析构帮助函数——“deleting析构函数”，然后，用该函数的地址 来替换虚函数表中“实际”虚析构函数的地址。析构帮助函数调用对该类合适的析构函数，然后为该类有选择性地调用合适的delete操作符。<BR><BR><STRONG>数组</STRONG><BR><BR>　　堆上分配空间的数组使虚析构函数进一步复杂化。问题变复杂的原因有两个：<BR><BR>　　1、堆上分配空间的数组，由于数组可大可小，所以，数组大小值应该和数组一起保存。因此，堆上分配空间的数组会分配额外的空间来存储数组元素的个数；<BR><BR>　　2、当数组被删除时，数组中每个元素都要被正确地释放，即使当数组大小不确定时也必须成功完成该操作。然而，派生类可能比基类占用更多的内存空间，从而使正确释放比较困难。<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct WW : W { int w1; };<BR>pv = new W[m];<BR>delete [] pv; // delete m W's&nbsp; (sizeof(W)&nbsp; == sizeof(V))<BR>pv = new WW[n];<BR>delete [] pv; // delete n WW's (sizeof(WW) &gt;&nbsp; sizeof(V))</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：WW从W继承，增加了一个成员变量，因此，WW占用的内存空间比W大。然而，不管指针pv指向W的数组还是WW的数组，delete[]都必须正确地释放WW或W对象占用的内存空间。</FONT><FONT size=3><BR><BR>　 　虽然从严格意义上来说，数组delete的多态行为C++标准并未定义，然而，微软有一些客户要求实现该行为。因此，在MSC++中，该行为是用另一个 编译器生成的虚析构帮助函数来完成。该函数被称为“向量delete析构函数”（因其针对特定的类定制，比如WW，所以，它能够遍历数组的每个元素，调用 对每个元素适用的析构函数）。<BR><BR>　　<STRONG>异常处理</STRONG><BR><BR>　　简单说来，异常处理是C++标准委员会工作文件提供的一种机制，通过该机制，一个函数可以通知其调用者“异常”情况的发生，调用者则能据此选择合适的代码来处理异常。该机制在传统的“函数调用返回，检查错误状态代码”方法之外，给程序提供了另一种处理错误的手段。<BR><BR>　 　因为C++是面向对象的语言，很自然地，C++中用对象来表达异常状态。并且，使用何种异常处理也是基于“抛出的”异常对象的静态或动态类型来决定的。 不光如此，既然C++总是保证超出范围的对象能够被正确地销毁，异常实现也必须保证当控制从异常抛出点转换到异常“捕获”点时（栈展开），超出范围的对象 能够被自动、正确地销毁。<BR><BR>　　考虑如下例子：<BR>&nbsp; <BR></FONT>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD><FONT size=3>struct X { X(); }; // exception object class<BR>struct Z { Z(); ~Z(); }; // class with a destructor<BR>extern void recover(const X&amp;);<BR>void f(int), g(int);<BR><BR>int main() {<BR>&nbsp;&nbsp; 　try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　f(0);<BR>&nbsp;&nbsp; 　} catch (const X&amp; rx) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　recover(rx);<BR>&nbsp;&nbsp; 　}<BR>&nbsp;&nbsp; 　return 0;<BR>}<BR><BR>void f(int i) {<BR>&nbsp;&nbsp; 　Z z1;<BR>&nbsp;&nbsp; 　g(i);<BR>&nbsp;&nbsp; 　Z z2;<BR>&nbsp;&nbsp; 　g(i-1);<BR>}<BR><BR>void g(int j) {<BR>&nbsp;&nbsp; 　if (j &lt; 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　throw X();<BR>}</FONT></TD></TR></TBODY></TABLE><FONT size=3><BR></FONT><FONT color=#0000ff size=3>　　译者注：X是异常类，Z是带析构函数的工作类，recover是错误处理函数，f和g一起产生异常条件，g实际抛出异常。</FONT><FONT size=3><BR><BR>　 　这段程序会抛出异常。在main中，加入了处理异常的try &amp; catch框架，当调用f(0)时，f构造z1，调用g(0)后，再构造z2，再调用g(-1)，此时g发现参数为负，抛出X异常对象。我们希望在某个调 用层次上，该异常能够得到处理。既然g和f都没有建立处理异常的框架，我们就只能希望main函数建立的异常处理框架能够处理X异常对象。实际上，确实如 此。当控制被转移到main中异常捕获点时，从g中的异常抛出点到main中的异常捕获点之间，该范围内的对象都必须被销毁。在本例中，z2和z1应该被 销毁。<BR><BR>　　谈到异常处理的具体实现方式，一般情况下，在抛出点和捕获点都使用“表”来表述能够捕获异常对象的类型；并且，实现要保证能够 在特定的捕获点真正捕获特定的异常对象；一般地，还要运用抛出的对象来初始化捕获语句的“实参”。通过合理地选择编码方案，可以保证这些表格不会占用过多 的内存空间。<BR><BR>　　异常处理的开销到底如何？让我们再考虑一下函数f。看起来f没有做异常处理。f确实没有包含try，catch，或者是 throw关键字，因此，我们会猜异常处理应该对f没有什么影响。错！编译器必须保证一旦z1被构造，而后续调用的任何函数向f抛回了异常，异常又出了f 的范围时，z1对象能被正确地销毁。同样，一旦z2被构造，编译器也必须保证后续抛出异常时，能够正确地销毁z2和z1。<BR><BR>　　要实现这些 “展开”语意，编译器必须在后台提供一种机制，该机制在调用者函数中，针对调用的函数抛出的异常动态决定异常环境（处理点）。这可能包括在每个函数的准备 工作和善后工作中增加额外的代码，在最糟糕的情况下，要针对每一套对象初始化的情况更新状态变量。例如，上述例子中，z1应被销毁的异常环境当然与z2和 z1都应该被销毁的异常环境不同，因此，不管是在构造z1后，还是继而在构造z2后，VC++都要分别在状态变量中更新（存储）新的值。<BR><BR>　　所有这些表，函数调用的准备和善后工作，状态变量的更新，都会使异常处理功能造成可观的内存空间和运行速度开销。正如我们所见，即使在没有使用异常处理的函数中，该开销也会发生。<BR><BR>　　幸运的是，一些编译器可以提供编译选项，关闭异常处理机制。那些不需要异常处理机制的代码，就可以避免这些额外的开销了。<BR><BR>　　<STRONG>小结</STRONG><BR><BR>　　好了，现在你可以写C++编译器了（开个玩笑）。<BR><BR>　 　在本文中，我们讨论了许多重要的C++运行实现问题。我们发现，很多美妙的C++语言特性的开销很低，同时，其他一些美妙的特性（译者注：主要是和 “虚”字相关的东西）将造成较大的开销。C++很多实现机制都是在后台默默地为你工作。一般说来，单独看一段代码时，很难衡量这段代码造成的运行时开销， 必须把这段代码放到一个更大的环境中来考察，运行时开销问题才能得到比较明确的答案。</FONT><BR><BR>
<P id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=763797</P>]]></description>
</item><item>
<title><![CDATA[编写类string的构造函数、拷贝构造函数和析构函数]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=33006</link>
<author>zc9706</author>
<pubDate>2008/3/27 19:03:28</pubDate>
<description><![CDATA[
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><SPAN style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　 <SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">String </FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类的原型如下</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">class String<BR>{<BR>&nbsp;&nbsp; public:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String(const char *str=NULL);<SPAN style="COLOR: red">&nbsp;//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">构造函数</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String(const String &amp;other); <SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拷贝构造函数</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~String(void); <SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">析构函数</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&amp; operator=(const String &amp;other); <SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等号操作符重载</SPAN></P><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><FONT color=#000000><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; </SPAN>ShowString();<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left></SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">&nbsp;&nbsp; private:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *m_data; <SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">指针</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><BR></SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt">};</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">String::~String()<BR>{<BR>&nbsp;&nbsp;&nbsp; delete [] m_data; <SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">析构函数，释放地址空间</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">}<BR>String::String(const char *str)<BR>{<BR>&nbsp;&nbsp;&nbsp; if (str==NULL)<SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当初始化串不存在的时候，为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><FONT face="Times New Roman">m_data</FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">申请一个空间存放</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><FONT face="Times New Roman">'\0'</FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><BR></SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_data=new char[1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *m_data='\0';<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当初始化串存在的时候，为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><FONT face="Times New Roman">m_data</FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">申请同样大小的空间存放该串；</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><BR></SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length=strlen(str);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_data=new char[length+1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcpy(m_data,str);<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>}<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">String::String(const String &amp;other)<SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拷贝构造函数，功能与构造函数类似。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">{<BR>&nbsp;&nbsp;&nbsp; int length=strlen(other.m_data);<BR>&nbsp;&nbsp;&nbsp; m_data=new [length+1];<BR>&nbsp;&nbsp;&nbsp; strcpy(m_data,other.m_data);<BR>}<BR>String&amp; String::operator =(const String &amp;other) <BR>{<BR>&nbsp;&nbsp;&nbsp; if (this==&amp;other)<SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当地址相同时，直接返回；</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><BR></SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp; delete [] m_data;<SPAN style="COLOR: red">//</SPAN></FONT></SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当地址不相同时，删除原来申请的空间，重新开始构造；</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt">&nbsp;&nbsp;&nbsp; int length=sizeof(other.m_data);<BR>&nbsp;&nbsp;&nbsp; m_data=new [length+1];<BR>&nbsp;&nbsp;&nbsp; strcpy(m_data,other.m_data);</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt">&nbsp;&nbsp;&nbsp; return *this;&nbsp;<BR>}</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P><SPAN lang=EN-US><o:p><FONT face="Times New Roman">
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt">String::ShowString()<SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt">//</SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由于</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt">m_data</SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是私有成员，对象只能通过</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt">public</SPAN><SPAN style="FONT-SIZE: 13.5pt; COLOR: red; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">成员函数来访问；</SPAN><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: red; mso-font-kerning: 0pt"><o:p></o:p></SPAN></P><o:p></o:p></SPAN>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt">{<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt"><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>cout&lt;&lt;this-&gt;m_data&lt;&lt;endl;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; mso-font-kerning: 0pt">}<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></o:p></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman"></FONT></o:p></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman"></FONT></o:p></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: black; mso-font-kerning: 0pt"><FONT face="Times New Roman">main()<BR>{<BR>String AD;<BR>char * p="ABCDE";<BR>String B(p);<BR>AD.ShowString();<BR>AD=B;<BR>AD.ShowString();<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><SPAN lang=EN-US style="FONT-SIZE: 13.5pt; COLOR: black; mso-font-kerning: 0pt"><BR><FONT face="Times New Roman">}<o:p></o:p></FONT></SPAN></P>
<P>&nbsp;</P>
<P><BR>&nbsp;</P>]]></description>
</item><item>
<title><![CDATA[C++内存分配问题]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=zc9706&amp;id=32871</link>
<author>zc9706</author>
<pubDate>2008/3/25 14:53:43</pubDate>
<description><![CDATA[<TR><TD> 
<P><SPAN class=oblog_text>网上看到，感觉讲得很清晰，刚好能解答我上次的笔试题 </SPAN></P><SPAN class=oblog_text>
<P><BR>char* r = "hello word!"; //指针在栈上，数据放在常量区；<BR>char b[]="hello word!" //b在栈上，数据在栈上；<BR>*r = 'w'; //修改常量区的值，报错；<BR>*b='w'; //修改栈上的值，允许；<BR><BR>其实应该是语法错误，可是VC++6.0没有警告或者错误，r指向的是文字常量区，此区域是编译的时候确定的，并且程序结束的时候自动释放的， *r = 'w';企图修改文字常量区引起错误,b的区别在于其空间是在栈上分配的，因此没有错误。 <BR><BR>const char* r = "hello word!"; //与上同；<BR><BR>*r = 'w'; //对常量进行赋值，报错；<BR><BR><BR><BR>一个由c/C++编译的程序占用的内存分为以下几个部分 <BR>1、<FONT color=#ff0000>栈区（stack</FONT>）— 由编译器自动分配释放 ，存放函数的参数值，局部变量的值 <BR>等。其操作方式类似于数据结构中的栈。 <BR>2、<FONT color=#ff0000>堆区（heap）</FONT> — 一般由程序员分配释放， 若程序员不释放，程序结束时可能 <BR>由OS回收 。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。 <BR>3、<FONT color=#ff0000>全局区（静态区）（static</FONT>）—，全局变量和静态变量的存储是放在一块的，初 <BR>始化的全局变量和静态变量在一块区域， 未初始化的全局变量和未初始化的静态 <BR>变量在相邻的另一块区域。 - 程序结束后有系统释放 <BR>4、<FONT color=#ff0000>文字常量区</FONT> —常量字符串就是放在这里的。 程序结束后由系统释放 <BR>5、<FONT color=#ff0000>程序代码区</FONT>—存放函数体的二进制代码。 <BR>二、例子程序 <BR><FONT color=#0033ff>//main.cpp <BR>int a = 0; 全局初始化区 <BR>char *p1; 全局未初始化区 <BR>main() <BR>{ <BR>int b; 栈 <BR>char s[] = "abc"; 栈 <BR>char *p2; 栈 <BR>char *p3 = "123456"; 123456\0在常量区，p3在栈上。 <BR>static int c =0； 全局（静态）初始化区 <BR>p1 = (char *)malloc(10); <BR>p2 = (char *)malloc(20); <BR>分配得来得10和20字节的区域就在堆区。 <BR>strcpy(p1, "123456"); 123456\0放在常量区，编译器可能会将它与p3所指向的 <BR>"123456"优化成一个地方。 <BR>} </FONT></P>
<P><FONT color=#2b2bd5>#include &lt;iostream&gt; <BR>using namespace std; </FONT></P>
<P><FONT color=#2b2bd5>int global = 100; //全局/静态区 <BR>const int N = 10; //常量区 <BR>int main() <BR>{ <BR>static int a = 0; //全局/静态区 <BR>char arr[100]="test";//arr分配在栈上，"test"也分配在栈上 <BR>char *s = "abcde";//s分配在栈上，"abcde"分配在常量区 <BR>char*str = NULL; //str分配在栈上 <BR>str = new char[10];//str所指向的空间分配在堆上 <BR>delete []str; <BR>return 0; <BR>}</FONT><BR><FONT color=#0033ff><BR></FONT>二、堆和栈的理论知识 <BR>2.1申请方式 <BR>stack: <BR>由系统自动分配。 例如，声明在函数中一个局部变量 int b; 系统自动在栈中为b <BR>开辟空间 <BR>heap: <BR>需要程序员自己申请，并指明大小，在c中malloc函数 <BR>如p1 = (char *)malloc(10); <BR>在C++中用new运算符 <BR>如p2 = (char *)malloc(10); <BR>但是注意p1、p2本身是在栈中的。 <BR>2.2 <BR>申请后系统的响应 <BR>栈：只要栈的剩余空间大于所申请空间，系统将为程序提供内存，否则将报异常提 <BR>示栈溢出。 <BR>堆：首先应该知道操作系统有一个记录空闲内存地址的链表，当系统收到程序的申 <BR>请时， <BR>会遍历该链表，寻找第一个空间大于所申请空间的堆结点，然后将该结点从空闲结 <BR>点链表中删除，并将该结点的空间分配给程序，另外，对于大多数系统，会在这块 <BR>内存空间中的首地址处记录本次分配的大小，这样，代码中的delete语句才能正确 <BR>的释放本内存空间。另外，由于找到的堆结点的大小不一定正好等于申请的大小， <BR>系统会自动的将多余的那部分重新放入空闲链表中。 <BR>2.3申请大小的限制 <BR>栈：在Windows下,栈是向低地址扩展的数据结构，是一块连续的内存的区域。这句 <BR>话的意思是栈顶的地址和栈的最大容量是系统预先规定好的，在 WINDOWS下，栈的 <BR>大小是2M（也有的说是1M，总之是一个编译时就确定的常数），如果申请的空间超 <BR>过栈的剩余空间时，将提示overflow。因此，能从栈获得的空间较小。 <BR>堆：堆是向高地址扩展的数据结构，是不连续的内存区域。这是由于系统是用链表 <BR>来存储的空闲内存地址的，自然是不连续的，而链表的遍历方向是由低地址向高地 <BR>址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见，堆获得的空间比较 <BR>灵活，也比较大。 <BR>2.4申请效率的比较： <BR>栈由系统自动分配，速度较快。但程序员是无法控制的。 <BR>堆是由new分配的内存，一般速度比较慢，而且容易产生内存碎片,不过用起来最方便. <BR>另外，在WINDOWS下，最好的方式是用VirtualAlloc分配内存，他不是在堆，也不 <BR>是在栈是直接在进程的地址空间中保留一快内存，虽然用起来最不方便。但是速度 <BR>快，也最灵活 <BR>2.5堆和栈中的存储内容 <BR>栈： 在函数调用时，第一个进栈的是主函数中后的下一条指令（函数调用语句的 <BR>下一条可执行语句）的地址，然后是函数的各个参数，在大多数的C编译器中，参 <BR>数是由右往左入栈的，然后是函数中的局部变量。注意静态变量是不入栈的。 <BR>当本次函数调用结束后，局部变量先出栈，然后是参数，最后栈顶指针指向最开始 <BR>存的地址，也就是主函数中的下一条指令，程序由该点继续运行。 <BR>堆：一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。 <BR>2.6存取效率的比较 <BR>char s1[] = "aaaaaaaaaaaaaaa"; <BR>char *s2 = "bbbbbbbbbbbbbbbbb"; <BR>aaaaaaaaaaa是在运行时刻赋值的； <BR>而bbbbbbbbbbb是在编译时就确定的； <BR>但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。 <BR>比如： <BR>＃i nclude <STDIO.H>; <BR>void main() <BR>{ <BR>char a = 1; <BR>char c[] = "1234567890"; <BR>char *p ="1234567890"; <BR>a = c[1]; <BR>a = p[1]; <BR>return; <BR>} <BR>对应的汇编代码 <BR>10: a = c[1]; <BR>00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] <BR>0040106A 88 4D FC mov byte ptr [ebp-4],cl <BR>11: a = p[1]; <BR>0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] <BR>00401070 8A 42 01 mov al,byte ptr [edx+1] <BR>00401073 88 45 FC mov byte ptr [ebp-4],al <BR>第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针 <BR>值读到edx中，在根据edx读取字符，显然慢了。 <BR>? <BR>2.7小结： <BR>堆和栈的区别可以用如下的比喻来看出： <BR>使用栈就象我们去饭馆里吃饭，只管点菜（发出申请）、付钱、和吃（使用），吃 <BR>饱了就走，不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作，他的好处是 <BR>快捷，但是自由度小。 <BR>使用堆就象是自己动手做喜欢吃的菜肴，比较麻烦，但是比较符合自己的口味，而 <BR>且自由度大。 <BR>堆和栈的区别主要分： <BR>操作系统方面的堆和栈，如上面说的那些，不多说了。 <BR>还有就是数据结构方面的堆和栈，这些都是不同的概念。这里的堆实际上指的就是 <BR>（满足堆性质的）优先队列的一种数据结构，第1个元素有最高的优先权；栈实际 <BR>上就是满足先进后出的性质的数学或数据结构。 <BR>虽然堆栈，堆栈的说法是连起来叫，但是他们还是有很大区别的，连着叫只是由于 <BR>历史的原因。</SPAN></P>
<P><SPAN class=oblog_text>转自：<A href="http://zhaosheng.csu.edu.cn/Block/blog/user/Yazone/archives/2007/358.htm">http://zhaosheng.csu.edu.cn/Block/blog/user/Yazone/archives/2007/358.htm</A></SPAN></STDIO.H></TD></TR></P>]]></description>
</item>
</channel>
</rss>