﻿<?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>C++博客-C++学习交流</title><link>http://www.cppblog.com/wind/</link><description /><language>zh-cn</language><lastBuildDate>Mon, 06 Apr 2026 03:30:30 GMT</lastBuildDate><pubDate>Mon, 06 Apr 2026 03:30:30 GMT</pubDate><ttl>60</ttl><item><title>SHELL编程入门</title><link>http://www.cppblog.com/wind/archive/2009/05/22/85377.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Fri, 22 May 2009 05:43:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2009/05/22/85377.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/85377.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2009/05/22/85377.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/85377.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/85377.html</trackback:ping><description><![CDATA[<div class="navheader">
<table summary="Navigation header" width="100%">
    <tbody>
        <tr>
            <th colspan="3" align="center">1.5.&nbsp;开发优良脚本</th>
        </tr>
        <tr>
            <td align="left" width="20%"><a  href="http://xiaowang.net/bgb-cn/ch01s04.html" accesskey="p">上一页</a>&nbsp;
            </td>
            <th align="center" width="60%">第&nbsp;1&nbsp;章&nbsp;Bash和Bash脚本</th>
            <td align="right" width="20%">&nbsp;<a  href="http://xiaowang.net/bgb-cn/ch01s06.html" accesskey="n">下一页</a></td>
        </tr>
    </tbody>
</table>
<hr>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;"><a name="sect_01_05"></a>1.5.&nbsp;开发优良脚本
</h2>
</div>
</div>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="sect_01_05_01"></a>1.5.1.&nbsp;优良脚本的要素
</h3>
</div>
</div>
</div>
<p>本指南只要是关于上面的shell构成部分，脚本。在继续之前我们应该考虑一些东西：</p>
<div class="orderedlist">
<ol type="1">
    <li>
    <p>一个脚本应该无错运行。</p>
    </li>
    <li>
    <p>它应该完成他要完成的任务。</p>
    </li>
    <li>
    <p>程序的逻辑结构定义清晰而且明显。</p>
    </li>
    <li>
    <p>一个脚本不做不必要的工作。</p>
    </li>
    <li>
    <p>脚本可以重用。</p>
    </li>
</ol>
</div>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="sect_01_05_02"></a>1.5.2.&nbsp;结构
</h3>
</div>
</div>
</div>
<p>shell脚本的结构非常具有灵活性。即使在Bash中有很大的自由度，你必须保证正确的逻辑，流控制和效率，这样，用户才能执行脚本能做到简单和正确。</p>
<p>当开始一个新的脚本的时候，问自己以下几个问题：</p>
<div class="itemizedlist">
<ul type="disc">
    <li>
    <p>需要从用户或者用户环境来取得任何信息吗？</p>
    </li>
    <li>
    <p>怎么样来存放那些信息？</p>
    </li>
    <li>
    <p>需要创建文件吗？哪里和文件需要拥有什么样的权限和所有权？</p>
    </li>
    <li>
    <p>我将用到什么命令？当在一个不同的系统使用脚本的时候，所有这些系统在要求的版本下有这些命令吗？</p>
    </li>
    <li>
    <p>用户需要什么提示吗？什么时候和为什么？</p>
    </li>
</ul>
</div>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="sect_01_05_03"></a>1.5.3.&nbsp;术语
</h3>
</div>
</div>
</div>
<p>下表给出了你需要熟悉的编程条款的概览：</p>
<div class="table"><a name="table_01_01"></a>
<p class="title"><strong>表&nbsp;1.1.&nbsp;编程条款的概览</strong></p>
<table summary="编程条款的概览" style="border: 0.5pt solid ; border-collapse: collapse;" border="0">
    <colgroup>
    <col width="50%">
    <col width="50%">
    </colgroup>
    <thead>
        <tr>
            <th style="border-right: 0.5pt solid; border-bottom: 0.5pt solid;" align="left">术语</th>
            <th style="border-bottom: 0.5pt solid;" align="left">含义</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td style="border-right: 0.5pt solid; border-bottom: 0.5pt solid;" align="left">命令控制</td>
            <td style="border-bottom: 0.5pt solid;" align="left">测试一个命令的退出状态来决定应该执行哪部分的程序。</td>
        </tr>
        <tr>
            <td style="border-right: 0.5pt solid; border-bottom: 0.5pt solid;" align="left">条件分支</td>
            <td style="border-bottom: 0.5pt solid;" align="left">在程序中条件决定接下来该怎么办的逻辑点。</td>
        </tr>
        <tr>
            <td style="border-right: 0.5pt solid; border-bottom: 0.5pt solid;" align="left">逻辑流程</td>
            <td style="border-bottom: 0.5pt solid;" align="left">程序的总体设计。决定任务的逻辑顺序，使得结果是成功的且是可以控制的。</td>
        </tr>
        <tr>
            <td style="border-right: 0.5pt solid; border-bottom: 0.5pt solid;" align="left">循环</td>
            <td style="border-bottom: 0.5pt solid;" align="left">程序执行0次或者多次的部分。</td>
        </tr>
        <tr>
            <td style="border-right: 0.5pt solid;" align="left">用户输入</td>
            <td align="left">程序运行的时候外部源提供的信息，可以在需要的被存储和回调。</td>
        </tr>
    </tbody>
</table>
</div>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="sect_01_05_04"></a>1.5.4.&nbsp;关于顺序和逻辑
</h3>
</div>
</div>
</div>
<p>为了加速开发的进程，程序的逻辑顺序应该在实现思考好。这是你开发脚本的第一步。</p>
<p>由很多方法可以使用；最常用的就是使用列表。逐条列记和一个程序相关的任务列表允许你描述每个进程。单个任务可以用他们的项目编号来引用。</p>
<p>使用你自己的口语来制定你的程序会执行的任务将帮助你建立易于理解的框架。之后，你可以用shell语言和结构来替换它们。</p>
<p>下面的例子现实了这样一个逻辑流程设计。描述了日志文件的轮换。例子显示了一个可能的重复循环，以你想轮换的基本日志文件的数量来控制：</p>
<div class="orderedlist">
<ol type="1">
    <li>
    <p>Do you want to rotate logs?</p>
    <div class="orderedlist">
    <ol type="a">
        <li>
        <p>If yes:</p>
        <div class="orderedlist">
        <ol type="i">
            <li>
            <p>Enter directory name containing the logs to be rotated.</p>
            </li>
            <li>
            <p>Enter base name of the log file.</p>
            </li>
            <li>
            <p>Enter number of days logs should be kept.</p>
            </li>
            <li>
            <p>Make settings permanent in user's crontab file.</p>
            </li>
        </ol>
        </div>
        </li>
        <li>
        <p>If no, go to step 3.</p>
        </li>
    </ol>
    </div>
    </li>
    <li>
    <p>Do you want to rotate another set of logs?</p>
    <div class="orderedlist">
    <ol type="a">
        <li>
        <p>If yes: repeat step 1.</p>
        </li>
        <li>
        <p>If no: go to step 3.</p>
        </li>
    </ol>
    </div>
    </li>
    <li>
    <p>Exit</p>
    </li>
</ol>
</div>
<p>用户应该提供信息给程序来运行。必须得到并储存来自用户的输入。用户应该注意到她的crontab会发生改变。</p>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="sect_01_05_05"></a>1.5.5.&nbsp;一个Bash脚本的例子：mysystem.sh
</h3>
</div>
</div>
</div>
<p><code class="filename">mysystem.sh</code> 脚本执行了一些熟悉的命令，(<span><strong class="command">date</strong></span>, <span><strong class="command">w</strong></span>, <span><strong class="command">uname</strong></span>, <span><strong class="command">uptime</strong></span>) 来显示你和你机器的信息。
</p>
<pre class="screen"><code class="prompt">tom:~&gt;</code> <span><strong class="command">cat <code class="option">-n</code> <code class="filename">mysystem.sh</code></strong></span><br>     1  #!/bin/bash<br>     2  clear<br>     3  echo "This is information provided by mysystem.sh.  Program starts now."<br>     4<br>     5  echo "Hello, $USER"<br>     6  echo<br>     7<br>     8  echo "Today's date is `date`, this is week `date +"%V"`."<br>     9  echo<br>    10<br>    11  echo "These users are currently connected:"<br>    12  w | cut -d " " -f 1 - | grep -v USER | sort -u<br>    13  echo<br>    14<br>    15  echo "This is `uname -s` running on a `uname -m` processor."<br>    16  echo<br>    17<br>    18  echo "This is the uptime information:"<br>    19  uptime<br>    20  echo<br>    21<br>    22  echo "That's all folks!"<br></pre>
<p>脚本总是以相同的2个字符开始，&#8220;<span class="quote">#!</span>&#8221;。之后，shell会执行定义在第一
行之后的命令。脚本在第1行清除屏幕内容。第2行打印一条语句，通知用户将要发生的事情。第5行问候用户。第6，9，13，16和20行是为了按顺序输出
显示。第8行打印了当前的日期和周数。第11行市又一个提示信息，和第3，8，22行一样。第12行格式化 <span><strong class="command">w</strong></span> 的输出；第15行显示了操作系统和CPU信息。第19行给出了uptime和load信息。
</p>
<p><span><strong class="command">echo</strong></span> 和 <span><strong class="command">printf</strong></span> 都是Bash内建命令。第一个总是以状态0退出，且简单地把参数在标准输出打印出来，而后者允许定义一个格式化字符串且在失败后返回一个非零的退出状态。
</p>
<p>这是一个相同的使用 <span><strong class="command">printf</strong></span> 内建命令的脚本：
</p>
<pre class="screen"><code class="prompt">tom:~&gt;</code> <span><strong class="command">cat <code class="filename">mysystem.sh</code></strong></span><br>#!/bin/bash<br>clear<br>printf "This is information provided by mysystem.sh.  Program starts now."<br><br>printf "Hello, $USER.\n\n"<br><br>printf "Today's date is `date`, this is week `date +"%V"`.\n\n"<br><br>printf "These users are currently connected:\n"<br>w | cut -d " " -f 1 - | grep -v USER | sort -u<br>printf "\n"<br><br>printf "This is `uname -s` running on a `uname -m` processor.\n\n"<br><br>printf "This is the uptime information:\n"<br>uptime<br>printf "\n"<br><br>printf "That's all folks!\n"<br></pre>
<p>依靠插入信息来建立友好的脚本将在 <a  href="http://xiaowang.net/bgb-cn/ch08.html" title="第&nbsp;8&nbsp;章&nbsp;编写交互脚本">第&nbsp;8&nbsp;章 <em>编写交互脚本</em></a> 详细讲解。
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<table summary="Note: bourne again shell的标准位置" border="0">
    <tbody>
        <tr>
            <td rowspan="2" align="center" valign="top" width="25"><img  src="http://xiaowang.net/bgb-cn/images/note.png" alt="[注意]"></td>
            <th align="left">Bourne Again shell的标准位置</th>
        </tr>
        <tr>
            <td align="left" valign="top">
            <p>意味着 <span><strong class="command">bash</strong></span> 程序安装在 <code class="filename">/bin</code>。
            </p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
<table summary="Warning: 如果stdout不存在" border="0">
    <tbody>
        <tr>
            <td rowspan="2" align="center" valign="top" width="25"><img  src="http://xiaowang.net/bgb-cn/images/warning.png" alt="[警告]"></td>
            <th align="left">如果stdout不存在</th>
        </tr>
        <tr>
            <td align="left" valign="top">
            <p>如果你从cron执行脚本，提供完整的路径名字和重定向输出和错误。既然shell在非交互模式运行，如果你考虑这些任何错误将导致脚本过早的退出。</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>以下章节将会具体讨论上面的脚本。</p>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="sect_01_05_06"></a>1.5.6.&nbsp;init脚本例子
