﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-无为-随笔分类-C $ C++</title><link>http://www.blogjava.net/mlh123caoer/category/17499.html</link><description>无为则可为，无为则至深！
</description><language>zh-cn</language><lastBuildDate>Mon, 27 Aug 2007 09:04:23 GMT</lastBuildDate><pubDate>Mon, 27 Aug 2007 09:04:23 GMT</pubDate><ttl>60</ttl><item><title>国外开源网站聚合</title><link>http://www.blogjava.net/mlh123caoer/archive/2007/08/25/139337.html</link><dc:creator>草儿</dc:creator><author>草儿</author><pubDate>Sat, 25 Aug 2007 15:16:00 GMT</pubDate><guid>http://www.blogjava.net/mlh123caoer/archive/2007/08/25/139337.html</guid><wfw:comment>http://www.blogjava.net/mlh123caoer/comments/139337.html</wfw:comment><comments>http://www.blogjava.net/mlh123caoer/archive/2007/08/25/139337.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/mlh123caoer/comments/commentRss/139337.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mlh123caoer/services/trackbacks/139337.html</trackback:ping><description><![CDATA[<p>sourceforge <a href="http://www.sourceforge.net/">http://www.sourceforge.net</a><br>java.net <a href="http://www.java.net/">http://www.java.net</a></p>
<p><a href="http://www.eclipse.org/">www.eclipse.org</a></p>
<p><a href="http://www.opensource.org/">www.opensource.org</a><br></p>
<p><span lang=EN-US style="FONT-FAMILY: SimSun; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt; mso-bidi-font-family: SimSun"><a href="http://strutstestcase.sourceforge.net/">http://strutstestcase.sourceforge.net</a> <font color=#002c99>(StrutsTestCase</font></span><span style="FONT-FAMILY: SimSun; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt; mso-bidi-font-family: SimSun">是基于<span lang=EN-US>Junit</span>的一个方便测试<span lang=EN-US>struts</span>框架的测试框架)<br><br></span>Lomboz <a href="http://www.objectlearn.com/index.jsp">http://www.objectlearn.com/index.jsp</a> (J2EE plugin for Eclipse)<br>htmlArea <a href="http://sourceforge.net/projects/itools-htmlarea/">http://sourceforge.net/projects/itools-htmlarea/</a> (所见即所得的在线HTML编辑器)<br>XmlBuddy <a href="http://www.xmlbuddy.com/">http://www.xmlbuddy.com/</a> (XML Editor plugin for Eclipse)<br>JFreeChart <a href="http://www.jfree.org/">http://www.jfree.org/</a> (用于生成图表的项目)<br>EclipseME <a href="http://eclipseme.sourceforge.net/">http://eclipseme.sourceforge.net/</a> (J2ME Developmnt Plugin for Eclipse)<br>mvnForum <a href="http://sourceforge.net/projects/mvnforum/">http://sourceforge.net/projects/mvnforum/</a> (论坛)<br>jChatBox <a href="http://www.javazoom.net/index.shtml">http://www.javazoom.net/index.shtml</a> (用servlet实现的WEB聊天引擎)<br>POI <a href="http://jakarta.apache.org/poi/index.html">http://jakarta.apache.org/poi/index.html</a> (用于处理Excel,WORD等文档的项目)<br>FileUpload <a href="http://jakarta.apache.org/commons/fileupload/">http://jakarta.apache.org/commons/fileupload/</a> (用于处理HTTP文件上传得项目)<br>PDFBox <a href="http://sourceforge.net/projects/pdfbox/">http://sourceforge.net/projects/pdfbox/</a> (处理PDF文档的项目)<br>Lucene <a href="http://jakarta.apache.org/lucene/index.html">http://jakarta.apache.org/lucene/index.html</a> (搜索引擎)<br>Digester <a href="http://jakarta.apache.org/commons/digester/">http://jakarta.apache.org/commons/digester/</a> (处理XML信息的项目)<br>DBCP <a href="http://jakarta.apache.org/commons/dbcp/">http://jakarta.apache.org/commons/dbcp/</a> (数据库连接池)<br>AXIS <a href="http://ws.apache.org/axis/">http://ws.apache.org/axis/</a> (WebService 的实现框架)<br>Jetspeed <a href="http://portals.apache.org/jetspeed-1/">http://portals.apache.org/jetspeed-1/</a> (Portal)<br>HSQLDB <a href="http://sourceforge.net/projects/hsqldb/">http://sourceforge.net/projects/hsqldb/</a> (Im memory Database Engine)<br>CEWOLF <a href="http://sourceforge.net/projects/cewolf/">http://sourceforge.net/projects/cewolf/</a> (一套标签库实现Web报表,使用的是jFreeChart引擎)<br>Struts Menu <a href="http://sourceforge.net/projects/struts-menu/">http://sourceforge.net/projects/struts-menu/</a> (基于Struts的Web菜单项目)<br>htmlparser <a href="http://sourceforge.net/projects/htmlparser/">http://sourceforge.net/projects/htmlparser/</a> (用于解析HTML信息的项目)<br>Mondrian <a href="http://sourceforge.net/projects/mondrian/(Open">http://sourceforge.net/projects/mondrian/(Open</a> Source OLAP Database)<br>ProGuard <a href="http://sourceforge.net/projects/proguard/(Java">http://sourceforge.net/projects/proguard/(Java</a>的混淆器)<br>InfoGlue <a href="http://sourceforge.net/projects/infoglue/">http://sourceforge.net/projects/infoglue/</a> (J2EE 内容管理系统)<br>JPivot <a href="http://sourceforge.net/projects/jpivot/">http://sourceforge.net/projects/jpivot/</a> (基于WEB的OLAP 展现)<br><a href="http://java-source.net/">http://java-source.net/</a></p>
<p>(5)几个常用JAVA开源项目的地址荟萃:<br>Lomboz <a href="http://www.objectlearn.com/index.jsp">http://www.objectlearn.com/index.jsp</a> (J2EE plugin for Eclipse)<br>htmlArea <a href="http://sourceforge.net/projects/itools-htmlarea/">http://sourceforge.net/projects/itools-htmlarea/</a> (所见即所得的在线HTML编辑器)<br>XmlBuddy <a href="http://www.xmlbuddy.com/">http://www.xmlbuddy.com/</a> (XML Editor plugin for Eclipse)<br>JFreeChart <a href="http://www.jfree.org/">http://www.jfree.org/</a> (用于生成图表的项目)<br>EclipseME <a href="http://eclipseme.sourceforge.net/">http://eclipseme.sourceforge.net/</a> (J2ME Developmnt Plugin for Eclipse)<br>mvnForum <a href="http://sourceforge.net/projects/mvnforum/">http://sourceforge.net/projects/mvnforum/</a> (论坛)<br>jChatBox <a href="http://www.javazoom.net/index.shtml">http://www.javazoom.net/index.shtml</a> (用servlet实现的WEB聊天引擎)<br>POI <a href="http://jakarta.apache.org/poi/index.html">http://jakarta.apache.org/poi/index.html</a> (用于处理Excel,WORD等文档的项目)<br>FileUpload <a href="http://jakarta.apache.org/commons/fileupload/">http://jakarta.apache.org/commons/fileupload/</a> (用于处理HTTP文件上传得项目)<br>PDFBox <a href="http://sourceforge.net/projects/pdfbox/">http://sourceforge.net/projects/pdfbox/</a> (处理PDF文档的项目)<br>Lucene <a href="http://jakarta.apache.org/lucene/index.html">http://jakarta.apache.org/lucene/index.html</a> (搜索引擎)<br>Digester <a href="http://jakarta.apache.org/commons/digester/">http://jakarta.apache.org/commons/digester/</a> (处理XML信息的项目)<br>DBCP <a href="http://jakarta.apache.org/commons/dbcp/">http://jakarta.apache.org/commons/dbcp/</a> (数据库连接池)<br>AXIS <a href="http://ws.apache.org/axis/">http://ws.apache.org/axis/</a> (WebService 的实现框架)<br>Jetspeed <a href="http://portals.apache.org/jetspeed-1/">http://portals.apache.org/jetspeed-1/</a> (Portal)<br>HSQLDB <a href="http://sourceforge.net/projects/hsqldb/">http://sourceforge.net/projects/hsqldb/</a> (Im memory Database Engine)<br>CEWOLF <a href="http://sourceforge.net/projects/cewolf/">http://sourceforge.net/projects/cewolf/</a>(一套标签库实现Web报表,使用的是jFreeChart擎)<br>Struts Menu <a href="http://sourceforge.net/projects/struts-menu/">http://sourceforge.net/projects/struts-menu/</a> (基于Struts的Web菜单项目)<br>htmlparser <a href="http://sourceforge.net/projects/htmlparser/">http://sourceforge.net/projects/htmlparser/</a> (用于解析HTML信息的项目)<br>Mondrian <a href="http://sourceforge.net/projects/mondrian/">http://sourceforge.net/projects/mondrian/</a> (Open Source OLAPdatabase)<br>ProGuard <a href="http://sourceforge.net/projects/proguard/">http://sourceforge.net/projects/proguard/</a> (Java的混淆器)<br>InfoGlue <a href="http://sourceforge.net/projects/infoglue/">http://sourceforge.net/projects/infoglue/</a> (J2EE 内容管理系统)<br>JPivot <a href="http://sourceforge.net/projects/jpivot/">http://sourceforge.net/projects/jpivot/</a> (基于WEB的OLAP 展现)<br>HttpClient <a href="http://jakarta.apache.org/commons/httpclient/">http://jakarta.apache.org/commons/httpclient/</a> 处理http客户端的接口</p><img src ="http://www.blogjava.net/mlh123caoer/aggbug/139337.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mlh123caoer/" target="_blank">草儿</a> 2007-08-25 23:16 <a href="http://www.blogjava.net/mlh123caoer/archive/2007/08/25/139337.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针专题 </title><link>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82250.html</link><dc:creator>草儿</dc:creator><author>草儿</author><pubDate>Mon, 20 Nov 2006 06:10:00 GMT</pubDate><guid>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82250.html</guid><wfw:comment>http://www.blogjava.net/mlh123caoer/comments/82250.html</wfw:comment><comments>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82250.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mlh123caoer/comments/commentRss/82250.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mlh123caoer/services/trackbacks/82250.html</trackback:ping><description><![CDATA[一、<strong>数组的指针、指针数组以及指向指针的指针</strong><p>　　考虑数组的指针的时候我们要同时考虑类型和维数这两个属性。换一句话，就是说一个数组排除在其中存储的数值，那么可以用类型和维数来位置表示他的种类。</p><p>A）一维数组<br />　　在c和c++中数组的指针就是数组的起始地址（也就第一个元素的地址），而且标准文档规定数组名代表数组的地址（这是地址数值层面的数组表示）。例如：</p><pre>int a[10];int *p;</pre><p>p=&amp;a[0]//和p=a是等价的：<br /><br />　　因为a是数组名，所以他是该数组的地址，同时因为第一个元素为a[0]，那么&amp;a[0]也代表了该数组的地址。但是我们是不是就说一个数组名和该数组的第一个元素的&amp;运算是一回事呢？在一维的时候当时是的，但是在高维的时候，我们要考虑到维数给数组带来的影响。<br />　　a[10]是一个数组，a是数组名，它是一个包含10个int类型的数组类型，不是一般的指针变量噢！（虽然标准文档规定在c++中从int[]到int*直接转换是可以的，在使用的时候似乎在函数的参数为指针的时候，我们将该数组名赋值没有任何异样），a代表数组的首地址，在数字层面和a[10]的地址一样。这样我们就可以使用指针变量以及a来操作这个数组了。<br />所以我们要注意以下问题：</p><p>（1） p[i]和a[i]都是代表该数组的第i+1个元素；<br />（2） p+i和a+i代表了第i+1个元素的地址，所以我们也可以使用　*（p+I）和*（a+I）来引用对象元素；<br />（3）p+1不是对于指针数量上加一，而是表示从当前的位置跳过当前指针指向类型长度的空间，对于win32的int为4byte；</p><p>B)多维数组<br />　　对于二维数组a[4][6];由于数组名代表数组的起始地址，所以a（第一层）和第一个元素a[0][0]地址的数字是相同的，但是意义却是不同的。对于该数组我们可以理解为：a的一维数组（第一层），它有四个元素a[0]、a[1]、a[2]、a[3]（第二层），而每个元素又含有6个元素a[0][0],a[0][1],a[0][2],a[0][3],a[0][4]，a[0][5]（第三层）,…到此我们终于访问到了每个元素了，这个过程我们经历了：a-&gt;a[0]-&gt;a[0][0]；<br />　　整体来讲：a是一个4行5列的二维数组，a表示它指向的数组的首地址（第一个元素地址&amp;a[0]）,同时a[0]指向一行，它是这个行的名字（和该行的第一个元素的首地址相同（第一个元素为地址&amp;a[0][0]））。所以从数字角度说：a、a[0]、&amp;a[0][0]是相同的，但是他们所处的层次是不同的。<br />　　既然a代表二维数组，那么a+i就表示它的第i+1个元素*（a+i）的地址，而在二维数组中<br />*（a+i）又指向一个数组，*（a+i）+j表示这个数组的第j+1个元素的地址，所以要访问这个元素可以使用 *（*（a+i）+j）（也就是a[i][j]）。<br />他们的示意图为（虚线代表不是实际存在的）：</p><p><img height="199" alt="" src="http://www.vckbase.com/document/journal/vckbase48/images/pntfigimg1.gif" width="291" border="0" /></p><p>对照这个图，如下的一些说法都是正确的（对于a[4][6]）：</p><ul><li>a是一个数组类型，*a指向一个数组； 
</li><li>a+i指向一个数组； 
</li><li>a、*a和&amp;a[0][0]数值相同； 
</li><li>a[i]+j和*（a+i）+j是同一个概念； </li></ul><p>　　总结一下就是：我们对于二维指针a，他指向数组a[0，1，2，3]，使用*，可以使他降级到第二层次，这样*a就指向了第一个真正的数组。对于其他的情况我们也可以采用相同的方式，对于其他维数和类型的数组我们可以采用相类似的思想。<br /><br />说到指向数组的指针，我们还可以声明一个指针变量让它指向一个数组。例如：</p><pre>int （*p）[5]；</pre><p>这时p就是一个指针，要指向一个含有5个int类型元素的数组，指向其他的就会出现问题。<br />这个时候我们可以使用上面的什么东西来初始化呢？<br />我们可以使用*a,*(a+1)，a[2]等。<br />原因很简单：我们在一个二维的数组中，那么表达方式有上面的相互类似的意义呢？只有　*a,*(a+1)，a[2]等，</p><p>C)指针数组<br />　　一个指针数组是指一个数组中的每个元素都是一个指针，例如：</p><pre>int *p[10];//而不能是int (*p)[10]</pre><p>或者</p><pre>char *p[10];</pre><p>此时p是一个指针（数值上和&amp;p[0]一样）；<br />在前面有int t[10]；</p><pre>int * pt=t;//使用pt指向t</pre><p>那么这里我们用什么指向int *t[10]中的t呢？我们要使用一个指针的指针：</p><pre>int **pt=t;</pre><p>　　这是因为：在int *t[10]中，每个元素是指针，那么同时t又指向这个数组，数组上和&amp;t[0]相同，也就是指向t[0]，指向一个指针变量，可以说是一个指针的指针了，所以自然要用</p><pre>int **pt;</pre><p><br />D)指针的指针<br />　　一个指针变量内部可以存储一个值，这个值是另外一个对象的地址，所以我们说一个指针变量可以指向一个普通变量，同样这个指针变量也有一个地址，也就是说有一个东西可以指向这个指针变量，然后再通过这个指针变量指向这个对象。那么如何来指向这个指针变量呢？由于指针变量本身已经是一个指针了（右值），那么我们这里就不能用一般的指针了，需要在指针上体现出来这些特点，我们需要定义指针的指针（二重指针）。</p><pre>int *p1=&amp;i;int**p2=&amp;p1；</pre><p>综合以上的所有点，下面是我们常常看到一些匹配（也是经常出错的地方）：</p><pre>int a[3],b[2][3],c,*d[3];void fun1(int *p)；void fun2(int (*p)[3]);void fun3(int **p);void fun4(int p[3]); void fun5(int p[]);void fun6(int p[2][3]);void fun7(int (&amp;p)[3]);</pre><p>函数 不会产生编译时刻的可能值（但逻辑上不一定都对）</p><table class="MsoNormalTable" id="table1" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN-LEFT: 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" width="389" border="1"><tbody><tr style="HEIGHT: 15pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 15pt" valign="top"><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">函数</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 15pt" valign="top"><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">不会产生编译时刻的可能值（但逻辑上不一定都对）</span></p></td></tr><tr style="HEIGHT: 6.75pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 6.75pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun1</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 6.75pt" valign="top"><p class="MsoNormal" style="TEXT-INDENT: 10.5pt"><span lang="EN-US" style="FONT-FAMILY: 宋体">a, &amp;a[i], *b ,b[i],&amp;b[i][j] ,&amp;c ,d[i]</span></p></td></tr><tr style="HEIGHT: 14.25pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 14.25pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun2</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 14.25pt" valign="top"><p class="MsoNormal" style="TEXT-INDENT: 10.5pt"><span lang="EN-US" style="FONT-FAMILY: 宋体">b</span><span style="FONT-FAMILY: 宋体">，<span lang="EN-US">b+i</span>，</span></p></td></tr><tr style="HEIGHT: 14.25pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 14.25pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun3</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 14.25pt" valign="top"><p class="MsoNormal" style="TEXT-INDENT: 10.5pt"><span lang="EN-US" style="FONT-FAMILY: 宋体">d</span></p></td></tr><tr style="HEIGHT: 13.5pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 13.5pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun4</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 13.5pt" valign="top"><p class="MsoNormal" style="TEXT-INDENT: 10.5pt"><span lang="EN-US" style="FONT-FAMILY: 宋体">a, &amp;a[i], *b ,b[i],&amp;b[i][j] ,&amp;c ,d[i]</span></p></td></tr><tr style="HEIGHT: 17.25pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 17.25pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun5</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 17.25pt" valign="top"><p class="MsoNormal" style="TEXT-INDENT: 10.5pt"><span lang="EN-US" style="FONT-FAMILY: 宋体">a, &amp;a[i], *b ,b[i],&amp;b[i][j] ,&amp;c ,d[i]</span></p></td></tr><tr style="HEIGHT: 10.5pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 10.5pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun6</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 10.5pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">  b</span></p></td></tr><tr style="HEIGHT: 16.95pt"><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 37px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 16.95pt" valign="top"><p class="MsoNormal"><span lang="EN-US" style="FONT-FAMILY: 宋体">fun7</span></p></td><td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 321px; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 16.95pt" valign="top"><p class="MsoNormal" style="TEXT-INDENT: 10.5pt"><span lang="EN-US" style="FONT-FAMILY: 宋体">a</span></p></td></tr></tbody></table><p>为什么可以有这样的搭配，原因如下：</p><ul><li>对于fun1 fun4 fun 5: 在编译器看来fun1,fun4,fun5的声明是一样，在编译时候，编译器把数组的大小舍去不考虑，只考虑它是一个指针，也就是说有没有大小说明是一样的，所以三者的形式都是fun1的形式（其实只要提供了int*指针就可以了）； 
</li><li>对于fun7 ：以上的解释对于引用是不适用的，如果变量被声明为数组的引用，那么编译器就要考虑数组的大小了，那么必须和声明一模一样（所以fun7就只有a合适）； 
</li><li>对于fun2：p是一个指向一个含有3个元素的数组，这样b和b+i正好合适，而a却不是（它是指向a[0]的，不是指向这个数组的）； 
</li><li>对于fun3：p是一个指针的指针，而d指向d[0]，同时d[0]又是一个指针，所以d就是一个指针的指针。但是b却不是（它是一个2*3的矩阵也就是年int [2][3]类型）； 
</li><li>对于fun6，p是一个2*3的数组类型，和b恰好完全匹配；<br /></li></ul><strong><br />二、函数指针、函数的指针参数以及返回指针的函数</strong><p>A) 函数指针<br />　　C++规定，一个函数的地址就是这个函数的名字。我们需要指出的就是一个指针需要指定类型是为了后来的指针解析时候使用，通过指针有效快速访问对象。那么对于函数的指针，它要表示出该函数的那些特性才能满足解析的唯一性呢？答案就是一个函数的特性有它的参数列表和返回类型。<br /><br />下面是一个函数指针的例子：</p><pre>int (*p)(int I,int j);</pre><p>不能是</p><pre>int *p(int I,int j)，</pre><p>这样就变成了返回指针的函数声明了。</p><p>　　在C++中处于对安全性的考虑，指针和它指向的对象要类型一致，也就说上面的指针所指向的函数的特性要和它一模一样：例如指向int min(int I,int j)；是可以的。但是指向int min(double I ,double j);是不可以。函数指针也和其他的指针一样，在使用的时候很怕发生"悬空"，所以在使用的时候同样要判断有效性，或者在定义的时候就初始化。</p><pre>int (*p)(int I,int j)=min;int (*p)(int I,int j)=&amp;min;int (*p)(int I,int j)=0；</pre><p>B) 函数的指针参数<br />　　函数指针可以作函数的参数：例如我们有一个积分的算法，对于不同的数学函数可以进行积分（我们这里假设函数都是一元的）；<br />那么我们的算法接口可以定义为：</p><pre>template&lt;class T&gt;T integrate( T lower, T upper , T (*)(T)=0 )throw(integrated_exp);</pre><p>　　这里的最后的参数是一个函数的指针，并且被设定缺省值为0。这个函数返回一个值，同时需要一个参数。假如加入我们有这样的一个函数：</p><pre>double line(double x){ return a*x+b;}</pre><p>那么我就可以使用了。<br /><br />函数指针还可以作为返回类型（注意不是函数！！，某个特定的函数是不可以作为返回类型的。）假设：</p><pre>typedef int (*PF)(int );PF getProcessMethod( );//true</pre><p>C) 返回指针的函数<br />　　一个函数的返回是函数的重要接口之一，c++的一个重要的强大的功能就是能够设计足够复杂和好用的用户自定义类型。而同时处理和传递这些类型也是很麻烦的一件事情，我们不想把我们的时间都花在这些对于我们的实际工作没有很实质帮助的拷贝上，解决这个问题就要依赖我们的接口设计：c和c++都提供了相应的解决方案，在c++中我们可是使用引用，讲他们作为函数的实际参数，或者我们在函数的实际参数中使用一个指针等。同样我们还可以使用一个函数返回一个指针：但是这是一个很不好解决的问题！<br />我们首先容易出错的是：将一个局部变量的地址传出来！例如：</p><pre>UserType * Process( ){　　UserType ut(param-list);　　//process ut;　　return &amp;ut;//}</pre><p>　　这个变量在我们的函数结束的时候就被销毁了，尽管地址可以传出去，但是这个地址已经不存在了，已经不能使用的东西，在这个函数之外却不知道，难免要出错！<br />同时我还会有一个比较麻烦的问题：使用new，又容易造成内存泄露</p><pre>UserType * Process ( ){　　UserTpye *put=new UserType(param-list );　　//process put;　　return put;}</pre><p>我们在函数内部使用了一个new，分配了一个空间，这样传出来也是可以！<br />　　就是说不会发生上面的问题了。但是用户通常都会忘记在程序的外面在把这个借来的空间还回去！内存空间就这样泄露了！<br />可能也是这些另人无奈的问题，所以很多程序员把函数的参数设定为指针或者引用，以此来代替这种向外传输吧！总之，使用这种返回指针的函数要小心！</p><p><strong>三、类成员的指针</strong></p><p>　　类成员和一般的外部变量相互比较，不同就是它所在的域不同，这个域很重要，它决定了该变量可以使用的范围。那么一个指针如果要指向类的成员函数或者成员变量，那么除了要表达它的返回类型、参数列表或者类型之外，那么还要说明它所指向的变量（或者函数）的域，为了说明该域我们要使用类域限定：</p><pre>class NJUPT{　　static double money=20000000;　　int num;　　public:　　NJUPT():num(10){};　　int get(){return num;};　　double getMoney(){reuturn money;}}</pre><p>我们定义成员的指针为</p><pre>int NJUPT:: *p;//指向int型成员变量int (NJUPt::*)p()//指向int f()型成员函数。</pre><p>为了使用这些指针，我们需要使用该类型的变量或者指针。</p><pre>NJUPT s,*ps;</pre><p>那么调用的方式为：</p><pre>cout&lt;&lt;s.*p;cout&lt;&lt;(s-&gt;*p)();</pre><p>　　这个看起来似乎很奇怪！但是只要你想到我们定义的指针被限定在了类域中了（我们在开始定义的使用使用了NJUPT:: ），这么使用也是很自然的。<br />　　如果一个类还有一些静态成员变量和静态成员函数，那么我是否也想这样使用呢？<br />答案是不用，静态成员我们就可以象使用外部的普通成员一样定义一个指针或者函数指针来访问就可以了，究其原因主要是这个成员的类型性质决定的。</p><pre>double *p=&amp;NJUPT::money;double (*p)()=&amp;NJUPT::getMoney():　</pre><img src ="http://www.blogjava.net/mlh123caoer/aggbug/82250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mlh123caoer/" target="_blank">草儿</a> 2006-11-20 14:10 <a href="http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数组,函数与指针</title><link>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82245.html</link><dc:creator>草儿</dc:creator><author>草儿</author><pubDate>Mon, 20 Nov 2006 06:05:00 GMT</pubDate><guid>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82245.html</guid><wfw:comment>http://www.blogjava.net/mlh123caoer/comments/82245.html</wfw:comment><comments>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mlh123caoer/comments/commentRss/82245.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mlh123caoer/services/trackbacks/82245.html</trackback:ping><description><![CDATA[<p>一 ：关于指针和堆的内存分配 <br />先来介绍一下指针 ：　指针一种类型，理论上来说它包含其他变量的地址，因此有的书上也叫它：地址变量。既然指针是一个类型，是类型就有大小，在达内的服务器上或者普通的ＰＣ机上，都是４个字节大小,里边只是存储了一个变量的地址而已。不管什么类型的指针，char * ,int * ,int (*) ,string * ,float * ，都是说明了本指针所指向的地址空间是什么类型而已，了解了这个基本上所有的问题都好象都变的合理了。 <br /><br />在C++中，申请和释放堆中分配的存贮空间，分别使用new和delete的两个运算符来完成： <br />指针类型　指针变量名=new 指针类型 (初始化)； <br />        delete 指针名; <br />例如：</p>
		<p>1、 int *p=new int(0); <br />     它与下列代码序列大体等价： <br />2、int tmp=0, *p=&amp;tmp; <br />区别：p所指向的变量是由库操作符new()分配的，位于内存的堆区中，并且该对象未命名。 <br />　　 <br />下面是关于new 操作的说明　：　</p>
		<p>1、new运算符返回的是一个指向所分配类型变量（对象）的指针。对所创建的变量或对象，都是通过该指针来间接操作的，而动态创建的对象本身没有名字。 <br />2、一般定义变量和对象时要用标识符命名，称命名对象，而动态的称无名对象(请注意与栈区中的临时对象的区别，两者完全不同：生命期不同，操作方法不同，临时变量对程序员是透明的)。 <br />3、堆区是不会在分配时做自动初始化的（包括清零），所以必须用初始化式(initializer)来显式初始化。new表达式的操作序列如下：从堆区分配对象，然后用括号中的值初始化该对象。 <br /><br />下面是从堆中申请数组 <br />1、申请数组空间： <br />指针变量名=new 类型名[下标表达式]; <br />注意：“下标表达式”不是常量表达式，即它的值不必在编译时确定，可以在运行时确定。这就是堆的一个非常显著的特点，有的时候程序员本身都不知道要申请能够多少内存的时候，堆就变的格外有用。 <br />2、释放数组空间： <br />delete [ ]指向该数组的指针变量名; <br />注意：方括号非常重要的，如果delete语句中少了方括号，因编译器认为该指针是指向数组第一个元素的，会产生回收不彻底的问题（只回收了第一个元素所占空间），我们通常叫它“内存泄露”，加了方括号后就转化为指向数组的指针，回收整个数组。delete [ ]的方括号中不需要填数组元素数，系统自知。即使写了，编译器也忽略。&lt;&lt;Think in c++&gt;&gt;上说过以前的delete []方括号中是必须添加个数的，后来由于很容易出错，所以后来的版本就改进了这个缺陷。 <br />下面是个例子，VC上编译通过 <br />#include&lt;iostream&gt; <br />using namespace std; <br />//#include &lt;iostream.h&gt; 　//for VC <br />#include &lt;string.h&gt; <br />void main(){ <br />int n; <br />char *p; <br />cout&lt;&lt;"请输入动态数组的元素个数"&lt;&lt;endl; <br />cin&gt;&gt;n; //n在运行时确定，可输入17 <br />p=new char[n]; //申请17个字符（可装8个汉字和一个结束符）的内存空间strcpy(pc,“堆内存的动态分配”);// <br />cout&lt;&lt;p&lt;&lt;endl; <br />delete []p;//释放pc所指向的n个字符的内存空间return ;　} <br /><br />通过指针使堆空间，编程中的几个可能问题 <br /><br />１．动态分配失败。返回一个空指针（NULL），表示发生了异常，堆资源不足，分配失败。 <br />   data = new double [m]; //申请空间 <br />if ((data ) == 0)…… //或者==NULL <br />２．指针删除与堆空间释放。删除一个指针p（delete p;）实际意思是删除了p所指的目标（变量或对象等），释放了它所占的堆空间，而不是删除ｐ本身，释放堆空间后，ｐ成了空悬指针，不能再通过p使用该空间，在重新给p赋值前，也不能再直接使用p。 <br />３．内存泄漏（memory leak）和重复释放。new与delete 是配对使用的， delete只能释放堆空间。如果new返回的指针值丢失，则所分配的堆空间无法回收，称内存泄漏，同一空间重复释放也是危险的，因为该空间可能已另分配，而这个时候又去释放的话，会导致一个很难查出来的运行时错误。所以必须妥善保存new返回的指针，以保证不发生内存泄漏，也必须保证不会重复释放堆内存空间。 <br />４．动态分配的变量或对象的生命期。无名变量的生命期并不依赖于建立它的作用域，比如在函数中建立的动态对象在函数返回后仍可使用。我们也称堆空间为自由空间（free store）就是这个原因。但必须记住释放该对象所占堆空间，并只能释放一次，在函数内建立，而在函数外释放是一件很容易失控的事，往往会出错，所以永远不要在函数体内申请空间，让调用者释放，这是一个很差的做法。你再怎么小心翼翼也可能会带来错误。 <br />类在堆中申请内存 ： <br />通过new建立的对象要调用构造函数，通过deletee删除对象要调用析构函数。 <br />CGoods *pc; <br />pc=new CGoods;  //分配堆空间，并构造一个无名对象 <br />                              //的CGoods对象； <br />……. <br />delete pc;  //先析构，然后将内存空间返回给堆；        堆对象的生命期并不依赖于建立它的作用域，所以除非程序结束，堆对象（无名对象）的生命期不会到期，并且需要显式地用delete语句析构堆对象，上面的堆对象在执行delete语句时，C++自动调用其析构函数。 <br />正因为构造函数可以有参数，所以new后面类（class）类型也可以有参数。这些参数即构造函数的参数。 <br />但对创建数组，则无参数，并只调用缺省的构造函数。见下例类说明： <br /><br />class CGoods{ <br />          char Name[21]; <br />          int  Amount; <br />          float Price; <br />          float Total_value; <br />public: <br /> CGoods(){}; //缺省构造函数。因已有其他构造函数，系统不会再自动生成缺省构造，必须显式声明。   CGoods(char* name,int amount ,float price){ <br />           strcpy(Name,name); <br />           Amount=amount; <br />           Price=price; <br />           Total_value=price*amount;　　} <br />           ……}；//类声明结束 <br />下面是调用机制　： <br /><br />void main(){ <br /> int n; <br /> CGoods *pc,*pc1,*pc2; <br /> pc=new CGoods(“hello”，10，118000); <br /> //调用三参数构造函数   pc1=new CGoods();  //调用缺省构造函数  cout&lt;&lt;”输入商品类数组元素数”&lt;&lt;endl; <br /> cin&gt;&gt;n; <br /> pc2=new CGoods[n]; <br />//动态建立数组，不能初始化，调用n次缺省构造函数   <br /> …… <br /> delete pc; <br /> delete pc1; <br /> delete []pc2;  } <br /><br />申请堆空间之后构造函数运行； <br />释放堆空间之前析构函数运行； <br />再次强调：由堆区创建对象数组，只能调用缺省的构造函数，不能调用其他任何构造函数。如果没有缺省的构造函数，则不能创建对象数组。 <br /><br />---------------------下面我们再来看一下指针数组和数组指针――――――――――――― <br />如果你想了解指针最好理解以下的公式 ： <br />(1)int*ptr;//指针所指向的类型是int <br /><br />　　(2)char*ptr;//指针所指向的的类型是char <br /><br />　　(3)int**ptr;//指针所指向的的类型是int* （也就是一个int * 型指针） <br /><br />　　(4)int(*ptr)[3];//指针所指向的的类型是int()[3] //二维指针的声明 <br /><br />（１）指针数组：一个数组里存放的都是同一个类型的指针，通常我们把他叫做指针数组。 <br />比如 int * a[10];它里边放了１０个int * 型变量，由于它是一个数组，已经在栈区分配了１０个(int * )的空间，也就是３２位机上是４０个byte,每个空间都可以存放一个int型变量的地址，这个时候你可以为这个数组的每一个元素初始化，在，或者单独做个循环去初始化它。 <br />例子： <br />int * a[2]={ new int(3),new int(4) };     //在栈区里声明一个int * 数组，它的每一个元素都在堆区里申请了一个无名变量，并初始化他们为３和４，注意此种声明方式具有缺陷，VC下会报错 <br />例如　： <br />int * a[2]={new int[3],new int[3]}; <br />delete a[0]; <br />delet a[10]; <br />但是我不建议达内的学生这么写，可能会造成歧义，不是好的风格，并且在VC中会报错，应该写成如下　： <br />int * a[2]； <br />a[0]= new int[3]; <br />a[1]=new int[3]; <br />delete a[0]; <br />delet a[10]; <br />这样申请内存的风格感觉比较符合大家的习惯；由于是数组，所以就不可以delete a;编译会出警告.delete  a[1]; <br />注意这里 是一个数组，不能delete [] ; <br />（ ２ ） 数组指针　： 一个指向一维或者多维数组的指针； <br />int * b=new int[10];　指向一维数组的指针b ; <br />注意，这个时候释放空间一定要delete [] ,否则会造成内存泄露， b 就成为了空悬指针. <br /><br />int (*b2)[10]=new int[10][10]; 注意，这里的b2指向了一个二维int型数组的首地址. <br />注意：在这里，b2等效于二维数组名，但没有指出其边界，即最高维的元素数量，但是它的最低维数的元素数量必须要指定！就像指向字符的指针，即等效一个字符串,不要把指向字符的指针说成指向字符串的指针。这与数组的嵌套定义相一致。 <br />int(*b3) [30] [20];  //三级指针――&gt;指向三维数组的指针； <br />int (*b2) [20];     //二级指针； <br />b3=new int [1] [20] [30]; <br />b2=new int [30] [20]; <br />      两个数组都是由600个整数组成，前者是只有一个元素的三维数组，每个元素为30行20列的二维数组，而另一个是有30个元素的二维数组，每个元素为20个元素的一维数组。 <br />      删除这两个动态数组可用下式： <br />delete [] b3;  //删除（释放）三维数组； <br />delete [] b2;  //删除（释放）二维数组； <br />再次重申：这里的b2的类型是int (*) ，这样表示一个指向二维数组的指针。 <br />b3表示一个指向（指向二维数组的指针）的指针，也就是三级指针. <br /><br />（ 3 ） 二级指针的指针 <br />看下例 : <br />int (**p)[2]=new (int(*)[3])[2]; <br />       p[0]=new int[2][2]; <br />       p[1]=new int[2][2]; <br />       p[2]=new int[2][2]; <br />       delete [] p[0]; <br />       delete [] p[1]; <br />       delete [] p[2]; <br />       delete [] p; <br />注意此地方的指针类型为int (*),碰到这种问题就把外边的[2]先去掉，然后回头先把int ** p＝new int(*)[n]申请出来，然后再把外边的［２］附加上去； <br />p代表了一个指向二级指针的指针，在它申请空间的时候要注意指针的类型，那就是int (*)代表二级指针，而int (**)顾名思义就是代表指向二级指针的指针了。既然是指针要在堆里申请空间，那首先要定义它的范围：（int(*)[n]）[2]，n 个这样的二级指针，其中的每一个二级指针的最低维是２个元素.（因为要确定一个二级指针的话，它的最低维数是必须指定的，上边已经提到）。然后我们又分别为p[0],p[1],p[2]…在堆里分配了空间，尤其要注意的是：在释放内存的时候一定要为p[0],p[1],p[2],单独delete[] ,否则又会造成内存泄露，在delete[]p 的时候一定先delete p[0]; delete p[1]，然后再把给p申请的空间释放掉 delete [] p ……这样会防止内存泄露。 <br /><br />（３）指针的指针； <br />int ** cc=new (int*)[10]; 声明一个１０个元素的数组，数组每个元素都是一个int *指针，每个元素还可以单独申请空间，因为cc的类型是int*型的指针，所以你要在堆里申请的话就要用int *来申请； <br />看下边的例子  (ｖｃ &amp; GNU编译器都已经通过)； <br />       int ** a= new int * [2];　　　　　//申请两个int * 型的空间 <br />       a[1]=new int[3];　　　　　　　　//为a的第二个元素又申请了３个int 型空间,a[1]指向了此空间首地址处 <br />       a[0]=new int[4];　　　　　　　　////为a的第一个元素又申请了４个int 型空间，a[0] 指向了此空间的首地址处 <br />       int * b; <br />       a[0][0]=0; <br />       a[0][1]=1; <br />       b=a[0]; <br />  delete [] a[0]　　　　　　　//一定要先释放a[0]，a[1]的空间，否则会造成内存泄露.; <br />       delete [] a[1]; <br />  delete [] a; <br />       b++; <br />       cout&lt;&lt;*b&lt;&lt;endl;       //随机数 <br />注意　：因为a 是在堆里申请的无名变量数组，所以在delete 的时候要用delete [] 来释放内存，但是a的每一个元素又单独申请了空间，所以在delete [] a之前要先delete [] 掉 a[0],a[1],否则又会造成内存泄露. <br />（４） 指针数组　： <br />　　　 <br />我们再来看看第二种　：二维指针数组 <br />int *(*c)[3]=new int *[3][2]； <br />如果你对上边的介绍的个种指针类型很熟悉的话，你一眼就能看出来c是个二级指针,只不过指向了一个二维int * 型的数组而已，也就是二维指针数组。 <br />例子　： <br /> int *(*b)[10]=new int*[2][10];// <br />b[0][0]=new int[100]; <br />b[0][1]=new int[100]; <br />*b[0][0]=1; <br />cout &lt;&lt;*b[0][0]&lt;&lt;endl;    //打印结果为１ <br />delete [] b[0][0]; <br />delete [] b[0][1]; <br />delete [] b; <br />cout&lt;&lt;*b[0][0]&lt;&lt;endl;    //打印随机数 <br />　这里只为大家还是要注意内存泄露的问题，在这里就不再多说了。 <br />如果看了上边的文章，大家估计就会很熟悉，这个b是一个二维指针，它指向了一个指针数组 <br /><br />第二种　： <br />int **d[2];表示一个拥有两个元素数组，每一个元素都是int ** 型，这个指向指针的指针：） <br />　　　d不管怎样变终究也是个数组，呵呵， <br />　　　如果你读懂了上边的，那下边的声明就很简单了： <br />　　　d[0]=new int *[10]; <br />　　　d[1]=new int * [10]; <br />delete [] d[0]; <br />delete [] d[1]; <br /><br />二　：　函数指针　 <br /><br />关于函数指针，我想在我们可能需要写个函数，这个函数体内要调用另一个函数，可是由于项目的进度有限，我们不知道要调用什么样的函数，这个时候可能就需要一个函数指针； <br /><br />int a();这个一个函数的声明； <br />ing (*b)();这是一个函数指针的声明； <br />让我们来分析一下，左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型（void）和由边圆括弧中的入口参数（本例中参数是空）。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小： <br />unsigned psize = sizeof (int (*) ()); 获得函数指针的大小 <br />// 为函数指针声明类型定义 <br />typedef int (*PFUNC) (); <br /><br />PFUNC是一个函数指针，它指向的函数没有输入参数，返回int。使用这个类型定义名可以隐藏复杂的函数指针语法，就我本人强烈建议我们大内弟子使用这种方式来定义； <br /><br />下面是一个例子，一个简单函数指针的回调(在GNU编译器上通过，在VC上需要改变一个头文件就OK了） <br /><br />#include&lt;iostream&gt;              //GNU 编译器 g++ 实现 <br />using namespace std; <br />/*                              //vc 的实现 <br />#include "stdafx.h" <br />#include &lt;iostream.h&gt; <br />*/ <br /><br />#define DF(F) int F(){  cout&lt;&lt;"this is in function "&lt;&lt;#F&lt;&lt;endl;\ <br />      return 0;       \ <br />} <br />//声明定义DF(F)替代 int F()；函数； <br />DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g); DF(h); DF(i);     //声明定义函数 a b c d e f g h i <br /><br />// int (*pfunc)();              //一个简单函数指针的声明 <br />typedef int(*FUNC)();   //一个函数指针类型的声明 <br /><br />FUNC ff[] = {a,b,c,d,e,f,g,h,i};   //声明一个函数指针数组，并初始化为以上声明的a,b,c,d,e,f,g,h,i函数 <br /><br />FUNC func3(FUNC vv){    //定义函数func3，传入一个函数指针，并且返回一个同样类型的函数指针 <br />      vv(); <br />      return vv; <br />} <br /><br />/*FUNC func4(int (*vv)()){      //func3的另一种实现 <br />      vv(); <br />      return vv; <br />}*/ <br /><br />int main(){ <br />      for(int i=0;i&lt;sizeof(ff)/sizeof (FUNC);i++){  //循环调用函数指针 <br />              FUNC r=func3(ff[ i ]); <br />              cout&lt;&lt;r()&lt;&lt;endl;                //输出返回值，只是返回了0 <br />      } <br />      return 0; <br />} <br />到目前为止，我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。如在Visual C++中，可以在函数类型前加_cdecl，_stdcall或者_pascal来表示其调用规范（默认为_cdecl）。C++ Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名，参数传递的顺序（从右到左或从左到右），堆栈清理责任（调用者或者被调用者）以及参数传递机制（堆栈，CPU寄存器等）。 <br />好了，先到此为止吧，写这篇文章耗费了基本上快半天的时间了，很多事情还没有做，等改天有时间再回来整理，所有的源程序都放在openlab3服务器上我的目录下lib/cpp下，大家可以去拿。不知道的登陆openlab3 然后cd ~chengx/lib/cpp就可以看到了。 <br /><br />还有很复杂的声明可能也是一种挑战 比如&lt;&lt;Think in c++&gt;&gt;里的 <br />int (*(*f4())[10]();的声明,f4是一个返回指针的函数，该指针指向了含有10个函数指针的数组，这些函数返回整形值；不是这个函数有特别之处，而是Bruce Eckel 说的“从右到左的辨认规则”是一种很好的方法，值得我们去学习，感谢他：) <br /><br />最后我想应该跟大家说一下，写程序应该就象JERRY所说的：简单就是美；我们应该遵循一个原则 ： KISS （Keep It Simple,Stupid ,尽量保持程序简单 出自 ：《Practical C programming》），把自己的程序尽量的简单明了，这是个非常非常好的习惯。 <br /></p><img src ="http://www.blogjava.net/mlh123caoer/aggbug/82245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mlh123caoer/" target="_blank">草儿</a> 2006-11-20 14:05 <a href="http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言中的转义字符</title><link>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82243.html</link><dc:creator>草儿</dc:creator><author>草儿</author><pubDate>Mon, 20 Nov 2006 06:03:00 GMT</pubDate><guid>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82243.html</guid><wfw:comment>http://www.blogjava.net/mlh123caoer/comments/82243.html</wfw:comment><comments>http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82243.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mlh123caoer/comments/commentRss/82243.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mlh123caoer/services/trackbacks/82243.html</trackback:ping><description><![CDATA[<p>在windows自带的超级终端中,如何清屏? <br />--通过发送0x0C(12)即可实现清屏。<br />--在“输入字符串”内容中输入 /x0c</p>
		<p>\0  ：字符串结束标志；<br />\n  ：换行（ascⅱ码为10）；           <br />\t  ：横向跳格；                               <br />\b  ：退格；<br />\r  ：回车（ascⅱ码为13）；<br />\f  ：走纸换页；<br />\\  ：字符\（ascⅱ码为92）；           <br />\'  ：单引号；                                   <br />'\"'：双引号；<br />\d05：用8进制表示字符；<br />\x1c：用16进制表示字符.<br /><br /></p><img src ="http://www.blogjava.net/mlh123caoer/aggbug/82243.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mlh123caoer/" target="_blank">草儿</a> 2006-11-20 14:03 <a href="http://www.blogjava.net/mlh123caoer/archive/2006/11/20/82243.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>