</h3>
</div>
</div>
</div>
<p>一个init脚本启动在UNIX和Linux机器上的系统服务。通常例子有系统日志守护程序，电源管理守护程序，名字和邮件守护程序。这些脚本，也被称作启动脚本，存储在系统的特定位置，比如 <code class="filename">/etc/rc.d/init.d</code> 或者 <code class="filename">/etc/init.d</code>。Init，初始化进程，读取它的配置文件来决定在某些运行等级哪些服务来启动或者停止，比如，为了进行管理任务，系统要尽可能设置成非使用状态，比如从备份中恢复一个危急的文件系统。重启动和关闭的运行等级通常也是配置好的。
</p>
<p>在启动一个服务或者停止它的时候需要执行的任务纪录在启动脚本中。配置 <span><strong class="command">init</strong></span> 是系统管理员的一项任务，由此服务可以在正确的时刻运行和停止。当面临这样的任务，你需要对你系统的启动和停止程序有着良好的理解。我们因此建议在开始着手你的初始化脚本之前阅读 <span><strong class="command">init</strong></span> 和 <code class="filename">inittab</code> 的man页面。
</p>
<p>这里是一个很简单的例子，当起动和关闭你的机器的时候会播放一个声音：</p>
<pre class="screen">#!/bin/bash<br><br># This script is for /etc/rc.d/init.d<br># Link in rc3.d/S99audio-greeting and rc0.d/K01audio-greeting<br><br>case "$1" in<br>'start')<br>  cat /usr/share/audio/at_your_service.au &gt; /dev/audio<br>  ;;<br>'stop')<br>  cat /usr/share/audio/oh_no_not_again.au &gt; /dev/audio<br>  ;;<br>esac<br>exit 0<br></pre>
<p><span><strong class="command">case</strong></span> 语句经常使用在这类脚本当中，在<a  href="http://xiaowang.net/bgb-cn/ch07s02.html#sect_07_02_05" title="7.2.5.&nbsp;使用exit语句和if">第&nbsp;7.2.5&nbsp;节 &#8220;使用exit语句和if&#8221;</a>中会解释。
</p>
</div>
</div>
<div class="navfooter">
<hr>
<table summary="Navigation footer" width="100%">
    <tbody>
        <tr>
            <td align="left" width="40%"><a  href="http://xiaowang.net/bgb-cn/ch01s04.html" accesskey="p">上一页</a>&nbsp;
            </td>
            <td align="center" width="20%"><a  href="http://xiaowang.net/bgb-cn/ch01.html" accesskey="u">上一级</a></td>
            <td align="right" width="40%">&nbsp;<a  href="http://xiaowang.net/bgb-cn/ch01s06.html" accesskey="n">下一页</a></td>
        </tr>
        <tr>
            <td align="left" valign="top" width="40%">1.4.&nbsp;建立块&nbsp;</td>
            <td align="center" width="20%"><a  href="http://xiaowang.net/bgb-cn/index.html" accesskey="h">起始页</a></td>
            <td align="right" valign="top" width="40%">&nbsp;1.6.&nbsp;总结</td>
        </tr>
    </tbody>
</table>
</div><img src ="http://www.cppblog.com/wind/aggbug/85377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2009-05-22 13:43 <a href="http://www.cppblog.com/wind/archive/2009/05/22/85377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>配置Java开发环境</title><link>http://www.cppblog.com/wind/archive/2009/04/10/79521.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Fri, 10 Apr 2009 09:10:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2009/04/10/79521.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/79521.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2009/04/10/79521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/79521.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/79521.html</trackback:ping><description><![CDATA[第一步：下载J2SDK和Tomcat：<br>J2SDK：到sun官方站（<a href="http://java.sun.com/j2se/1.5.0/download.jsp" target=_blank><u><font color=#0000ff>http://java.sun.com/j2se/1.5.0/download.jsp</font></u></a>）下载j2sdk， 注意下载版本为Windows Offline Installation的SDK，同时最好下载J2SE 1.5.0 Documentation，下载J2EE API Documentaition .<br>Tomcat：到tomcat官方站点 （<a href="http://tomcat.apache.org/download-60.cgi"><u><font color=#0000ff>http://tomcat.apache.org/download-60.cgi</font></u></a>）下载tomcat(apache-tomcat-6.0.18)。 <br><br>第二步：安装和配置J2SDK和Tomcat：执行j2sdk和tomcat的安装程序，然后按默认设置进行安装即可。 <br>1.安装J2SDK以后，需要配置一下环境变量，在我的电脑-&gt;属性-&gt;高级-&gt;环境变量-&gt;系统变量中添加以下环境变量 (假定你的J2SDK安装在c:\j2sdk1.5.0）： <br>JAVA_HOME=C:\Program Files\Java\jdk1.5.0_05<br>classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;（.;一定不能少，因为它代表当前路径) path=%JAVA_HOME%\bin <br>测试J2SDK是否装成功:运行-cmd-(分别输入javac/java/java -version),看是否有相应信息出现。<br>2.安装Tomcat后，在我的电脑-&gt;属性-&gt;高级-&gt;环境变量-&gt;系统变量中添加以下环境变量(假定你的tomcat安装在E:\javaSoft\apache-tomcat-6.0.14)： <br>TOMCAT_HOME：E:\javaSoft\apache-tomcat-6.0.14<br>然后修改环境变量中的classpath，修改后的classpath如下： <br>classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%TOMCAT_HOME%\lib\servlet-api.jar 接着可以启动tomcat，在IE中访问<a href="http://localhost:8080/" target=_blank><u><font color=#0000ff>http://localhost:8080/</font></u></a>，如果看到tomcat的欢迎页面的话说明安装成功了。(免安装版，用bin目录中的startup.bat启动) <br>path:windows系统执行命令时要搜寻的路径<br>classpath:java在编译和运行时要找的class所在的路径<br><br>第三步：建立自己的jsp app目录 <br>1.到Tomcat的安装目录的webapps目录，可以看到ROOT，examples, tomcat-docs之类Tomcat自带的的目录； <br>2.在webapps目录下新建一个目录，起名叫myapp； <br>3.myapp下新建一个目录WEB-INF，注意，目录名称是区分大小写的； <br>4.WEB-INF下新建一个文件web.xml，内容如下： <br>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; <br>&lt;!DOCTYPE web-app <br>PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target=_blank><u><font color=#0000ff>http://java.sun.com/dtd/web-app_2_3.dtd</font></u></a>"&gt; <br>&lt;web-app&gt; <br>&nbsp;&nbsp; &lt;display-name&gt;My Web Application&lt;/display-name&gt; <br>&nbsp;&nbsp; &lt;description&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A application for test. <br>&nbsp;&nbsp; &lt;/description&gt; <br>&lt;/web-app&gt; <br>5.在myapp下新建一个测试的jsp页面，文件名为index.jsp，文件内容如下： <br>&lt;html&gt;&lt;body&gt;&lt;center&gt; <br>Now time is: &lt;%=new java.util.Date()%&gt; <br>&lt;/center&gt;&lt;/body&gt;&lt;/html&gt; <br>6.重启Tomcat <br>7.打开浏览器，输入<a href="http://localhost:8080/myapp/index.jsp" target=_blank><u><font color=#0000ff>http://localhost:8080/myapp/index.jsp</font></u></a> 看到当前时间的话说明就成功了。 <br><br>第四步：建立自己的Servlet： <br>1.新建一个servlet程序，文件名为Test.java，文件内容如下： <br>package test; <br>import java.io.IOException; <br>import java.io.PrintWriter; <br>import javax.servlet.ServletException; <br>import javax.servlet.http.HttpServlet; <br>import javax.servlet.http.HttpServletRequest; <br>import javax.servlet.http.HttpServletResponse; <br>public class Test extends HttpServlet { <br>protected void doGet(HttpServletRequest request, HttpServletResponse response) <br>throws ServletException, IOException { <br>PrintWriter out=response.getWriter(); <br>out.println("&lt;html&gt;&lt;body&gt;&lt;h1&gt;This is a servlet test.&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;"); <br>out.flush(); <br>} <br>} <br>2 .编译 <br>将Test.java使用如下命令编译： <br>C:\Test&gt;javac Test.java <br>然后在c:\Test下会产生一个编译后的servlet文件：Test.class <br>3 .将结构test\Test.class剪切到%TOMCAT_HOME%\webapps\myapp\WEB-INF\classes下， 也就是剪切那个test目录到classes目录下，如果classes目录不存在，就新建一个。 现在webapps\myapp\WEB-INF\classes下有test\Test.class的文件目录结构. <br>4 .修改webapps\myapp\WEB-INF\web.xml，添加servlet和servlet-mapping <br>编辑后的web.xml如下所示:<br>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; <br>&lt;!DOCTYPE web-app <br>PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" <br>"<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target=_blank><u><font color=#0000ff>http://java.sun.com/dtd/web-app_2_3.dtd</font></u></a>"&gt; <br>&lt;web-app&gt; <br>&nbsp;&nbsp; &lt;display-name&gt;My Web Application&lt;/display-name&gt; <br>&nbsp;&nbsp; &lt;description&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp; A application for test. <br>&nbsp;&nbsp; &lt;/description&gt; <br>&lt;servlet&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;Test&lt;/servlet-name&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;display-name&gt;Test&lt;/display-name&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;A test Servlet&lt;/description&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;test.Test&lt;/servlet-class&gt; <br>&lt;/servlet&gt; <br>&lt;servlet-mapping&gt; <br>&nbsp;&nbsp; &lt;servlet-name&gt;Test&lt;/servlet-name&gt; <br>&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/Test&lt;/url-pattern&gt; <br>&lt;/servlet-mapping&gt; <br>&lt;/web-app&gt; <br>这段话中的servlet这一段声明了你要调用的Servlet，而servlet-mapping则是将声明的servlet"映射"到地址/Test上 <br>5 .重启动Tomcat，启动浏览器，输入<a href="http://localhost:8080/myapp/Test" target=_blank><u><font color=#0000ff>http://localhost:8080/myapp/Test</font></u></a> 如果看到输出This is a servlet test. <br>就说明编写的servlet成功了。 <br>注意：修改了web.xml以及新加了class，都要重启Tomcat <br><br>第四步：建立自己的Bean： <br>1.新建一个java程序，文件名为TestBean.java，文件内容如下： <br>package test;<br>public class TestBean{ <br>private String name = null; <br>public TestBean(String strName_p){ <br>this.name=strName_p; <br>} <br>public void setName(String strName_p){ <br>this.name=strName_p; <br>} <br>public String getName(){ <br>return this.name; <br>} <br>} <br><br>2 .编译 <br>将TestBean.java放在c:\test下，使用如下命令编译： <br>C:\Test&gt;javac TestBean.java <br>然后在c:\Test下会产生一个编译后的bean文件：TestBean.class <br>3 .将TestBean.class文件剪切到 %TOMCAT_HOME%\webapps\myapp\WEB-INF\classes\test下， <br>4 .新建一个TestBean.jsp文件，文件内容为： <br>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;"><u><font color=#0000ff>%@page</font></u></a> import="test.TestBean"%&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br>&lt;html&gt;&lt;body&gt;&lt;center&gt; <br>&lt;% <br>TestBean testBean=new TestBean("This is a test java bean."); <br>%&gt; <br>Java bean name is: &lt;%=testBean.getName()%&gt; <br>&lt;/center&gt;&lt;/body&gt;&lt;/html&gt; <br>5 .重启Tomcat，启动浏览器，输入<a href="http://localhost:8080/myapp/TestBean.jsp" target=_blank><u><font color=#0000ff>http://localhost:8080/myapp/TestBean.jsp</font></u></a> 如果看到输出 <br>Java bean name is: This is a test java bean.就说明编写的Bean成功了。<img src ="http://www.cppblog.com/wind/aggbug/79521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2009-04-10 17:10 <a href="http://www.cppblog.com/wind/archive/2009/04/10/79521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库基础</title><link>http://www.cppblog.com/wind/archive/2009/02/02/72799.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Mon, 02 Feb 2009 05:50:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2009/02/02/72799.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/72799.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2009/02/02/72799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/72799.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/72799.html</trackback:ping><description><![CDATA[<p>asc 按升序排列<br>desc 按降序排列</p>
<p>下列语句部分是Mssql语句，不可以在access中使用。</p>
<p>SQL分类： <br>DDL—数据定义语言(Create，Alter，Drop，DECLARE) <br>DML—数据操纵语言(Select，Delete，Update，Insert) <br>DCL—数据控制语言(GRANT，REVOKE，COMMIT，ROLLBACK)</p>
<p>首先,简要介绍基础语句：<br>1、说明：创建数据库<br>Create DATABASE database-name <br>2、说明：删除数据库<br>drop database dbname<br>3、说明：备份sql server<br>--- 创建 备份数据的 device<br>USE master<br>EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'<br>--- 开始 备份<br>BACKUP DATABASE pubs TO testBack <br>4、说明：创建新表<br>create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)<br>根据已有的表创建新表： <br>A：create table tab_new like tab_old (使用旧表创建新表)<br>B：create table tab_new as select col1,col2&#8230; from tab_old definition only<br>5、说明：删除新表drop table tabname <br>6、说明：增加一个列<br>Alter table tabname add column col type<br>注：列增加后将不能删除。DB2中列加上后数据类型也不能改变，唯一能改变的是增加varchar类型的长度。<br>7、说明：添加主键： Alter table tabname add primary key(col) <br>说明：删除主键： Alter table tabname drop primary key(col) <br>8、说明：创建索引：create [unique] index idxname on tabname(col&#8230;.) <br>删除索引：drop index idxname<br>注：索引是不可更改的，想更改必须删除重新建。<br>9、说明：创建视图：create view viewname as select statement <br>删除视图：drop view viewname<br>10、说明：几个简单的基本的sql语句<br>选择：select * from table1 where 范围<br>插入：insert into table1(field1,field2) values(value1,value2)<br>删除：delete from table1 where 范围<br>更新：update table1 set field1=value1 where 范围<br>查找：select * from table1 where field1 like &#8217;%value1%&#8217; ---like的语法很精妙，查资料!<br>排序：select * from table1 order by field1,field2 [desc]<br>总数：select count as totalcount from table1<br>求和：select sum(field1) as sumvalue from table1<br>平均：select avg(field1) as avgvalue from table1<br>最大：select max(field1) as maxvalue from table1<br>最小：select min(field1) as minvalue from table1<br>11、说明：几个高级查询运算词<br>A： UNION 运算符 <br>UNION 运算符通过组合其他两个结果表（例如 TABLE1 和 TABLE2）并消去表中任何重复行而派生出一个结果表。当 ALL 随 UNION 一起使用时（即 UNION ALL），不消除重复行。两种情况下，派生表的每一行不是来自 TABLE1 就是来自 TABLE2。 <br>B： EXCEPT 运算符 <br>EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随 EXCEPT 一起使用时 (EXCEPT ALL)，不消除重复行。 <br>C： INTERSECT 运算符<br>INTERSECT 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL 随 INTERSECT 一起使用时 (INTERSECT ALL)，不消除重复行。 <br>注：使用运算词的几个查询结果行必须是一致的。 <br>12、说明：使用外连接 <br>A、left outer join： <br>左外连接（左连接）：结果集几包括连接表的匹配行，也包括左连接表的所有行。 <br>sql: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c<br>B：right outer join: <br>右外连接(右连接)：结果集既包括连接表的匹配连接行，也包括右连接表的所有行。 <br>C：full outer join： <br>全外连接：不仅包括符号连接表的匹配行，还包括两个连接表中的所有记录。</p>
<p>其次，大家来看一些不错的sql语句<br>1、说明：复制表(只复制结构,源表名：a 新表名：b) (Access可用)</p>
<p>法一：select * into b from a where 1&lt;&gt;1<br>法二：select top 0 * into b from a<br>2、说明：拷贝表(拷贝数据,源表名：a 目标表名：b) (Access可用)<br>insert into b(a, b, c) select d,e,f from b;</p>
<p>3、说明：跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)<br>insert into b(a, b, c) select d,e,f from b in &#8216;具体数据库&#8217; where 条件<br>例子：..from b in '"&amp;Server.MapPath(".")&amp;"\data.mdb" &amp;"' where..</p>
<p>4、说明：子查询(表名1：a 表名2：b)<br>select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3)</p>
<p>5、说明：显示文章、提交人和最后回复时间<br>select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b</p>
<p>6、说明：外连接查询(表名1：a 表名2：b)<br>select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c</p>
<p>7、说明：在线视图查询(表名1：a )<br>select * from (Select a,b,c FROM a) T where t.a &gt; 1;</p>
<p>8、说明：between的用法,between限制查询数据范围时包括了边界值,not between不包括<br>select * from table1 where time between time1 and time2<br>select a,b,c, from table1 where a not between 数值1 and 数值2</p>
<p>9、说明：in 的使用方法<br>select * from table1 where a [not] in (&#8216;值1&#8217;,&#8217;值2&#8217;,&#8217;值4&#8217;,&#8217;值6&#8217;)</p>
<p>10、说明：两张关联表，删除主表中已经在副表中没有的信息 <br>delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )</p>
<p>11、说明：四表联查问题：<br>select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....</p>
<p>12、说明：日程安排提前五分钟提醒 <br>sql: select * from 日程安排 where datediff('minute',f开始时间,getdate())&gt;5</p>
<p>13、说明：一条sql 语句搞定数据库分页<br>select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段</p>
<p>14、说明：前10条记录<br>select top 10 * form table1 where 范围</p>
<p>15、说明：选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)<br>select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)</p>
<p>16、说明：包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表<br>(select a from tableA ) except (select a from tableB) except (select a from tableC)</p>
<p>17、说明：随机取出10条数据<br>select top 10 * from tablename order by newid()</p>
<p>18、说明：随机选择记录<br>select newid()</p>
<p>19、说明：删除重复记录<br>Delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)</p>
<p>20、说明：列出数据库里所有的表名<br>select name from sysobjects where type='U' </p>
<p>21、说明：列出表里的所有的<br>select name from syscolumns where id=object_id('TableName')</p>
<p>22、说明：列示type、vender、pcs字段，以type字段排列，case可以方便地实现多重选择，类似select 中的case。<br>select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type<br>显示结果：<br>type vender pcs<br>电脑 A 1<br>电脑 A 1<br>光盘 B 2<br>光盘 A 2<br>手机 B 3<br>手机 C 3</p>
<p>23、说明：初始化表table1</p>
<p>TRUNCATE TABLE table1</p>
<p>24、说明：选择从10到15的记录<br>select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc<br>　　<br>随机选择数据库记录的方法（使用Randomize函数，通过SQL语句实现）<br>　　对存储在数据库中的数据来说，随机数特性能给出上面的效果，但它们可能太慢了些。你不能要求ASP&#8220;找个随机数&#8221;然后打印出来。实际上常见的解决方案是建立如下所示的循环： <br>Randomize <br>RNumber = Int(Rnd*499) +1 <br>　<br>While Not objRec.EOF <br>If objRec("ID") = RNumber THEN <br>... 这里是执行脚本 ... <br>end if <br>objRec.MoveNext <br>Wend <br>　<br>　　这很容易理解。首先，你取出1到500范围之内的一个随机数（假设500就是数据库内记录的总数）。然后，你遍历每一记录来测试ID 的值、检查其是否匹配RNumber。满足条件的话就执行由THEN 关键字开始的那一块代码。假如你的RNumber 等于495，那么要循环一遍数据库花的时间可就长了。虽然500这个数字看起来大了些，但相比更为稳固的企业解决方案这还是个小型数据库了，后者通常在一个数据库内就包含了成千上万条记录。这时候不就死定了？ <br>　　采用SQL，你就可以很快地找出准确的记录并且打开一个只包含该记录的recordset，如下所示： <br>Randomize <br>RNumber = Int(Rnd*499) + 1 <br>　<br>sql = "Select * FROM Customers Where ID = " &amp; RNumber <br>　<br>set objRec = ObjConn.Execute(SQL) <br>Response.WriteRNumber &amp; " = " &amp; objRec("ID") &amp; " " &amp; objRec("c_email") <br>　<br>　　不必写出RNumber 和ID，你只需要检查匹配情况即可。只要你对以上代码的工作满意，你自可按需操作&#8220;随机&#8221;记录。Recordset没有包含其他内容，因此你很快就能找到你需要的记录这样就大大降低了处理时间。 <br>再谈随机数 <br>　　现在你下定决心要榨干Random 函数的最后一滴油，那么你可能会一次取出多条随机记录或者想采用一定随机范围内的记录。把上面的标准Random 示例扩展一下就可以用SQL应对上面两种情况了。 <br>　　为了取出几条随机选择的记录并存放在同一recordset内，你可以存储三个随机数，然后查询数据库获得匹配这些数字的记录： <br>sql = "Select * FROM Customers Where ID = " &amp; RNumber &amp; " or ID = " &amp; RNumber2 &amp; " or ID = " &amp; RNumber3 <br>　<br>　　假如你想选出10条记录（也许是每次页面装载时的10条链接的列表），你可以用BETWEEN 或者数学等式选出第一条记录和适当数量的递增记录。这一操作可以通过好几种方式来完成，但是 Select 语句只显示一种可能（这里的ID 是自动生成的号码）： <br>sql = "Select * FROM Customers Where ID BETWEEN " &amp; RNumber &amp; " AND " &amp; RNumber &amp; "+ 9" </p>
<p>　　注意：以上代码的执行目的不是检查数据库内是否有9条并发记录。</p>
<p>　<br>随机读取若干条记录，测试过<br>Access语法：Select top 10 * From 表名 orDER BY Rnd(id)<br>sql server:select top n * from 表名 order by newid()<br>mysqlelect * From 表名 order By rand() Limit n<br>Access左连接语法(最近开发要用左连接,Access帮助什么都没有,网上没有Access的SQL说明,只有自己测试, 现在记下以备后查)<br>语法elect table1.fd1,table1,fd2,table2.fd2 From table1 left join table2 on table1.fd1,table2.fd1 where ...<br>使用SQL语句 用...代替过长的字符串显示<br>语法：<br>SQL数据库：select case when len(field)&gt;10 then left(field,10)+'...' else field end as news_name,news_id from tablename<br>Access数据库：Select iif(len(field)&gt;2,left(field,2)+'...',field) FROM tablename; <br>　<br>Conn.Execute说明<br>Execute方法<br>　　该方法用于执行SQL语句。根据SQL语句执行后是否返回记录集，该方法的使用格式分为以下两种：</p>
<p>1．执行SQL查询语句时，将返回查询得到的记录集。用法为：<br>　　　　Set 对象变量名=连接对象.Execute("SQL 查询语言")<br>　　　Execute方法调用后，会自动创建记录集对象，并将查询结果存储在该记录对象中，通过Set方法，将记录集赋给指定的对象保存，以后对象变量就代表了该记录集对象。</p>
<p>　　　　2．执行SQL的操作性语言时，没有记录集的返回。此时用法为：<br>　　　　连接对象.Execute "SQL 操作性语句" [, RecordAffected][, Option]<br>　　　　　　&#183;RecordAffected 为可选项，此出可放置一个变量，SQL语句执行后，所生效的记录数会自动保存到该变量中。通过访问该变量，就可知道SQL语句队多少条记录进行了操作。<br>　　　　　　&#183;Option 可选项，该参数的取值通常为adCMDText，它用于告诉ADO，应该将Execute方法之后的第一个字符解释为命令文本。通过指定该参数，可使执行更高效。</p>
<p>&#183;BeginTrans、RollbackTrans、CommitTrans方法<br>　　这三个方法是连接对象提供的用于事务处理的方法。BeginTrans用于开始一个事物；RollbackTrans用于回滚事务；CommitTrans用于提交所有的事务处理结果，即确认事务的处理。<br>　　事务处理可以将一组操作视为一个整体，只有全部语句都成功执行后，事务处理才算成功；若其中有一个语句执行失败，则整个处理就算失败，并恢复到处里前的状态。<br>　　BeginTrans和CommitTrans用于标记事务的开始和结束，在这两个之间的语句，就是作为事务处理的语句。判断事务处理是否成功，可通过连接对象的Error集合来实现，若Error集合的成员个数不为0，则说明有错误发生，事务处理失败。Error集合中的每一个Error对象，代表一个错误信息</p><img src ="http://www.cppblog.com/wind/aggbug/72799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2009-02-02 13:50 <a href="http://www.cppblog.com/wind/archive/2009/02/02/72799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>回调函数</title><link>http://www.cppblog.com/wind/archive/2008/12/05/68630.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Fri, 05 Dec 2008 03:04:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/12/05/68630.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/68630.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/12/05/68630.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/68630.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/68630.html</trackback:ping><description><![CDATA[&nbsp;
<p><span>回</span><span>调</span><span>函数</span></p>
<p><span>2007</span><span>年</span><span>05</span><span>月</span><span>27</span><span>日</span> <span>星期日</span><span> 16:07</span></p>
<table cellPadding=0 border=0>
    <tbody>
        <tr>
            <td>
            <p><span>简</span><span>介</span><span><br><br></span><span>　　</span><span>对</span><span>于很多初学者来</span><span>说</span><span>，往往</span><span>觉</span><span>得回</span><span>调</span><span>函数很神秘，很想知道回</span><span>调</span><span>函数的工作原理。本文将要解</span><span>释</span><span>什</span><span>么</span><span>是回</span><span>调</span><span>函数、它</span><span>们</span><span>有什</span><span>么</span><span>好</span><span>处</span><span>、</span><span>为</span><span>什</span><span>么</span><span>要使用它</span><span>们</span><span>等等</span><span>问题</span><span>，在</span><span>开</span><span>始之前，假</span><span>设</span><span>你已</span><span>经</span><span>熟知了函数指</span><span>针</span><span>。</span><span> <br><br></span><span>　　什</span><span>么</span><span>是回</span><span>调</span><span>函数？</span><span><br><br></span><span>　　</span><span>简</span><span>而言之，回</span><span>调</span><span>函数就是一个通</span><span>过</span><span>函数指</span><span>针调</span><span>用的函数。如果你把函数的指</span><span>针</span><span>（地址）作</span><span>为</span><span>参数</span><span>传递给</span><span>另一个函数，当</span><span>这</span><span>个指</span><span>针</span><span>被用</span><span>为调</span><span>用它所指向的函数</span><span>时</span><span>，我</span><span>们</span><span>就</span><span>说这</span><span>是回</span><span>调</span><span>函数。</span><span><br><br></span><span>　　</span><span>为</span><span>什</span><span>么</span><span>要使用回</span><span>调</span><span>函数？</span><span><br><br></span><span>　　因</span><span>为</span><span>可以把</span><span>调</span><span>用者与被</span><span>调</span><span>用者分</span><span>开</span><span>。</span><span>调</span><span>用者不</span><span>关</span><span>心</span><span>谁</span><span>是被</span><span>调</span><span>用者，所有它需知道的，只是存在一个具有某</span><span>种</span><span>特定原型、某些限制条件（如返回</span><span>值为</span><span>int</span><span>）的被</span><span>调</span><span>用函数。</span><span><br><br></span><span>　　如果想知道回</span><span>调</span><span>函数在</span><span>实际</span><span>中有什</span><span>么</span><span>作用，先假</span><span>设</span><span>有</span><span>这样</span><span>一</span><span>种</span><span>情况，我</span><span>们</span><span>要</span><span>编</span><span>写一个</span><span>库</span><span>，它提供了某些排序算法的</span><span>实现</span><span>，如冒泡排序、快速排序、</span><span>shell</span><span>排序、</span><span>shake</span><span>排序等等，但</span><span>为</span><span>使</span><span>库</span><span>更加通用，不想在函数中嵌入排序</span><span>逻辑</span><span>，而</span><span>让</span><span>使用者来</span><span>实现</span><span>相</span><span>应</span><span>的</span><span>逻辑</span><span>；或者，想</span><span>让库</span><span>可用于多</span><span>种</span><span>数据</span><span>类</span><span>型（</span><span>int</span><span>、</span><span>float</span><span>、</span><span>string</span><span>），此</span><span>时</span><span>，</span><span>该</span><span>怎</span><span>么办</span><span>呢？可以使用函数指</span><span>针</span><span>，并</span><span>进</span><span>行回</span><span>调</span><span>。</span><span><br><br></span><span>　　回</span><span>调</span><span>可用于通知机制，例如，有</span><span>时</span><span>要在程序中</span><span>设</span><span>置一个</span><span>计时</span><span>器，</span><span>每</span><span>到一定</span><span>时间</span><span>，程序会得到相</span><span>应</span><span>的通知，但通知机制的</span><span>实现</span><span>者</span><span>对</span><span>我</span><span>们</span><span>的程序一无所知。而此</span><span>时</span><span>，就需有一个特定原型的函数指</span><span>针</span><span>，用</span><span>这</span><span>个指</span><span>针</span><span>来</span><span>进</span><span>行回</span><span>调</span><span>，来通知我</span><span>们</span><span>的程序事件已</span><span>经发</span><span>生。</span><span>实际</span><span>上，</span><span>SetTimer() API</span><span>使用了一个回</span><span>调</span><span>函数来通知</span><span>计时</span><span>器，而且，万一没有提供回</span><span>调</span><span>函数，它</span><span>还</span><span>会把一个消息</span><span>发</span><span>往程序的消息</span><span>队</span><span>列。</span><span><br><br></span><span>　　另一个使用回</span><span>调</span><span>机制的</span><span>API</span><span>函数是</span><span>EnumWindow()</span><span>，它枚</span><span>举</span><span>屏幕上所有的</span><span>顶层</span><span>窗口，</span><span>为每</span><span>个窗口</span><span>调</span><span>用一个程序提供的函数，并</span><span>传递</span><span>窗口的</span><span>处</span><span>理程序。如果被</span><span>调</span><span>用者返回一个</span><span>值</span><span>，就</span><span>继续进</span><span>行迭代，否</span><span>则</span><span>，退出。</span><span>EnumWindow()</span><span>并不</span><span>关</span><span>心被</span><span>调</span><span>用者在何</span><span>处</span><span>，也不</span><span>关</span><span>心被</span><span>调</span><span>用者用它</span><span>传递</span><span>的</span><span>处</span><span>理程序做了什</span><span>么</span><span>，它只</span><span>关</span><span>心返回</span><span>值</span><span>，因</span><span>为</span><span>基于返回</span><span>值</span><span>，它将</span><span>继续执</span><span>行或退出。</span><span><br><br></span><span>　　不管怎</span><span>么说</span><span>，回</span><span>调</span><span>函数是</span><span>继续</span><span>自</span><span>C</span><span>语</span><span>言的，因而，在</span><span>C++</span><span>中，</span><span>应</span><span>只在与</span><span>C</span><span>代</span><span>码</span><span>建立接口，或与已有的回</span><span>调</span><span>接口打交道</span><span>时</span><span>，才使用回</span><span>调</span><span>函数。除了上述情况，在</span><span>C++</span><span>中</span><span>应</span><span>使用虚</span><span>拟</span><span>方法或函数符（</span><span>functor</span><span>），而不是回</span><span>调</span><span>函数。</span><span><br><br></span><span>　　一个</span><span>简单</span><span>的回</span><span>调</span><span>函数</span><span>实现</span><span><br><br></span><span>　　下面</span><span>创</span><span>建了一个</span><span>sort.dll</span><span>的</span><span>动态链</span><span>接</span><span>库</span><span>，它</span><span>导</span><span>出了一个名</span><span>为</span><span>CompareFunction</span><span>的</span><span>类</span><span>型</span><span>--typedef int (__stdcall *CompareFunction)(const byte*, const byte*)</span><span>，它就是回</span><span>调</span><span>函数的</span><span>类</span><span>型。另外，它也</span><span>导</span><span>出了两个方法：</span><span>Bubblesort()</span><span>和</span><span>Quicksort()</span><span>，</span><span>这</span><span>两个方法原型相同，但</span><span>实现</span><span>了不同的排序算法。</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc);<br><br>void DLLDIR __stdcall Quicksort(byte* array,int size,int elem_size,CompareFunction cmpFunc);</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　</span><span>这</span><span>两个函数接受以下参数：</span><span><br><br></span><span>　　</span><span>&#183;byte * array</span><span>：指向元素数</span><span>组</span><span>的指</span><span>针</span><span>（任意</span><span>类</span><span>型）。</span><span><br><br></span><span>　　</span><span>&#183;int size</span><span>：数</span><span>组</span><span>中元素的个数。</span><span><br><br></span><span>　　</span><span>&#183;int elem_size</span><span>：数</span><span>组</span><span>中一个元素的大小，以字</span><span>节为单</span><span>位。</span><span><br><br></span><span>　　</span><span>&#183;CompareFunction cmpFunc</span><span>：</span><span>带</span><span>有上述原型的指向回</span><span>调</span><span>函数的指</span><span>针</span><span>。</span><span><br><br></span><span>　　</span><span>这</span><span>两个函数的会</span><span>对</span><span>数</span><span>组进</span><span>行某</span><span>种</span><span>排序，但</span><span>每</span><span>次都需决定两个元素哪个排在前面，而函数中有一个回</span><span>调</span><span>函数，其地址是作</span><span>为</span><span>一个参数</span><span>传递进</span><span>来的。</span><span>对编</span><span>写者来</span><span>说</span><span>，不必介意函数在何</span><span>处实现</span><span>，或它怎</span><span>样</span><span>被</span><span>实现</span><span>的，所需在意的只是两个用于比</span><span>较</span><span>的元素的地址，并返回以下的某个</span><span>值</span><span>（</span><span>库</span><span>的</span><span>编</span><span>写者和使用者都必</span><span>须</span><span>遵守</span><span>这</span><span>个</span><span>约</span><span>定）：</span><span><br><br></span><span>　　</span><span>&#183;-1</span><span>：如果第一个元素</span><span>较</span><span>小，那它在已排序好的数</span><span>组</span><span>中，</span><span>应该</span><span>排在第二个元素前面。</span><span><br><br></span><span>　　</span><span>&#183;0</span><span>：如果两个元素相等，那</span><span>么</span><span>它</span><span>们</span><span>的相</span><span>对</span><span>位置并不重要，在已排序好的数</span><span>组</span><span>中，</span><span>谁</span><span>在前面都无所</span><span>谓</span><span>。</span><span> <br><br></span><span>　　</span><span>&#183;1</span><span>：如果第一个元素</span><span>较</span><span>大，那在已排序好的数</span><span>组</span><span>中，它</span><span>应该</span><span>排第二个元素后面。</span><span><br><br></span><span>　　</span><span>基于以上</span><span>约</span><span>定，函数</span><span>Bubblesort()</span><span>的</span><span>实现</span><span>如下，</span><span>Quicksort()</span><span>就稍微</span><span>复杂</span><span>一点：</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc)<br>{<br></span><span>　</span><span>for(int i=0; i &lt; size; i++)<br></span><span>　</span><span>{<br></span><span>　　</span><span>for(int j=0; j &lt; size-1; j++)<br></span><span>　　</span><span>{<br></span><span>　　　</span><span>//</span><span>回</span><span>调</span><span>比</span><span>较</span><span>函数</span><span><br></span><span>　　　</span><span>if(1 == (*cmpFunc)(array+j*elem_size,array+(j+1)*elem_size))<br></span><span>　　　</span><span>{<br></span><span>　　　　</span><span>//</span><span>两个相比</span><span>较</span><span>的元素相交</span><span>换</span><span><br></span><span>　　　　</span><span>byte* temp = new byte[elem_size];<br></span><span>　　　　</span><span>memcpy(temp, array+j*elem_size, elem_size);<br></span><span>　　　　</span><span>memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);<br></span><span>　　　　</span><span>memcpy(array+(j+1)*elem_size, temp, elem_size);<br></span><span>　　　　</span><span>delete [] temp;<br></span><span>　　　</span><span>}<br></span><span>　　</span><span>}<br></span><span>　</span><span>}<br>}</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　注意：因</span><span>为实现</span><span>中使用了</span><span>memcpy()</span><span>，所以函数在使用的数据</span><span>类</span><span>型方面，会有所局限。</span><span><br><br></span><span>　　</span><span>对</span><span>使用者来</span><span>说</span><span>，必</span><span>须</span><span>有一个回</span><span>调</span><span>函数，其地址要</span><span>传递给</span><span>Bubblesort()</span><span>函数。下面有二个</span><span>简单</span><span>的示例，一个比</span><span>较</span><span>两个整数，而另一个比</span><span>较</span><span>两个字符串：</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>int __stdcall CompareInts(const byte* velem1, const byte* velem2)<br>{<br></span><span>　</span><span>int elem1 = *(int*)velem1;<br></span><span>　</span><span>int elem2 = *(int*)velem2;<br><br></span><span>　</span><span>if(elem1 &lt; elem2)<br></span><span>　　</span><span>return -1;<br></span><span>　</span><span>if(elem1 &gt; elem2)<br></span><span>　　</span><span>return 1;<br><br></span><span>　</span><span>return 0;<br>}<br><br>int __stdcall CompareStrings(const byte* velem1, const byte* velem2)<br>{<br></span><span>　</span><span>const char* elem1 = (char*)velem1;<br></span><span>　</span><span>const char* elem2 = (char*)velem2;<br></span><span>　</span><span>return strcmp(elem1, elem2);<br>}</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　下面另有一个程序，用于</span><span>测试</span><span>以上所有的代</span><span>码</span><span>，它</span><span>传递</span><span>了一个有</span><span>5</span><span>个元素的数</span><span>组给</span><span>Bubblesort()</span><span>和</span><span>Quicksort()</span><span>，同</span><span>时还传递</span><span>了一个指向回</span><span>调</span><span>函数的指</span><span>针</span><span>。</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>int main(int argc, char* argv[])<br>{<br></span><span>　</span><span>int i;<br></span><span>　</span><span>int array[] = {5432, 4321, 3210, 2109, 1098};<br><br></span><span>　</span><span>cout &lt;&lt; "Before sorting ints with Bubblesort\n";<br></span><span>　</span><span>for(i=0; i &lt; 5; i++)<br></span><span>　　</span><span>cout &lt;&lt; array[i] &lt;&lt; '\n';<br><br></span><span>　</span><span>Bubblesort((byte*)array, 5, sizeof(array[0]), &amp;CompareInts);<br><br></span><span>　</span><span>cout &lt;&lt; "After the sorting\n";<br></span><span>　</span><span>for(i=0; i &lt; 5; i++)<br></span><span>　　</span><span>cout &lt;&lt; array[i] &lt;&lt; '\n';<br><br></span><span>　</span><span>const char str[5][10] = {"estella","danielle","crissy","bo","angie"};<br><br></span><span>　</span><span>cout &lt;&lt; "Before sorting strings with Quicksort\n";<br></span><span>　</span><span>for(i=0; i &lt; 5; i++)<br></span><span>　　</span><span>cout &lt;&lt; str[i] &lt;&lt; '\n';<br><br></span><span>　</span><span>Quicksort((byte*)str, 5, 10, &amp;CompareStrings);<br><br></span><span>　</span><span>cout &lt;&lt; "After the sorting\n";<br></span><span>　</span><span>for(i=0; i &lt; 5; i++)<br></span><span>　　</span><span>cout &lt;&lt; str[i] &lt;&lt; '\n';<br><br></span><span>　</span><span>return 0;<br>}</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　如果想</span><span>进</span><span>行降序排序（大元素在先），就只需修改回</span><span>调</span><span>函数的代</span><span>码</span><span>，或使用另一个回</span><span>调</span><span>函数，</span><span>这样编</span><span>程起来灵活性就比</span><span>较</span><span>大了。</span></p>
            <p><span>调</span><span>用</span><span>约</span><span>定</span><span><br><br></span><span>　　上面的代</span><span>码</span><span>中，可在函数原型中找到</span><span>__stdcall</span><span>，因</span><span>为</span><span>它以双下划</span><span>线</span><span>打</span><span>头</span><span>，所以它是一个特定于</span><span>编译</span><span>器的</span><span>扩</span><span>展，</span><span>说</span><span>到底也就是微</span><span>软</span><span>的</span><span>实现</span><span>。任何支持</span><span>开发</span><span>基于</span><span>Win32</span><span>的程序都必</span><span>须</span><span>支持</span><span>这</span><span>个</span><span>扩</span><span>展或其等价物。以</span><span>__stdcall</span><span>标识</span><span>的函数使用了</span><span>标</span><span>准</span><span>调</span><span>用</span><span>约</span><span>定，</span><span>为</span><span>什</span><span>么</span><span>叫</span><span>标</span><span>准</span><span>约</span><span>定呢，因</span><span>为</span><span>所有的</span><span>Win32 API</span><span>（除了个</span><span>别</span><span>接受可</span><span>变</span><span>参数的除外）都使用它。</span><span>标</span><span>准</span><span>调</span><span>用</span><span>约</span><span>定的函数在它</span><span>们</span><span>返回到</span><span>调</span><span>用者之前，都会从堆</span><span>栈</span><span>中移除掉参数，</span><span>这</span><span>也是</span><span>Pascal</span><span>的</span><span>标</span><span>准</span><span>约</span><span>定。但在</span><span>C/C++</span><span>中，</span><span>调</span><span>用</span><span>约</span><span>定是</span><span>调</span><span>用者</span><span>负责</span><span>清理堆</span><span>栈</span><span>，而不是被</span><span>调</span><span>用函数；</span><span>为强</span><span>制函数使用</span><span>C/C++</span><span>调</span><span>用</span><span>约</span><span>定，可使用</span><span>__cdecl</span><span>。另外，可</span><span>变</span><span>参数函数也使用</span><span>C/C++</span><span>调</span><span>用</span><span>约</span><span>定。</span><span><br><br></span><span>　　</span><span>Windows</span><span>操作系</span><span>统</span><span>采用了</span><span>标</span><span>准</span><span>调</span><span>用</span><span>约</span><span>定（</span><span>Pascal</span><span>约</span><span>定），因</span><span>为</span><span>其可减小代</span><span>码</span><span>的体</span><span>积</span><span>。</span><span>这</span><span>点</span><span>对</span><span>早期的</span><span>Windows</span><span>来</span><span>说</span><span>非常重要，因</span><span>为</span><span>那</span><span>时</span><span>它运行在只有</span><span>640KB</span><span>内存的</span><span>电脑</span><span>上。</span><span><br><br></span><span>　　</span><span>如果你不喜</span><span>欢</span><span>__stdcall</span><span>，</span><span>还</span><span>可以使用</span><span>CALLBACK</span><span>宏，它定</span><span>义</span><span>在</span><span>windef.h</span><span>中：</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>#define CALLBACK __stdcallor<br><br>#define CALLBACK PASCAL //</span><span>而</span><span>PASCAL</span><span>在此被</span><span>#defined</span><span>成</span><span>__stdcall</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　作</span><span>为</span><span>回</span><span>调</span><span>函数的</span><span>C++</span><span>方法</span><span><br><br></span><span>　　因</span><span>为</span><span>平</span><span>时</span><span>很可能会使用到</span><span>C++</span><span>编</span><span>写代</span><span>码</span><span>，也</span><span>许</span><span>会想到把回</span><span>调</span><span>函数写成</span><span>类</span><span>中的一个方法，但先来看看以下的代</span><span>码</span><span>：</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>class CCallbackTester<br>{<br></span><span>　</span><span>public:<br></span><span>　</span><span>int CALLBACK CompareInts(const byte* velem1, const byte* velem2);<br>};<br><br>Bubblesort((byte*)array, 5, sizeof(array[0]),<br>&amp;CCallbackTester::CompareInts);</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　如果使用微</span><span>软</span><span>的</span><span>编译</span><span>器，将会得到下面</span><span>这</span><span>个</span><span>编译错误</span><span>：</span></p>
            <div align=center>
            <table cellPadding=0 width="90%" border=1>
                <tbody>
                    <tr>
                        <td>
                        <p><span>error C2664: 'Bubblesort' : cannot convert parameter 4 from 'int (__stdcall CCallbackTester::*)(const unsigned char *,const unsigned char *)' to 'int (__stdcall *)(const unsigned char *,const unsigned char *)' There is no context in which this conversion is possible</span></p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p><span><br></span><span>　　</span><span>这</span><span>是因</span><span>为</span><span>非静</span><span>态</span><span>成</span><span>员</span><span>函数有一个</span><span>额</span><span>外的参数：</span><span>this</span><span>指</span><span>针</span><span>，</span><span>这</span><span>将迫使你在成</span><span>员</span><span>函数前面加上</span><span>static</span><span>。当然，</span><span>还</span><span>有几</span><span>种</span><span>方法可以解决</span><span>这</span><span>个</span><span>问题</span><span>，但限于篇幅，就不再</span><span>论</span><span>述了</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p><img src ="http://www.cppblog.com/wind/aggbug/68630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-12-05 11:04 <a href="http://www.cppblog.com/wind/archive/2008/12/05/68630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux使用Eclipse开发C/C++程序</title><link>http://www.cppblog.com/wind/archive/2008/12/02/68383.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Tue, 02 Dec 2008 06:30:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/12/02/68383.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/68383.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/12/02/68383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/68383.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/68383.html</trackback:ping><description><![CDATA[<h2>详解Linux下安装Eclipse和CDT开发C/C++</h2>
<div class=t_msgfont id=postmessage_517617><font style="FONT-SIZE: 10pt"><font color=seagreen>本文转载自</font><a href="http://blog.163.com/a3563@126/blog/static/5467570620084295143783/" target=_blank><font color=seagreen><u>http://blog.163.com/a3563@126/blog/static/5467570620084295143783/</u></font></a>,。</font><br><strong><font color=red><font style="FONT-SIZE: 10pt">一. 为什么要在<span class=t_tag onclick=tagshow(event) href="tag.php?name=Linux">Linux</span>使用Eclipse开发C/C++<span class=t_tag onclick=tagshow(event) href="tag.php?name=%B3%CC%D0%F2">程序</span>?</font></font> </strong><br>&nbsp; &nbsp;&nbsp; &nbsp; Linux 是一个以C/C++开发为主的平台，无论是Kernel或是Application，主要都使用C/C++开发。传统在Linux下开发程序，是在文字模式下，利用vi等文字编辑器撰写C/C++程序存盘后，在Command line下使用gcc编译，若要debug，则使用gdb。<br>&nbsp; &nbsp;&nbsp; &nbsp; 这种开发方式生产力并不高，若只是开发学习用的小程序则影响不大，但若要开发大型项目时，程序档案个数众多，需要用project或solution的方式管理；且debug时breakpoint的加入，单步执行，观察变量变化等，都需要更可视化的方式才能够增加生产力；最重要的，由于现在的程序语言皆非常的庞大，又有复杂的函式库，要程序员熟记所有的程序语法和function名称，实在很困难，所以语法<span class=t_tag onclick=tagshow(event) href="tag.php?name=%CC%E1%CA%BE">提示</span>(<span class=t_tag onclick=tagshow(event) href="tag.php?name=Intel">Intel</span>lisense)的功能就非常重要，这些就必须靠IDE来达成。<br>&nbsp; &nbsp;&nbsp; &nbsp; 在Windows平台上，若要开发C/C++程序，我们有Microsoft Visual Studio、Borland C++ Builder可用，这些都是很好用的IDE，但可惜仅能在Windows下使用，但是在Linux平台呢?基于以下理由，我推荐使用Eclipse开发 C/C++程序：<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; 1. Eclipse是一个用Java所撰写IDE，因此可跨平台，所以在Linux和Windows平台下皆可使用Eclipse，可降低程序员熟析IDE的学习曲线。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; 2. Eclipse 虽然主要拿来开发Java程序，但事实上Eclipse为一个『万用语言』的IDE，只要挂上plugin后，就可以在Eclipse开发各种语言程序，所以我们只要挂上CDT(C/C++ Development Toolkit)后，就可以在Eclipse开发C/C++程序，除此之外，目前的主流程序语言，如C/C++、C#、Java、PHP、Perl、 Python、Ruby、Rebol、JavaScript、SQL、XML、UML等，皆可在Eclipse上撰写，所以只要熟析Eclipse的 IDE环境，将来若开发其它语言程序，就不用再重新学习IDE环境了。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; 3. 最重要的，Eclipse和CDT是Open Source且完全免费，取得相当容易，事实上Fedora 5已经包含Eclipse和CDT了，虽然预设Fedara 5安装时并没有含Eclipse，只要手动另外加选即可。<br><strong><font color=red>二. 如何在Linux下安装Eclipse和CDT?</font></strong>&nbsp;&nbsp;<br><font color=blue>1. <span class=t_tag onclick=tagshow(event) href="tag.php?name=%CF%C2%D4%D8">下载</span>档案</font><br>&nbsp; &nbsp; A、 下载JRE(Java Runtime Environment) 。(<a href="http://java.sun.com/javase/downloads/index.jsp" target=_blank><font color=#666666><u>http://<span class=t_tag onclick=tagshow(event) href="tag.php?name=java">java</span>.sun.com/<span class=t_tag onclick=tagshow(event) href="tag.php?name=java">java</span>se/downloads/index.jsp</u></font></a>)<br>&nbsp; &nbsp; B、 下载Eclipse SDK。(<a href="http://www.eclipse.org/downloads/" target=_blank><font color=#666666><u>http://www.eclipse.org/downloads/</u></font></a>)<br>&nbsp; &nbsp; C、 下载CDT。(<a href="http://www.eclipse.org/cdt/downloads.php" target=_blank><font color=#666666><u>http://www.eclipse.org/cdt/downloads.php</u></font></a>)<br><font color=blue>2. 安装</font><br>&nbsp; &nbsp; <strong>A、安装JRE</strong><br>&nbsp; &nbsp;&nbsp; &nbsp;i. [<span class=t_tag onclick=tagshow(event) href="tag.php?name=root">root</span>@localhost ~]#mkdir /usr/local/java<br>&nbsp; &nbsp;&nbsp; &nbsp;ii. <font color=#0800>(将档案jre-1_5_0_09-linux-i586-<span class=t_tag onclick=tagshow(event) href="tag.php?name=rpm">rpm</span>.bin下载到/usr/local/java目录下)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;iii. <font color=#0800>(超级用户模式)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost ~]#su&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>&nbsp; &nbsp;&nbsp; &nbsp;iv.&nbsp;&nbsp;[root@localhost ~]#cd /usr/java<br>&nbsp; &nbsp;&nbsp; &nbsp;v. <font color=#0800>(将您所下载的档的权限更改为可执行)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost java]#chmod a+x jre-1_5_0_09-linux-i586-rpm.bin <br>&nbsp; &nbsp;&nbsp; &nbsp;vi. <font color=#0800>(启动安装过程) </font><br>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost java]#./jre-1_5_0_09-linux-i586-rpm.bin<br>&nbsp; &nbsp;&nbsp; &nbsp;<font color=#0800>(此时将显示二进制许可协议，按控格显示下一页，读完许可协议后，输入 『yes』继续安装。此时会将解压缩，产生jre-1_5_0_9-linux-i586.rpm)<br><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/JRE1.jpg" onload="attachimg(this, 'load')" border=0><br></font>&nbsp; &nbsp;&nbsp; &nbsp;vii. <font color=#0800>(安装jre-1_5_0_9-linux-i586.rpm)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost java]#rpm &#8211;ivh jre-1_5_0_9-linux-i586.rpm <br><img height=235 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/JRE2.jpg" width=574 border=0><br>&nbsp; &nbsp;&nbsp; &nbsp;<font color=#0800>(此时会将JRE装在/usr/java/jre1.5.0_09目录下)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;viii. <font color=#0800>(设定环境变量，让Linux能找到JRE)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost java]#vi /etc/profile<br>&nbsp; &nbsp;&nbsp; &nbsp;<font color=#0800>(将以下内容加入在档案后面)</font><br><font style="FONT-SIZE: 13px"><font color=#08080>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;1</font> <img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" onload="attachimg(this, 'load')" border=0><font color=sienna>PATH = $PATH: / usr / java / jre1. 5 .0_09 / bin</font><font color=#000><br></font><font color=#08080>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;2</font> <font color=#000><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" onload="attachimg(this, 'load')" border=0></font><font color=sienna>export JAVA_HOME =/ usr / java / jre1. 5 .0_09<br></font><font color=#08080>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;3</font> <font color=#000><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" onload="attachimg(this, 'load')" border=0></font><font color=sienna>export CLASSPATH = $JAVA_HOME / lib:.</font> </font><br>&nbsp; &nbsp;&nbsp; &nbsp;<font color=#0800>(存盘后，重新启动Linux)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;ix. <font color=#0800>(测试Java是否安装成功)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost ~]#java &#8211;version<br><img height=164 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/JRE3.jpg" width=665 border=0><br><br>&nbsp; &nbsp;<strong> B、 安装Eclipse SDK</strong><br>&nbsp; &nbsp;&nbsp; &nbsp;i. <font color=#0800>(将档案eclipse-SDK-3.2.1-linux-gtk.tar.gz下载到桌面)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;ii. [root@localhost ~]#cd /usr/local<br>&nbsp; &nbsp;&nbsp; &nbsp;iii. [root@localhost local]#cp ~Desktop/eclipse-SDK-3.2.1-linux-gtk.tar.gz <br>&nbsp; &nbsp;&nbsp; &nbsp;iv.<font color=#0800> (将eclipse-SDK-3.2.1-linux-gtk.tar.gz解压缩)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost local]#tar &#8211;zxvf eclipse-SDK-3.2.1-linux-gtk.tar.gz<br>&nbsp; &nbsp;&nbsp; &nbsp;v. [root@localhost local]#cd eclipse<br>&nbsp; &nbsp;&nbsp; &nbsp;vi. <font color=#0800>(执行Eclipse)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost eclipse]#./eclipse<br>&nbsp; &nbsp;&nbsp; &nbsp;vii. <font color=#0800>(Select a workspace)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;<font color=#0800>(将Use this as the default and do not ask again打勾，以后就不会出现这个窗口)<br><img height=319 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Eclipse1.jpg" width=704 border=0><br><br>&nbsp; &nbsp;&nbsp; &nbsp;(第一次执行Eclipse会出现此error，因为没有任何Eclipse设定档，所以无法读取，第二次执行Eclipse就无此错误讯息，按OK继续。)<br><img height=184 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Eclipse2.jpg" width=701 border=0><br><br>&nbsp; &nbsp;&nbsp; &nbsp;(Eclipse主画面)<br><img height=549 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Eclipse3.jpg" width=800 border=0><br><br></font>&nbsp; &nbsp; <strong>C、 安装CDT</strong><br>&nbsp; &nbsp;&nbsp; &nbsp;i. <font color=#0800>(将档案org.eclipse.cdt-3.1.1-linux.x86.tar.gz下载到桌面)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;ii. [root@localhost ~]#cp ~/Desktop/org.eclipse.cdt-3.1.1-linux.x86.tar.gz<br>&nbsp; &nbsp;&nbsp; &nbsp;iii. <font color=#0800>(将org.eclipse.cdt-3.1.1-linux.x86.tar.gz解压缩)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost ~]#tar &#8211;zxvf org.eclipse.cdt-3.1.1-linux.x86.tar.gz<br>&nbsp; &nbsp;&nbsp; &nbsp;<font color=#0800>(档案将解到~/eclipse目录下)</font><br>&nbsp; &nbsp;&nbsp; &nbsp;iv. <font color=#0800>(安装CDT plugin)<br></font>&nbsp; &nbsp;&nbsp; &nbsp;[root@localhost ~]cp &#8211;r eclipse/plugins/. /usr/local/eclipse/plugins/ <br>&nbsp; &nbsp;&nbsp; &nbsp;v. <font color=#0800>(启动Eclipse，多了C和C++ Project支持)</font> <br>&nbsp; &nbsp; <img height=499 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/CDT1.jpg" width=700 border=0><br><font color=red>三 <strong>如何在Eclipse上开发C/C++程序?</strong></font><br><strong>i. 建立Hello Word project</strong><br>&nbsp;&nbsp;1. 建立C/C++ project<br><img height=156 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld1.jpg" width=468 border=0><br><br>&nbsp;&nbsp;2. 选择Managed Make C++ Project(若选择Managed Make C++ Project，Eclipse会自动为我们建立<span class=t_tag onclick=tagshow(event) href="tag.php?name=make">make</span> file；若选择Standard Make C++ Project，则必须自己写<span class=t_tag onclick=tagshow(event) href="tag.php?name=make">make</span> file。)<br><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld2.jpg" onload="attachimg(this, 'load')" border=0><br><br>&nbsp;&nbsp;3. 输入Project name<br><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld3.jpg" onload="attachimg(this, 'load')" border=0><br><br>&nbsp;&nbsp;4. 选择Project类型(如执行档或Library，这里选择执行档即可)<br><img height=498 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld4.jpg" width=700 border=0><br><br>&nbsp;&nbsp;5. 额外的设定<br><img height=499 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld5.jpg" width=700 border=0><br><br>&nbsp;&nbsp;6. Open Associated Perspective?(选Yes继续)<br><img height=498 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld6.jpg" width=699 border=0><br><br>&nbsp;&nbsp;7. 建立C++ Source File<br><img height=308 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld7.jpg" width=577 border=0><br><br>8. 输入C++ Source File檔名<br><img alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld8.jpg" onload="attachimg(this, 'load')" border=0><br><br>&nbsp;&nbsp;9. 输入C++程序代码<br><img height=550 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld9.jpg" width=799 border=0><br><br>&nbsp;&nbsp;10. 执行程序(显示在下方的Console区)<br><img height=548 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/HelloWorld10.jpg" width=799 border=0><br><br><strong>ii. 如何在Eclipse CDT中Debug C/C++程序?</strong><br>1. 在Eclipse中Debug，就如同在一般IDE中Debug一样，只要在程序代码的左方按两下，就可加入breakpoint。<br><img height=547 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Debug1.jpg" width=799 border=0><br><br>&nbsp;&nbsp;2. 启动Debug<br><img height=547 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Debug2.jpg" width=798 border=0><br><br>&nbsp;&nbsp;3. Debug设定，按Debug开始Debug<br><img height=550 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Debug3.jpg" width=800 border=0><br><br>&nbsp;&nbsp;4. 单步执行，显示变量变化<br><img height=548 alt="" src="http://www.cnblogs.com/images/cnblogs_com/oomusou/Debug4.jpg" width=798 border=0><br><br><font style="FONT-SIZE: 12pt"><font color=red><strong>四. 结论</strong></font><br></font>&nbsp; &nbsp;&nbsp; &nbsp; Eclipse 为Linux在C/C++开发提供一个完善的IDE环境，事实上，以我用过众多IDE的经验，除了Visual Studio最方便外，Eclipse的好用也直追Visual Studio，并且超越Borland C++ Builder及Dev C++，虽然安装上比较麻烦，但只要依照本文介绍一步一步的设定，就一定可完成Eclipse设定，若想要在Windows平台使用gcc compiler，也<span class=t_tag onclick=tagshow(event) href="tag.php?name=%BD%A8%D2%E9">建议</span>使用Eclipse + CDT + MinGW的组合</div><img src ="http://www.cppblog.com/wind/aggbug/68383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-12-02 14:30 <a href="http://www.cppblog.com/wind/archive/2008/12/02/68383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IP地址的分类</title><link>http://www.cppblog.com/wind/archive/2008/12/01/68282.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Mon, 01 Dec 2008 04:55:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/12/01/68282.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/68282.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/12/01/68282.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/68282.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/68282.html</trackback:ping><description><![CDATA[我们说过因特网是把全世界的无数个网络连接起来的一个庞大的网间网，每个网络中的计算机通过其自身的IP地址而被唯一标识的，据此我们也可以设想，在INTERNET上这个庞大的网间网中，每个网络也有自己的标识符。这与我们日常生活中的电话号码很相像，例如有一个电话号码为0515163，这个号码中的前四位表示该电话是属于哪个地区的，后面的数字表示该地区的某个电话号码。与上面的例子类似，我们把计算机的IP地址也分成两部分，分别为网络标识和主机标识。同一个物理网络上的所有主机都用同一个网络标识，网络上的一个主机（包括网络上工作站、<a class=channel_keylink href="http://server.chinaitlab.com/" target=_blank><u><font color=#0000ff>服务器</font></u></a>和<a class=channel_keylink href="http://cisco.chinaitlab.com/List_6.html" target=_blank><u><font color=#0000ff>路由</font></u></a>器等）都有一个主机标识与其对应?IP地址的4个字节划分为2个部分，一部分用以标明具体的网络段，即网络标识；另一部分用以标明具体的节点，即主机标识，也就是说某个网络中的特定的计算机号码。例如，盐城市信息网络中心的<a class=channel_keylink href="http://server.chinaitlab.com/" target=_blank><u><font color=#0000ff>服务器</font></u></a>的IP地址为210.73.140.2，对于该IP地址，我们可以把它分成网络标识和主机标识两部分，这样上述的IP地址就可以写成： <br>　　<br>　　网络标识：210.73.140.0 <br>　　<br>　　主机标识： 2 <br>　　<br>　　合起来写：210.73.140.2 <br>　　<br>　　由于网络中包含的计算机有可能不一样多，有的网络可能含有较多的计算机，也有的网络包含较少的计算机，于是人们按照网络规模的大小，把32位地址信息设成三种定位的划分方式，这三种划分方法分别对应于A类、B类、C类IP地址。 <br>　　<br>　　1．A类IP地址 <br>　　<br>　　一个A类IP地址是指，在IP地址的四段号码中，第一段号码为网络号码，剩下的三段号码为本地计算机的号码。如果用二进制表示IP地址的话，A类IP地址就由1字节的网络地址和3字节主机地址组成，网络地址的最高位必须是&#8220;0&#8221;。A类IP地址中网络的标识长度为7位，主机标识的长度为24位，A类网络地址数量较少，可以用于主机数达1600多万台的大型网络。 <br>　　<br>　　2．B类IP地址 <br>　　<br>　　一个B类IP地址是指，在IP地址的四段号码中，前两段号码为网络号码，B类IP地址就由2字节的网络地址和2字节主机地址组成，网络地址的最高位必须是&#8220;10&#8221;。B类IP地址中网络的标识长度为14位，主机标识的长度为16位，B类网络地址适用于中等规模规模的网络，每个网络所能容纳的计算机数为6万多台。 <br>　　<br>　　3．C类IP地址 <br>　　<br>　　一个C类IP地址是指，在IP地址的四段号码中，前三段号码为网络号码，剩下的一段号码为本地计算机的号码。如果用二进制表示IP地址的话，C类IP地址就由3字节的网络地址和1字节主机地址组成，网络地址的最高位必须是&#8220;110&#8221;。C类IP地址中网络的标识长度为21位，主机标识的长度为8位，C类网络地址数量较多，适用于小规模的局域网络，每个网络最多只能包含254台计算机。 <br>　　<br>　　除了上面三种类型的IP地址外，还有几种特殊类型的IP地址，TCP/IP<a class=channel_keylink href="http://cisco.chinaitlab.com/List_11.html" target=_blank><u><font color=#0000ff>协议</font></u></a>规定，凡IP地址中的第一个字节以&#8220;11110&#8221;开始的地址都叫多点广播地址。因此，任何第一个字节大于223小于240的IP地址是多点广播地址；IP地址中的每一个字节都为0的地址（&#8220;0.0.0.0&#8221;）对应于当前主机；IP地址中的每一个字节都为1的IP地址（&#8220;255．255．255．255&#8221;）是当前子网的广播地址；IP地址中凡是以&#8220;11110&#8221;的地址都留着将来作为特殊用途使用；IP地址中不能以十进制&#8220;127&#8221;作为开头，127．1．1．1用于回路测试，同时网络ID的第一个6位组也不能全置为&#8220;0&#8221;，全&#8220;0&#8221;表示本地网络。<img src ="http://www.cppblog.com/wind/aggbug/68282.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-12-01 12:55 <a href="http://www.cppblog.com/wind/archive/2008/12/01/68282.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在SQL Server 2005中启用xp_cmdshell</title><link>http://www.cppblog.com/wind/archive/2008/11/29/68135.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Sat, 29 Nov 2008 02:32:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/11/29/68135.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/68135.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/11/29/68135.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/68135.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/68135.html</trackback:ping><description><![CDATA[<p>在SQL Server 2005中，xp_cmdshell默认是被禁止使用的，使用xp_cmdshell会得类似这样的提示：<br>SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the security configuration for this server.</p>
<p>如果你是管理员，可以用以下语句启用xp_cmdshell<br>首先用SQL Server Management Studio Express连接到数据库服务器，然后运行下面的SQL语句：<br>sp_configure 'show advanced options',1<br>reconfigure<br>go<br>sp_configure 'xp_cmdshell',1<br>reconfigure<br>go<br>然后你就可以使用xp_cmdshell了。</p>
<p>如果服务器上的xp_cmdshell存储过程被删除掉了，还可以在master数据中运行下面的SQL语句加回来<br>sp_addextendedproc xp_cmdshell,@dllname='xplog70.dll'</p><img src ="http://www.cppblog.com/wind/aggbug/68135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-11-29 10:32 <a href="http://www.cppblog.com/wind/archive/2008/11/29/68135.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数指针（转帖）</title><link>http://www.cppblog.com/wind/archive/2008/11/11/66661.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Tue, 11 Nov 2008 14:55:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/11/11/66661.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/66661.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/11/11/66661.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/66661.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/66661.html</trackback:ping><description><![CDATA[数指针的类型，如：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;FP)();<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FP&nbsp;fp3;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;和上面的fp一样的定义。</span></div>
<p>　　函数指针之所以让初学者畏惧，最主要的原因是它的括号太多了；某些用途的函数指针，往往会让人陷在括号堆中出不来，这里就不举例了，因为不是本文讨论的范围；typedef 方法可以有效的减少括号的数量，以及理清层次，所以受到推荐。本文暂时只考虑简单的函数指针，因此暂不用到typedef。<br><br>　　假如有如下两个函数：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f1()<br><img id=Codehighlighter1_14_61_Open_Image onclick="this.style.display='none'; Codehighlighter1_14_61_Open_Text.style.display='none'; Codehighlighter1_14_61_Closed_Image.style.display='inline'; Codehighlighter1_14_61_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_14_61_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_14_61_Closed_Text.style.display='none'; Codehighlighter1_14_61_Open_Image.style.display='inline'; Codehighlighter1_14_61_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_14_61_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_14_61_Open_Text><span style="COLOR: #000000">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">call&nbsp;f&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f2(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a)<br><img id=Codehighlighter1_85_147_Open_Image onclick="this.style.display='none'; Codehighlighter1_85_147_Open_Text.style.display='none'; Codehighlighter1_85_147_Closed_Image.style.display='inline'; Codehighlighter1_85_147_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_85_147_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_85_147_Closed_Text.style.display='none'; Codehighlighter1_85_147_Open_Image.style.display='inline'; Codehighlighter1_85_147_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_85_147_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_85_147_Open_Text><span style="COLOR: #000000">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">call&nbsp;f2(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>　　现在需要通过函数指针来调用，我们需要给指针指定函数：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;fp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">f1;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;也可以用：fp&nbsp;=&nbsp;f1;</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;fp2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">f2;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;也可以用：fp2=&nbsp;f2;</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">fp3)()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">f1;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;也可以用：void&nbsp;(*fp3)()&nbsp;=&nbsp;f1;&nbsp;&nbsp;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">调用时如下：</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;fp();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;或&nbsp;(*fp)();</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;fp2(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;或&nbsp;(*fp2)(1);</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;fp3();&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;或&nbsp;(*fp3)();<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>　　对于此两种调用方法，效果完全一样，我推荐用前一种。后一种不仅仅是多打了键盘，而且也损失了一些灵活性。这里暂且不说它。<br>&nbsp;&nbsp;<br>　　C++强调类型安全。也就是说，不同类型的变量是不能直接赋值的，否则轻则警告，重则报错。这是一个很有用的特性，常常能帮我们找到问题。因此，有识之士认为，C++中的任何一外警告都不能忽视。甚至有人提出，编译的时候不能出现任何警告信息，也就是说，警告应该当作错误一样处理。<br>&nbsp;&nbsp;<br>　　比如，我们把f1赋值给fp2，那么C++编译器(vc7.1)就会报错：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;fp2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">f1;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;error&nbsp;C2440:&nbsp;&#8220;=&#8221;&nbsp;:&nbsp;无法从&#8220;void&nbsp;(__cdecl&nbsp;*)(void)&#8221;转换为&#8220;void&nbsp;(__cdecl&nbsp;*)(int)&#8221;</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;fp1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">f1;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;OK<img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>　　这样，编译器可以帮我们找出编码上的错误，节省了我们的排错时间。<br>&nbsp;&nbsp;<br>　　考虑一下C++标准模板库的sort函数：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;快速排序函数</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;template&lt;typename RandomAccessIterator, typename BinaryPredicate&gt;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sort(<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RandomAccessIterator&nbsp;_First,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;需排序数据的第一个元素位置</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RandomAccessIterator&nbsp;_Last,&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;需排序数据的最后一个元素位置（不参与排序）</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BinaryPredicate&nbsp;_Comp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;排序使用的比较算法(可以是函数指针、函数对象等)</span><span style="COLOR: #008000"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</span></div>
<p>　　比如，我们有一个整型数组：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_13_23_Open_Image onclick="this.style.display='none'; Codehighlighter1_13_23_Open_Text.style.display='none'; Codehighlighter1_13_23_Closed_Image.style.display='inline'; Codehighlighter1_13_23_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_13_23_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_13_23_Closed_Text.style.display='none'; Codehighlighter1_13_23_Open_Image.style.display='inline'; Codehighlighter1_13_23_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n[</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_13_23_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_13_23_Open_Text><span style="COLOR: #000000">{</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;<img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>　　要对它进行升序排序，我们需定义一个比较函数：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;less(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b)<br><img id=Codehighlighter1_28_53_Open_Image onclick="this.style.display='none'; Codehighlighter1_28_53_Open_Text.style.display='none'; Codehighlighter1_28_53_Closed_Image.style.display='inline'; Codehighlighter1_28_53_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_28_53_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_28_53_Closed_Text.style.display='none'; Codehighlighter1_28_53_Open_Image.style.display='inline'; Codehighlighter1_28_53_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_28_53_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_28_53_Open_Text><span style="COLOR: #000000">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;b;&nbsp;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span></div>
<p>　　然后用：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;sort(n,&nbsp;n</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">,&nbsp;less);</span></div>
<p>　　要是想对它进行降序排序，我们只要换一个比较函数就可以了。C/C++的标准模板已经提供了less和great函数，因此我们可以直接用下面的语句来比较：&nbsp;&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;sort(n,&nbsp;n</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">,&nbsp;great);</span></div>
<p><br>　　这样，不需要改变sort函数的定义，就可以按任意方法进行排序，是不是很灵活？&nbsp;&nbsp;<br>　　这种用法以C++的标准模板库(STL)中非常流行。另外，操作系统中也经常使用回调(CallBack)函数，实际上，所谓回调函数，本质就是函数指针。</p>
<p>　　看起来很简单吧，这是最普通的C语言指针的用法。本来这是一个很美妙的事情，但是当C++来临时，世界就开始变了样。<br>　　假如，用来进行sort的比较函数是某个类的成员，那又如何呢？<br>转帖<a href="http://ly4cn.cnblogs.com/archive/2005/12/17/299007.html">http://ly4cn.cnblogs.com/archive/2005/12/17/299007.html</a></p><img src ="http://www.cppblog.com/wind/aggbug/66661.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-11-11 22:55 <a href="http://www.cppblog.com/wind/archive/2008/11/11/66661.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++习题</title><link>http://www.cppblog.com/wind/archive/2008/11/10/66519.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Mon, 10 Nov 2008 07:01:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/11/10/66519.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/66519.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/11/10/66519.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/66519.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/66519.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 用递归算法判断数组a[N]是否为一个递增数组。#include&nbsp;"stdafx.h"#include&nbsp;&lt;iostream&gt;using&nbsp;namespace&nbsp;std;bool&nbsp;Compare(int&nbsp;ar[]&nbsp;,int&nbsp;n){&nbsp;&nbsp;&nbsp;&nbsp;if(n==1)&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.cppblog.com/wind/archive/2008/11/10/66519.html'>阅读全文</a><img src ="http://www.cppblog.com/wind/aggbug/66519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-11-10 15:01 <a href="http://www.cppblog.com/wind/archive/2008/11/10/66519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Danamic Link Library</title><link>http://www.cppblog.com/wind/archive/2008/11/05/66025.html</link><dc:creator>dengbo</dc:creator><author>dengbo</author><pubDate>Wed, 05 Nov 2008 06:55:00 GMT</pubDate><guid>http://www.cppblog.com/wind/archive/2008/11/05/66025.html</guid><wfw:comment>http://www.cppblog.com/wind/comments/66025.html</wfw:comment><comments>http://www.cppblog.com/wind/archive/2008/11/05/66025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wind/comments/commentRss/66025.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wind/services/trackbacks/66025.html</trackback:ping><description><![CDATA[&nbsp;
<p align=left><span>DLL</span><span>文件</span><span>(Dynamic Linkable Library </span><span>即</span><span>动态链</span><span>接</span><span>库</span><span>文件</span><span>)</span><span>，是一</span><span>种</span><span>不能</span><span>单</span><span>独运行的文件，它允</span><span>许</span><span>程序共享</span><span>执</span><span>行特殊任</span><span>务</span><span>所必需的代</span><span>码</span><span>和其他</span><span>资</span><span>源</span></p>
<p align=left><span>　　比</span><span>较</span><span>大的</span><span>应</span><span>用程序都由很多模</span><span>块组</span><span>成，</span><span>这</span><span>些模</span><span>块</span><span>分</span><span>别</span><span>完成相</span><span>对</span><span>独立的功能，它</span><span>们</span><span>彼此</span><span>协</span><span>作来完成整个</span><span>软</span><span>件系</span><span>统</span><span>的工作。可能存在一些模</span><span>块</span><span>的功能</span><span>较为</span><span>通用，在构造其它</span><span>软</span><span>件系</span><span>统时</span><span>仍会被使用。在构造</span><span>软</span><span>件系</span><span>统时</span><span>，如果将所有模</span><span>块</span><span>的源代</span><span>码</span><span>都静</span><span>态编译</span><span>到整个</span><span>应</span><span>用程序</span><span> EXE </span><span>文件中，会</span><span>产</span><span>生一些</span><span>问题</span><span>：一个缺点是增加了</span><span>应</span><span>用程序的大小，它会占用更多的磁</span><span>盘</span><span>空</span><span>间</span><span>，程序运行</span><span>时</span><span>也会消耗</span><span>较</span><span>大的内存空</span><span>间</span><span>，造成系</span><span>统资</span><span>源的浪</span><span>费</span><span>；另一个缺点是，在</span><span>编</span><span>写大的</span><span> EXE </span><span>程序</span><span>时</span><span>，在</span><span>每</span><span>次修改重建</span><span>时</span><span>都必</span><span>须调</span><span>整</span><span>编译</span><span>所有源代</span><span>码</span><span>，增加了</span><span>编译过</span><span>程的</span><span>复杂</span><span>性，也不利于</span><span>阶</span><span>段性的</span><span>单</span><span>元</span><span>测试</span><span>。</span></p>
<p align=left><span>　　</span><span>Windows </span><span>系</span><span>统</span><span>平台上提供了一</span><span>种</span><span>完全不同的</span><span>较</span><span>有效的</span><span>编</span><span>程和运行</span><span>环</span><span>境，你可以将独立的程序模</span><span>块创</span><span>建</span><span>为较</span><span>小的</span><span> DLL </span><span>文件，并可</span><span>对</span><span>它</span><span>们单</span><span>独</span><span>编译</span><span>和</span><span>测试</span><span>。在运行</span><span>时</span><span>，只有当</span><span> EXE </span><span>程序确</span><span>实</span><span>要</span><span>调</span><span>用</span><span>这</span><span>些</span><span> DLL </span><span>模</span><span>块</span><span>的情况下，系</span><span>统</span><span>才会将它</span><span>们</span><span>装</span><span>载</span><span>到内</span><span>存空</span><span>间</span><span>中。</span><span>这种</span><span>方式不</span><span>仅</span><span>减少了</span><span> EXE </span><span>文件的大小和</span><span>对</span><span>内存空</span><span>间</span><span>的需求，而且使</span><span>这</span><span>些</span><span> DLL </span><span>模</span><span>块</span><span>可以同</span><span>时</span><span>被多个</span><span>应</span><span>用程序使用。</span><span>Windows </span><span>自己就将一些主要的系</span><span>统</span><span>功能以</span><span> DLL </span><span>模</span><span>块</span><span>的形式</span><span>实现</span><span>。</span></p>
<p align=left><span>　　一般来</span><span>说</span><span>，</span><span>DLL </span><span>是一</span><span>种</span><span>磁</span><span>盘</span><span>文件，以</span><span>.dll</span><span>、</span><span>.DRV</span><span>、</span><span>.FON</span><span>、</span><span>.SYS </span><span>和</span><span>许</span><span>多以</span><span> .EXE </span><span>为扩</span><span>展名的系</span><span>统</span><span>文件都可以是</span><span> DLL</span><span>。它由全局数据、服</span><span>务</span><span>函数和</span><span>资</span><span>源</span><span>组</span><span>成，在运行</span><span>时</span><span>被系</span><span>统</span><span>加</span><span>载</span><span>到</span><span>调</span><span>用</span><span>进</span><span>程的虚</span><span>拟</span><span>空</span><span>间</span><span>中，成</span><span>为调</span><span>用</span><span>进</span><span>程的一部分。如果与其它</span><span> DLL </span><span>之</span><span>间</span><span>没有冲突，</span><span>该</span><span>文件通常映射到</span><span>进</span><span>程虚</span><span>拟</span><span>空</span><span>间</span><span>的同一地址上。</span><span>DLL </span><span>模</span><span>块</span><span>中包含各</span><span>种导</span><span>出函数，用于向外界提供服</span><span>务</span><span>。</span><span>DLL </span><span>可以有自己的数据段，但没有自己的堆</span><span>栈</span><span>，使用与</span><span>调</span><span>用它的</span><span>应</span><span>用程序相同的堆</span><span>栈</span><span>模式；一个</span><span> DLL </span><span>在内存中只有一个</span><span>实</span><span>例；</span><span>DLL </span><span>实现</span><span>了代</span><span>码</span><span>封装性；</span><span>DLL </span><span>的</span><span>编</span><span>制与具体的</span><span>编</span><span>程</span><span>语</span><span>言及</span><span>编译</span><span>器无</span><span>关</span><span>。</span></p>
<p align=left><span>　　在</span><span> Win32 </span><span>环</span><span>境中，</span><span>每</span><span>个</span><span>进</span><span>程都</span><span>复</span><span>制了自己的</span><span>读</span><span>/</span><span>写全局</span><span>变</span><span>量。如果想要与其它</span><span>进</span><span>程共享内存，必</span><span>须</span><span>使用内存映射文件或者声明一个共享数据段。</span><span>DLL </span><span>模</span><span>块</span><span>需要的堆</span><span>栈</span><span>内存都是从运行</span><span>进</span><span>程的堆</span><span>栈</span><span>中分配出来的。</span><span>Windows </span><span>在加</span><span>载</span><span> DLL </span><span>模</span><span>块时</span><span>将</span><span>进</span><span>程函数</span><span>调</span><span>用与</span><span> DLL </span><span>文件的</span><span>导</span><span>出函</span><span>数相匹配。</span><span>Windows </span><span>操作系</span><span>统对</span><span> DLL </span><span>的操作</span><span>仅仅</span><span>是把</span><span> DLL </span><span>映射到需要它的</span><span>进</span><span>程的虚</span><span>拟</span><span>地址空</span><span>间</span><span>里去。</span><span>DLL </span><span>函数中的代</span><span>码</span><span>所</span><span>创</span><span>建的任何</span><span>对</span><span>象（包括</span><span>变</span><span>量）都</span><span>归调</span><span>用它的</span><span>线</span><span>程或</span><span>进</span><span>程所有。</span></p>
<p align=left><span>　　</span><span>调</span><span>用方式：</span></p>
<p align=left><span>　　</span><span>1</span><span>、静</span><span>态调</span><span>用方式：由</span><span>编译</span><span>系</span><span>统</span><span>完成</span><span>对</span><span> DLL </span><span>的加</span><span>载</span><span>和</span><span>应</span><span>用程序</span><span>结</span><span>束</span><span>时</span><span> DLL </span><span>卸</span><span>载</span><span>的</span><span>编码</span><span>（如</span><span>还</span><span>有其它程序使用</span><span>该</span><span> DLL</span><span>，</span><span>则</span><span> Windows </span><span>对</span><span> DLL </span><span>的</span><span>应</span><span>用</span><span>记录</span><span>减</span><span>1</span><span>，直到所有相</span><span>关</span><span>程序都</span><span>结</span><span>束</span><span>对该</span><span> DLL </span><span>的使用</span><span>时</span><span>才</span><span>释</span><span>放它，</span><span>简单实</span><span>用，但不</span><span>够</span><span>灵活，只能</span><span>满</span><span>足一般要求。</span></p>
<p align=left><span>　　</span><span>隐</span><span>式的</span><span>调</span><span>用：需要把</span><span>产</span><span>生</span><span>动态连</span><span>接</span><span>库时产</span><span>生的</span><span> .LIB </span><span>文件加入到</span><span>应</span><span>用程序的工程中，想使用</span><span> DLL </span><span>中的函数</span><span>时</span><span>，只</span><span>须说</span><span>明一下。</span><span>隐</span><span>式</span><span>调</span><span>用不需要</span><span>调</span><span>用</span><span> LoadLibrary() </span><span>和</span><span> FreeLibrary()</span><span>。程序</span><span>员</span><span>在建立一个</span><span> DLL </span><span>文件</span><span>时</span><span>，</span><span>链</span><span>接程序会自</span><span>动</span><span>生成一个与之</span><span>对应</span><span>的</span><span> LIB </span><span>导</span><span>入文件。</span><span>该</span><span>文件包含了</span><span>每</span><span>一个</span><span> DLL </span><span>导</span><span>出函数的符号名和可</span><span>选</span><span>的</span><span>标识</span><span>号，但是并不含有</span><span>实际</span><span>的代</span><span>码</span><span>。</span><span>LIB </span><span>文件作</span><span>为</span><span> DLL </span><span>的替代文件被</span><span>编译</span><span>到</span><span>应</span><span>用程序</span><span>项</span><span>目中。</span></p>
<p align=left><span>　　当程序</span><span>员</span><span>通</span><span>过</span><span>静</span><span>态链</span><span>接方式</span><span>编译</span><span>生成</span><span>应</span><span>用程序</span><span>时</span><span>，</span><span>应</span><span>用程序中的</span><span>调</span><span>用函数与</span><span> LIB </span><span>文件中</span><span>导</span><span>出符号相匹配，</span><span>这</span><span>些符号</span><span>或</span><span>标识</span><span>号</span><span>进</span><span>入到生成的</span><span> EXE </span><span>文件中。</span><span>LIB </span><span>文件中也包含了</span><span>对应</span><span>的</span><span> DL L</span><span>文件名（但不是完全的路径名），</span><span>链</span><span>接程序将其存</span><span>储</span><span>在</span><span> EXE </span><span>文件内部。</span></p>
<p align=left><span>　　当</span><span>应</span><span>用程序运行</span><span>过</span><span>程中需要加</span><span>载</span><span> DLL </span><span>文件</span><span>时</span><span>，</span><span>Windows </span><span>根据</span><span>这</span><span>些信息</span><span>发现</span><span>并加</span><span>载</span><span> DLL</span><span>，然后通</span><span>过</span><span>符号名或</span><span>标识</span><span>号</span><span>实现对</span><span> DLL </span><span>函数的</span><span>动态链</span><span>接。所有被</span><span>应</span><span>用程序</span><span>调</span><span>用的</span><span> DLL </span><span>文件都会在</span><span>应</span><span>用程序</span><span> EXE</span><span>　文件加</span><span>载时</span><span>被加</span><span>载</span><span>在到内存中。可</span><span>执</span><span>行程序</span><span>链</span><span>接到一个包含</span><span> DLL </span><span>输</span><span>出函数信息的</span><span>输</span><span>入</span><span>库</span><span>文件</span><span>(.LIB</span><span>文件</span><span>)</span><span>。操作系</span><span>统</span><span>在加</span><span>载</span><span>使用可</span><span>执</span><span>行程序</span><span>时</span><span>加</span><span>载</span><span> DLL</span><span>。可</span><span>执</span><span>行</span><span>程序直接通</span><span>过</span><span>函数名</span><span>调</span><span>用</span><span> DLL </span><span>的</span><span>输</span><span>出函数，</span><span>调</span><span>用方法和程序内部其</span><span> </span><span>它的函数是一</span><span>样</span><span>的。</span></p>
<p align=left><span>　　</span><span>2</span><span>、</span><span>动态调</span><span>用方式：是由</span><span>编</span><span>程者用</span><span> API </span><span>函数加</span><span>载</span><span>和卸</span><span>载</span><span> DLL </span><span>来达到</span><span>调</span><span>用</span><span> DLL </span><span>的目的，使用上</span><span>较复杂</span><span>，但能更加有效地使用内存，是</span><span>编</span><span>制大型</span><span>应</span><span>用程序</span><span>时</span><span>的重要方式。</span></p>
<p align=left><span>　　</span><span>显</span><span>式的</span><span>调</span><span>用：</span></p>
<p align=left><span>　　是指在</span><span>应</span><span>用程序中用</span><span> LoadLibrary </span><span>或</span><span> MFC </span><span>提供的</span><span> AfxLoadLibrary </span><span>显</span><span>式的将自己所做的</span><span>动态连</span><span>接</span><span>库调进</span><span>来，</span><span>动态连</span><span>接</span><span>库</span><span>的文件名即是上面两个函数的参数，再用</span><span> GetProcAddress() </span><span>获</span><span>取想要引入的函数</span><span>。自此，你就可以象使用如同本</span><span>应</span><span>用程序自定</span><span>义</span><span>的函数一</span><span>样</span><span>来</span><span>调</span><span>用此引入函数了。在</span><span>应</span><span>用程序退出之前，</span><span>应该</span><span>用</span><span> FreeLibrary </span><span>或</span><span> MFC </span><span>提供的</span><span> AfxFreeLibrary </span><span>释</span><span>放</span><span>动态连</span><span>接</span><span>库</span><span>。直接</span><span>调</span><span>用</span><span> Win32 </span><span>的</span><span> LoadLibary </span><span>函数，并指定</span><span> DLL </span><span>的路径作</span><span>为</span><span>参数。</span><span>LoadLibary </span><span>返回</span><span> HINSTANCE </span><span>参数，</span><span>应</span><span>用程序在</span><span>调</span><span>用</span><span> GetProcAddress </span><span>函数</span><span>时</span><span>使用</span><span>这</span><span>一参数。</span><span>GetProcAddress </span><span>函数将符号名或</span><span>标识</span><span>号</span><span>转换为</span><span> DLL </span><span>内部的地址。程序</span><span>员</span><span>可以决定</span><span> DLL </span><span>文件何</span><span>时</span><span>加</span><span>载</span><span>或</span><span>不加</span><span>载</span><span>，</span><span>显</span><span>式</span><span>链</span><span>接在运行</span><span>时</span><span>决定加</span><span>载</span><span>哪个</span><span> DLL </span><span>文件。使用</span><span> DLL </span><span>的程序在使用之前必</span><span>须</span><span>加</span><span>载</span><span>（</span><span>LoadLibrary</span><span>）加</span><span>载</span><span>DLL</span><span>从而得到一个</span><span>DLL</span><span>模</span><span>块</span><span>的句柄，然后</span><span>调</span><span>用</span><span> GetProcAddress </span><span>函数得到</span><span>输</span><span>出函数的指</span><span>针</span><span>，在退出之前必</span><span>须</span><span>卸</span><span>载</span><span>DLL(FreeLibrary)</span><span>。</span></p>
<p align=left><span>　　正因</span><span>为</span><span>DLL </span><span>有占用内存小，好</span><span>编辑</span><span>等的特点有很多</span><span>电脑</span><span>病毒都是</span><span>DLL</span><span>格式文件。</span><span>但不能</span><span>单</span><span>独运行。</span><span> </span></p>
<p><span>　　</span><span>动态链</span><span>接</span><span>库</span><span>通常都不能直接运行，也不能接收消息。它</span><span>们</span><span>是一些独立的文件，其中包含能被可</span><span>执</span><span>行程序或其它</span><span>DLL</span><span>调</span><span>用来完成某</span><span>项</span><span>工作的函数。只</span><span>有在其它模</span><span>块调</span><span>用</span><span>动态链</span><span>接</span><span>库</span><span>中的函数</span><span>时</span><span>，它才</span><span>发挥</span><span>作用</span><span>。</span></p><img src ="http://www.cppblog.com/wind/aggbug/66025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wind/" target="_blank">dengbo</a> 2008-11-05 14:55 <a href="http://www.cppblog.com/wind/archive/2008/11/05/66025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>