﻿<?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++博客-Render Donkey-随笔分类-Programming</title><link>http://www.cppblog.com/Leaf/category/10585.html</link><description>~~</description><language>zh-cn</language><lastBuildDate>Fri, 14 Jun 2013 21:23:50 GMT</lastBuildDate><pubDate>Fri, 14 Jun 2013 21:23:50 GMT</pubDate><ttl>60</ttl><item><title>镜面反射矩阵推导</title><link>http://www.cppblog.com/Leaf/archive/2013/06/15/201017.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Fri, 14 Jun 2013 16:48:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/06/15/201017.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/201017.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/06/15/201017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/201017.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/201017.html</trackback:ping><description><![CDATA[<p>最近公司游戏正在准备上线，所以FlasCC也就没有研究了，偶尔有闲功夫，也是玩玩3DMAX和UNITY3D。 感觉不会3DMAX，是一种局限。</p> <p>回到主题，记录一下镜面反射矩阵的推导。</p> <p>在用Irrlicht和RTT做镜面效果的时候，用到了反射矩阵。 就是需要把摄相机镜像，渲染一个RT，贴到镜面模型上。这个其实还纠结了许久，因为之前做水面渲染的时候，水面是平的，很好计算摄相机在水面以下的位置。 但是换成镜面，就不一样了，因为镜面可能是任意面。 于是就需要一个通用的反射矩阵。</p> <p>反射矩阵的计算是基于平面的，因为，任何反射，都需要一个反射面。</p> <p>所以，我们先给出平面表示 Plane(nx,ny,nz,d); 其中(nx,ny,nz)已经单位化。</p> <p>然后，我们假设空间中有任意一点P(x,y,z,1)</p> <p>设这个点P以Plane为反射面的镜像点为P1(x1,y1,z1,w)。</p> <p>&nbsp;</p> <p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p> <p>根据定理，我们知道， 若两个点以某一点为镜像，则两个点的坐标之和除以2，就刚好是中点。 </p> <p>这个理论我们用到这里的话， 那这个中点就刚好是平面上的一个点。 平面上的这个点就是 P(x,y,z,1) - (nx,ny,nz,0)*D .&nbsp; 其中D就是点P到平面的距离</p> <p>而D=Plane dot P = (x*nx+y*ny+z*nz+d);</p> <p>由上面的描述，我们马上想到，那么要求点P1的话，就是这样&nbsp; </p> <p>(P+P1)/2 = P(x,y,z,1) - (nx,ny,nz,0)*D</p> <p>=&gt; P1 = P(x,y,z,1) - 2(nx,ny,nz,0)*D</p> <p>=&gt;P1 = P(x,y,z,1) - 2(nx,ny,nz,0)*(x*nx+y*ny+z*nz+d)</p> <p>&nbsp;</p> <p>换成矩阵形式则为</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ｜1-2*nx*nx&nbsp;&nbsp; -2*nx*ny&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -2*nx*nz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; |</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | -2*ny*nx&nbsp;&nbsp;&nbsp;&nbsp; 1 - 2*ny*ny&nbsp;&nbsp;&nbsp;&nbsp; -2*ny*nz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; |</p> <p>P1 = {x,y,z,1}&nbsp;&nbsp; x&nbsp;&nbsp; | -2*nz*nx&nbsp;&nbsp;&nbsp;&nbsp; -2*nz*ny&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1-2*nz*nz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; |</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | -2*d*nx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -2*d*ny&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -2*d*nz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; |</p> <p>&nbsp;</p> <p>大功告成</p> <p>btw:这是行主矩阵表示法</p> <img src ="http://www.cppblog.com/Leaf/aggbug/201017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-06-15 00:48 <a href="http://www.cppblog.com/Leaf/archive/2013/06/15/201017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>请教大家一个关于EPOLLET和EPOLLLT的问题</title><link>http://www.cppblog.com/Leaf/archive/2013/02/25/198061.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Mon, 25 Feb 2013 05:05:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2013/02/25/198061.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/198061.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2013/02/25/198061.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/198061.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/198061.html</trackback:ping><description><![CDATA[今天在查看EPOLLET和EPOLLLT的细节的时候，发现一篇文章。 但不知文中说的是否有道理，望各位大大给个明确的答复。<br />游戏服务器，我们用的是ET方式。<br /><a href="http://blog.linezing.com/2011/01/%E5%89%96%E6%9E%90-epoll-etlt-%E8%A7%A6%E5%8F%91%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%A7%E8%83%BD%E5%B7%AE%E5%BC%82%E8%AF%AF%E8%A7%A3%EF%BC%88%E5%AE%9A%E6%80%A7%E5%88%86%E6%9E%90%EF%BC%89"><br /></a><h2><a href="http://blog.linezing.com/2011/01/%E5%89%96%E6%9E%90-epoll-etlt-%E8%A7%A6%E5%8F%91%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%A7%E8%83%BD%E5%B7%AE%E5%BC%82%E8%AF%AF%E8%A7%A3%EF%BC%88%E5%AE%9A%E6%80%A7%E5%88%86%E6%9E%90%EF%BC%89"></a><a href="http://blog.linezing.com/2011/01/%e5%89%96%e6%9e%90-epoll-etlt-%e8%a7%a6%e5%8f%91%e6%96%b9%e5%bc%8f%e7%9a%84%e6%80%a7%e8%83%bd%e5%b7%ae%e5%bc%82%e8%af%af%e8%a7%a3%ef%bc%88%e5%ae%9a%e6%80%a7%e5%88%86%e6%9e%90%ef%bc%89"><font color="#1086a4">剖析 epoll ET/LT 触发方式的性能差异误解（定性分析）</font><br /><br /><br /></a><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><span style="font-family: Arial; ">平时大家使用 epoll 时都知道其事件触发模式有默认的 level-trigger 模式和通过 EPOLLET 启用的 edge-trigger 模式两种。从 epoll 发展历史来看，它刚诞生时只有 edge-trigger 模式，后来因容易产生 race-cond 且不易被开发者理解，又增加了 level-trigger 模式并作为默认处理方式。</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><span style="font-family: Arial; ">二者的差异在于 level-trigger 模式下只要某个 fd 处于 readable/writable 状态，无论什么时候进行 epoll_wait 都会返回该 fd；而 edge-trigger 模式下只有某个 fd 从 unreadable 变为 readable 或从 unwritable 变为 writable 时，epoll_wait 才会返回该 fd。</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><strong style="margin: 0px; padding: 0px; font-family: Arial; ">通常的误区是：level-trigger 模式在 epoll 池中存在大量 fd 时效率要显著低于 edge-trigger 模式。</strong></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><span style="font-family: Arial; ">但从 kernel 代码来看，edge-trigger/level-trigger 模式的处理逻辑几乎完全相同，差别仅在于 level-trigger 模式在 event 发生时不会将其从 ready list 中移除，略为增大了 event 处理过程中 kernel space 中记录数据的大小。</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><span style="font-family: Arial; ">然而，edge-trigger 模式一定要配合 user app 中的 ready list 结构，以便收集已出现 event 的 fd，再通过 round-robin 方式挨个处理，以此避免通信数据量很大时出现忙于处理热点 fd 而导致非热点 fd 饿死的现象。统观 kernel 和 user space，由于 user app 中 ready list 的实现千奇百怪，不一定都经过仔细的推敲优化，因此 edge-trigger 的总内存开销往往还大于 level-trigger 的开销。</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><span style="font-family: Arial; ">一般号称 edge-trigger 模式的优势在于能够减少 epoll 相关系统调用，这话不假，但 user app 里可不是只有 epoll 相关系统调用吧？为了绕过饿死问题，edge-trigger 模式的 user app 要自行进行 read/write 循环处理，这其中增加的系统调用和减少的 epoll 系统调用加起来，有谁能说一定就能明显地快起来呢？</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><span style="font-family: Arial; ">实际上，epoll_wait 的效率是 O(ready fd num) 级别的，因此 edge-trigger 模式的真正优势在于减少了每次 epoll_wait 可能需要返回的 fd 数量，在并发 event 数量极多的情况下能加快 epoll_wait 的处理速度，但别忘了这只是针对 epoll 体系自己而言的提升，与此同时 user app 需要增加复杂的逻辑、花费更多的 cpu/mem 与其配合工作，总体性能收益究竟如何？只有实际测量才知道，无法一概而论。不过，为了降低处理逻辑复杂度，常用的事件处理库大部分都选择了 level-trigger 模式（如 libevent、boost::asio等）</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 16px; "><strong style="margin: 0px; padding: 0px; font-family: Arial; ">结论：<br style="margin: 0px; padding: 0px; " />&#8226;	epoll 的 edge-trigger 和 level-trigger 模式处理逻辑差异极小，性能测试结果表明常规应用场景 中二者性能差异可以忽略。<br style="margin: 0px; padding: 0px; " />&#8226;	使用 edge-trigger 的 user app 比使用 level-trigger 的逻辑复杂，出错概率更高。<br style="margin: 0px; padding: 0px; " />&#8226;	edge-trigger 和 level-trigger 的性能差异主要在于 epoll_wait 系统调用的处理速度，是否是 user app 的性能瓶颈需要视应用场景而定，不可一概而论。</strong></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; font-size: 14px; "><span style="font-family: Arial; ">欢迎就此话题进行深入调研、讨论！</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: black; line-height: 18px; font-size: 12px; font-weight: normal; background-color: #ffffff; font-family: 微软雅黑; "><span style="font-family: Arial; ">参考资料：</span><br style="margin: 0px; padding: 0px; " /><span style="font-family: Arial; ">&#8226;	linux kernel source：fs/eventpoll.c</span><br style="margin: 0px; padding: 0px; " /><span style="font-family: Arial; ">&#8226;	&#8220;Comparing and Evaluating epoll, select, and poll Event</span><br style="margin: 0px; padding: 0px; " /><span style="font-family: Arial; ">Mechanisms&#8221;：http://bcr2.uwaterloo.ca/~brecht/papers/getpaper.php?file=ols-2004.pdf</span><br style="margin: 0px; padding: 0px; " /><span style="font-family: Arial; ">&#8226;	&#8220;Edge-triggered interfaces are too difficult?&#8221;：http://lwn.net/Articles/25137/</span></p><p style="margin: 0px 0px 18px; padding: 0px; color: #333333; line-height: 18px; font-family: 'Microsoft Yahei', Tahoma, Arial, Helvetica, sans-serif; font-size: 12px; font-weight: normal; background-color: #ffffff; "><span style="font-family: Arial; ">By QingWu</span></p></h2><a href="http://blog.linezing.com/2011/01/%E5%89%96%E6%9E%90-epoll-etlt-%E8%A7%A6%E5%8F%91%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%A7%E8%83%BD%E5%B7%AE%E5%BC%82%E8%AF%AF%E8%A7%A3%EF%BC%88%E5%AE%9A%E6%80%A7%E5%88%86%E6%9E%90%EF%BC%89"><br /></a><img src ="http://www.cppblog.com/Leaf/aggbug/198061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2013-02-25 13:05 <a href="http://www.cppblog.com/Leaf/archive/2013/02/25/198061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>代颜色的提示信息输出。</title><link>http://www.cppblog.com/Leaf/archive/2010/08/20/124041.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Thu, 19 Aug 2010 17:00:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/08/20/124041.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/124041.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/08/20/124041.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/124041.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/124041.html</trackback:ping><description><![CDATA[前几天在网上搜到一段改变控制台字符颜色的代码，用它做了一个代字体颜色的Log输出。感觉还是比较不错的。<br><br>&nbsp;&nbsp;/*<br>&nbsp;&nbsp;0 黑色　1　深蓝　２绿　３浅蓝<br>&nbsp;&nbsp;４暗红　５暗紫　６嫩黄　７浅白<br>&nbsp;&nbsp;８浅灰　９亮蓝　１０亮绿　１１非常蓝<br>&nbsp;&nbsp;１２大红　１３亮紫　１４黄　１５白　<br>&nbsp;&nbsp;*/<br><br>这是那段代码。我已做成了ANSI和UNICODE都支持的版本，具体为什么要这样，可以看前一篇关于字符编码与IO的问题。<br>
<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://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;__Printfc(U16&nbsp;color,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;format,<img src="http://www.cppblog.com/Images/dot.gif">)&nbsp;<br><img id=Codehighlighter1_54_587_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_587_Open_Text.style.display='none'; Codehighlighter1_54_587_Closed_Image.style.display='inline'; Codehighlighter1_54_587_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_54_587_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_587_Closed_Text.style.display='none'; Codehighlighter1_54_587_Open_Image.style.display='inline'; Codehighlighter1_54_587_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_54_587_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_54_587_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;va_list&nbsp;argList;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;U16&nbsp;oldcolor;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hCon</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">GetStdHandle(STD_OUTPUT_HANDLE);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONSOLE_SCREEN_BUFFER_INFO&nbsp;bInfo;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetConsoleScreenBufferInfo(hCon,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">bInfo&nbsp;);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oldcolor&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;bInfo.wAttributes;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(oldcolor</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">color)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetConsoleTextAttribute(hCon,color);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;_UNICODE<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_tsetlocale(LC_CTYPE,TEXT(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;va_start(&nbsp;argList,&nbsp;format&nbsp;);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_tprintf(&nbsp;format,argList);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;va_end(&nbsp;argList&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;_UNICODE<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_tsetlocale(LC_CTYPE,TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(oldcolor</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">color)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetConsoleTextAttribute(hCon,color);&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>
<img src ="http://www.cppblog.com/Leaf/aggbug/124041.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-08-20 01:00 <a href="http://www.cppblog.com/Leaf/archive/2010/08/20/124041.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符输出与编码集的问题。 </title><link>http://www.cppblog.com/Leaf/archive/2010/08/19/123908.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Wed, 18 Aug 2010 17:19:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/08/19/123908.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/123908.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/08/19/123908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/123908.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/123908.html</trackback:ping><description><![CDATA[今天早上起来就兴致脖脖地开始编写引擎的Log输出工具。　一个小时后，基本上完功。　经测试时才发现，原来_tprintf在Unicode下不能输出中文。求解未果，只好去上班了。<br><span>　　晚上回来继续完善早上的工作，将Log输出做成了可以重定向的层次结构，并放入了一个可以共享的Share动态库中。这样就可以保持Log输出系统的唯一和共享（静态Lib中共无法共享）.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用百度搜了一下这个输出问题，突然发现了其中奥妙，原来Unicode需要本地化信息。<br><span>　　经测试发现了如下规律<br>/*<br>&nbsp;&nbsp;　　　&nbsp;C多&nbsp;　CU 　　非C多 　非CU<br>stdio&nbsp;　　&nbsp;1&nbsp;　　0&nbsp;　　　1&nbsp;&nbsp;　　　1<br>iostream　&nbsp;1　　&nbsp;1&nbsp;　　　0&nbsp;　　　&nbsp;0</span></span><br><br><span><span>可以得出<br>１、在多字节时，默认(C）风格下，二者都能输出中文。<br>２、在多字节时，非C风格下，cout不能输出中文<br>３、在U时，默认C风格下，print不能输出中文<br>４、在U时，非C风格下，cout不能输出中文</span></span><br><br><span><span><font color=#ff0000>由此可知，要在C风格下，iostream才能输出中文。<br>而printf只有在C风格的Unicode下才不能输出中文，其它均可。</font><br>*/<br><br>测试代码如下<br>#include &lt;iostream&gt;<br>#include &lt;tchar.h&gt;<br>#include &lt;locale&gt;<br>int _tmain(int argc, _TCHAR* argv[])<br>{<br>#ifdef _UNICODE<br>&nbsp;_tsetlocale(LC_CTYPE,TEXT(""));<br>#endif<br>&nbsp;_tprintf(TEXT("a在哪里啊\n"));<br>#ifdef _UNICODE<br>&nbsp;_tsetlocale(LC_CTYPE,TEXT("C"));<br>#endif</span></span><br><span><span><br>#ifdef _UNICODE<br>&nbsp;std::wcout&lt;&lt;"d在哪里啊"&lt;&lt;std::endl;<br>#else<br>&nbsp;std::cout&lt;&lt;"d在哪里啊"&lt;&lt;std::endl;<br>#endif<br>&nbsp;getchar();<br>&nbsp;return 0;<br>}<br></span></span>
<img src ="http://www.cppblog.com/Leaf/aggbug/123908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-08-19 01:19 <a href="http://www.cppblog.com/Leaf/archive/2010/08/19/123908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>发几个自己做的东西</title><link>http://www.cppblog.com/Leaf/archive/2010/06/20/118321.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sun, 20 Jun 2010 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/06/20/118321.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/118321.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/06/20/118321.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/118321.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/118321.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最大的遗憾莫过于大学里没做过啥像样的东西，许多东西都烂在了学校那破硬盘里，就这点了，有需要的可以下载。<br>代码写得很烂，不是人读的。不过能编译通，能执行。<br><br>其中三维模型导入是用OPENGL+GLUT+VS 2005<br>墙中公主和3D贪食蛇是用的D3DAPI+VC6.0&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/06/20/118321.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/118321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-06-20 22:04 <a href="http://www.cppblog.com/Leaf/archive/2010/06/20/118321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>收录：VC调试技巧</title><link>http://www.cppblog.com/Leaf/archive/2010/05/24/116244.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Mon, 24 May 2010 11:54:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/24/116244.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/116244.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/24/116244.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/116244.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/116244.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 调试是一个程序员最基本的技能，其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言，却不能编制出任何好的软件。<br><br>这里我简要的根据自己的经验列出调试中比较常用的技巧，希望对大家有用。&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/05/24/116244.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/116244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-24 19:54 <a href="http://www.cppblog.com/Leaf/archive/2010/05/24/116244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>发几道关于C++基础知识的题，能不能做自己清楚就行。</title><link>http://www.cppblog.com/Leaf/archive/2010/05/11/115067.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Tue, 11 May 2010 00:52:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/11/115067.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/115067.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/11/115067.html#Feedback</comments><slash:comments>31</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/115067.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/115067.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 下面这些是基础题，“高手”们飘过！！！<br>我想一般公司对语言方面，总会变着方法考下面的这些问题。这只是出现的一种形式。有啥好题欢迎大家分享，下面这些是我自己YY的。看题的兄弟只需在自己心里作答就行，一定不要忘了几乎每题都有一个“ 为什么”。<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/05/11/115067.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/115067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-11 08:52 <a href="http://www.cppblog.com/Leaf/archive/2010/05/11/115067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>讨论会结贴</title><link>http://www.cppblog.com/Leaf/archive/2010/05/09/114942.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sun, 09 May 2010 11:38:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/09/114942.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/114942.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/09/114942.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/114942.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/114942.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 前几天发了一篇关于一个缓冲区溢出问题的讨论。当然是饱受非意。有人说这是撞大运，有人说这是无聊。但是呢，从讨论中，我们发现了更多的问题。学到了更多的知识。 其实许多时候我们有必要“撞大运”，但是在撞大运出问题之后，一定要弄清楚事情的原因。 博友的回复已经充分说明了当时的问题。 但是提出了一个新问题：就是临时变量分配时的空间问题。<br>比如说有分连续分配了3个临时变量，却发现这3个临时变量的址址不是按变量大小连续。（如两个INT变量间相差是12，而非预期的4） 又或者后声明的变量地址却跑在了前头）。 <br>&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/05/09/114942.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/114942.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-09 19:38 <a href="http://www.cppblog.com/Leaf/archive/2010/05/09/114942.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>讨论会：一个不是问题的问题!</title><link>http://www.cppblog.com/Leaf/archive/2010/05/06/114596.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Thu, 06 May 2010 04:41:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/06/114596.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/114596.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/06/114596.html#Feedback</comments><slash:comments>38</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/114596.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/114596.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这段代码在执行时，输出 Success!<br><br><br>不知道各位有何高见！<br>我心中也有一个答案。但先不说，大家一起来讨论。。。 共同完成这篇贴子。 随后，大家的高端回复会以如下方式出现<br>如果不希望最后出现在这里，请大家注明。 默认情况下，表示同意！<br><br>ID：XXXX<br>解释：*****************<br><br><br>=======================<br>ID：XXXXX<br>解释：********************&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/05/06/114596.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/114596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-06 12:41 <a href="http://www.cppblog.com/Leaf/archive/2010/05/06/114596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]深入讲解函数中分配内存问题</title><link>http://www.cppblog.com/Leaf/archive/2010/05/05/114425.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Wed, 05 May 2010 01:02:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/05/114425.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/114425.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/05/114425.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/114425.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/114425.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 开始写了一篇，通过说明他们产生了拷贝，而导致p不能成功分配。但并未提出事实根据，下面我们来仔细看看具体原因。<br><br>我们需要弄清两点：1、main函数中的p与MyNew函数中的p是不是一样；2、如果不一样，是怎么导致了不一样的。<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/05/05/114425.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/114425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-05 09:02 <a href="http://www.cppblog.com/Leaf/archive/2010/05/05/114425.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>冒泡排序与选择排序的不同、快速排序与选择排序的结合</title><link>http://www.cppblog.com/Leaf/archive/2010/05/04/114393.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Tue, 04 May 2010 15:44:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/04/114393.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/114393.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/04/114393.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/114393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/114393.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 目前广为使用的快速排序和选择排序联合使用，也会有意想不到的提升！<br>众所周知，当用快速排序法排序时，划分到很细的时候，明显很亏。 比如：两三个数排序却要划分成两堆，这样很划不来。所以，我们可以设定一个阀值，当快速排序划分到一定粒度的时候，便采用选择排序。 至于这个阀值，可以通过performace来测试，以得到一个“最优值”<br><br>&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/05/04/114393.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/114393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-04 23:44 <a href="http://www.cppblog.com/Leaf/archive/2010/05/04/114393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>某内存池中的指针用法 </title><link>http://www.cppblog.com/Leaf/archive/2010/05/03/114263.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Mon, 03 May 2010 10:33:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/05/03/114263.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/114263.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/05/03/114263.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/114263.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/114263.html</trackback:ping><description><![CDATA[<p>内存池实现有许多种，各有不同的优缺点。</p>
<p>这里不是主要说内存池，只是觉得这个内存池中的指针用得很飘逸！</p>
<p>&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"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;T,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;AllocSize&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MemPool&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img id=Codehighlighter1_58_1247_Open_Image onclick="this.style.display='none'; Codehighlighter1_58_1247_Open_Text.style.display='none'; Codehighlighter1_58_1247_Closed_Image.style.display='inline'; Codehighlighter1_58_1247_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_58_1247_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_58_1247_Closed_Text.style.display='none'; Codehighlighter1_58_1247_Open_Image.style.display='inline'; Codehighlighter1_58_1247_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_58_1247_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_58_1247_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">(size_t&nbsp;allocLength)&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img id=Codehighlighter1_131_454_Open_Image onclick="this.style.display='none'; Codehighlighter1_131_454_Open_Text.style.display='none'; Codehighlighter1_131_454_Closed_Image.style.display='inline'; Codehighlighter1_131_454_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_131_454_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_131_454_Closed_Text.style.display='none'; Codehighlighter1_131_454_Open_Image.style.display='inline'; Codehighlighter1_131_454_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_131_454_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_131_454_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">mStartPotinter)&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img id=Codehighlighter1_175_214_Open_Image onclick="this.style.display='none'; Codehighlighter1_175_214_Open_Text.style.display='none'; Codehighlighter1_175_214_Closed_Image.style.display='inline'; Codehighlighter1_175_214_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_175_214_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_175_214_Closed_Text.style.display='none'; Codehighlighter1_175_214_Open_Image.style.display='inline'; Codehighlighter1_175_214_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_175_214_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_175_214_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyAlloc();&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">将当前指向空闲内存起始地址作为反回地址&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">12</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;mStartPotinter;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取出空闲区域前4字节的值，赋值给空闲地址&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">因为前四字节中存放了下一个BLOCK的地址&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mStartPotinter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)mStartPotinter;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;p;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">&nbsp;delete(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;deleteP)&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img id=Codehighlighter1_516_667_Open_Image onclick="this.style.display='none'; Codehighlighter1_516_667_Open_Text.style.display='none'; Codehighlighter1_516_667_Closed_Image.style.display='inline'; Codehighlighter1_516_667_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_516_667_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_516_667_Closed_Text.style.display='none'; Codehighlighter1_516_667_Open_Image.style.display='inline'; Codehighlighter1_516_667_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_516_667_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_516_667_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert(deletePointer);&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">22</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)deleteP&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;mStartPotinter;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mStartPotinter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)deleteP;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;MyAlloc()&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img id=Codehighlighter1_708_1194_Open_Image onclick="this.style.display='none'; Codehighlighter1_708_1194_Open_Text.style.display='none'; Codehighlighter1_708_1194_Closed_Image.style.display='inline'; Codehighlighter1_708_1194_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_708_1194_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_708_1194_Closed_Text.style.display='none'; Codehighlighter1_708_1194_Open_Image.style.display='inline'; Codehighlighter1_708_1194_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_708_1194_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_708_1194_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">预分配内存&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">29</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mStartPotinter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">[</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(T)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">AllocSize];&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">构造BLOCK之间的关系&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">每个BLOCK的前4BYTE存放了下一个BLOCK的地址&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">32</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">&nbsp;next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)mStartPotinter;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;mStartPotinter;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;AllocSize;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img id=Codehighlighter1_1037_1160_Open_Image onclick="this.style.display='none'; Codehighlighter1_1037_1160_Open_Text.style.display='none'; Codehighlighter1_1037_1160_Closed_Image.style.display='inline'; Codehighlighter1_1037_1160_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1037_1160_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1037_1160_Closed_Text.style.display='none'; Codehighlighter1_1037_1160_Open_Image.style.display='inline'; Codehighlighter1_1037_1160_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1037_1160_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1037_1160_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(T);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">步进&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">38</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;p;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">赋值&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">39</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)p;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">步进&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">40</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">42</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">43</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;mStartPotinter;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">47</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;T,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;AllocSize</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">48</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;MemPool</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T,AllocSize</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::mStartPotinter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">49</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">50</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">51</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>本文来自CSDN博客，转载请标明出处：http:</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">blog.csdn.net/wqjqepr/archive/2010/05/03/5552322.aspx</span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>简单提示一下： unsigned char** next = (unsigned char**)mStartPotinter;</p>
<p>mStartPotinter作为二维指针的时候，相当于是一系列的unsigned char* [].</p>
<p>对于第一个 *next 相当于(unsigned char*)mStartPointer[0].</p>
<p>第二个相当于(unsigned char*)mStartPointer[sizeof(T)*1];</p>
<p>第三个相当于(unsigned char*)mStartPointer[sizeof(T)*2];</p>
<p>所以，构造BLOCK之间关系的时候，也可以写成</p>
<p>&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"><span style="COLOR: #008080">1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;AllocSize;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img id=Codehighlighter1_36_138_Open_Image onclick="this.style.display='none'; Codehighlighter1_36_138_Open_Text.style.display='none'; Codehighlighter1_36_138_Closed_Image.style.display='inline'; Codehighlighter1_36_138_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_36_138_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_36_138_Closed_Text.style.display='none'; Codehighlighter1_36_138_Open_Image.style.display='inline'; Codehighlighter1_36_138_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_36_138_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_36_138_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;p&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(T);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">步进&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">4</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)(p[</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(T)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i]);&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;pp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;p;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">赋值&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">6</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">&nbsp;</span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>不想多解释了，累。估计多看几分种啥都明白了！</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/Leaf/aggbug/114263.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-05-03 18:33 <a href="http://www.cppblog.com/Leaf/archive/2010/05/03/114263.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++ 对象的内存布局</title><link>http://www.cppblog.com/Leaf/archive/2010/04/27/113740.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Tue, 27 Apr 2010 12:56:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2010/04/27/113740.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/113740.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2010/04/27/113740.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/113740.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/113740.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这是陈皓继《C++虚函数表解析》之后的又一大作。<br>讲述了C++对象在以下情况的内存布局。值得一看！<br>1）有成员变量的情况。<br><br>2）有重复继承的情况。<br><br>3）有虚拟继承的情况。<br><br>4）有钻石型虚拟继承的情况。<br><br>还有，对于前几天的贴子表示报歉，今天是直接贴到这里的。 没乱码，还好！！！&nbsp;&nbsp;<a href='http://www.cppblog.com/Leaf/archive/2010/04/27/113740.html'>阅读全文</a><img src ="http://www.cppblog.com/Leaf/aggbug/113740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2010-04-27 20:56 <a href="http://www.cppblog.com/Leaf/archive/2010/04/27/113740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++虚函数表探究</title><link>http://www.cppblog.com/Leaf/archive/2009/07/24/91095.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Fri, 24 Jul 2009 15:52:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2009/07/24/91095.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/91095.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2009/07/24/91095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/91095.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/91095.html</trackback:ping><description><![CDATA[<p>C++中的虚函数的作用主要是实现了多态的机制。关于多态，简而言之就是用父类型别的指针指向其子类的实例，然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有&#8220;多种形态&#8221;，这是一种泛型技术。所谓泛型技术，说白了就是试图使用不变的代码来实现可变的算法。比如：模板技术，RTTI技术，虚函数技术，要么是试图做到在编译时决议，要么试图做到运行时决议。 <br>关于虚函数的使用方法，我在这里不做过多的阐述。大家可以看看相关的C++的书籍。在这篇文章中，我只想从虚函数的实现机制上面为大家 一个清晰的剖析。 <br>当然，相同的文章在网上也出现过一些了，但我总感觉这些文章不是很容易阅读，大段大段的代码，没有图片，没有详细的说明，没有比较，没有举一反三。不利于学习和阅读，所以这是我想写下这篇文章的原因。也希望大家多给我提意见。 <br>言归正传，让我们一起进入虚函数的世界。 <br>虚函数表<br>对C++ 了解的人都应该知道虚函数（Virtual Function）是通过一张虚函数表（Virtual Table）来实现的。简称为V-Table。 在这个表中，主是要一个类的虚函数的地址表，这张表解决了继承、覆盖的问题，保证其容真实反应实际的函数。这样，在有虚函数的类的实例中这个表被分配在了 这个实例的内存中，所以，当我们用父类的指针来操作一个子类的时候，这张虚函数表就显得由为重要了，它就像一个地图一样，指明了实际所应该调用的函数。 <br>这里我们着重看一下这张虚函数表。在C++的标准规格说明书中说到，编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置（这是为了保证正确取到虚函数的偏移量）。 这意味着我们通过对象实例的地址得到这张虚函数表，然后就可以遍历其中函数指针，并调用相应的函数。 <br>听我扯了那么多，我可以感觉出来你现在可能比以前更加晕头转向了。 没关系，下面就是实际的例子，相信聪明的你一看就明白了。 <br>假设我们有这样的一个类： <br>class Base { <br>public: <br>virtual void f() { cout &lt;&lt; "Base::f" &lt;&lt; endl; } <br>virtual void g() { cout &lt;&lt; "Base::g" &lt;&lt; endl; } <br>virtual void h() { cout &lt;&lt; "Base::h" &lt;&lt; endl; } <br>}; <br>按照上面的说法，我们可以通过Base的实例来得到虚函数表。 下面是实际例程： <br>typedef void(*Fun)(void); <br>Base b; <br>Fun pFun = NULL; <br>cout &lt;&lt; "虚函数表地址：" &lt;&lt; (int*)(&amp;b) &lt;&lt; endl; <br>cout &lt;&lt; "虚函数表 — 第一个函数地址：" &lt;&lt; (int*)*(int*)(&amp;b) &lt;&lt; endl; <br>// Invoke the first virtual function <br>pFun = (Fun)*((int*)*(int*)(&amp;b)); <br>pFun(); <br>实际运行经果如下：(Windows XP+VS2003, Linux 2.6.22 + GCC 4.1.3) <br>虚函数表地址：0012FED4 <br>虚函数表 — 第一个函数地址：0044F148 <br>Base::f <br>通过这个示例，我们可以看到，我们可以通过强行把&amp;b转成int *，取得虚函数表的地址，然后，再次取址就可以得到第一个虚函数的地址了，也就是Base::f()，这在上面的程序中得到了验证（把int* 强制转成了函数指针）。通过这个示例，我们就可以知道如果要调用Base::g()和Base::h()，其代码如下： <br>(Fun)*((int*)*(int*)(&amp;b)+0); // Base::f() <br>(Fun)*((int*)*(int*)(&amp;b)+1); // Base::g() <br>(Fun)*((int*)*(int*)(&amp;b)+2); // Base::h() <br>这个时候你应该懂了吧。什么？还是有点晕。也是，这样的代码看着太乱了。没问题，让我画个图解释一下。如下所示： </p>
<p><br>注意：在上面这个图中，我在虚函数表的最后多加了一个结点，这是虚函数表的结束结点，就像字符串的结束符&#8220;\0&#8221;一样，其标志了虚函数表的结束。这个结束标志的值在不同的编译器下是不同的。在WinXP+VS2003下，这个值是NULL。而在Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3下，这个值是如果1，表示还有下一个虚函数表，如果值是0，表示是最后一个虚函数表。 <br>下面，我将分别说明&#8220;无覆盖&#8221;和&#8220;有覆盖&#8221;时的虚函数表的样子。没有覆盖父类的虚函数是毫无意义的。我之所以要讲述没有覆盖的情况，主要目的是为了给一个对比。在比较之下，我们可以更加清楚地知道其内部的具体实现。 <br>一般继承（无虚函数覆盖）<br>下面，再让我们来看看继承时的虚函数表是什么样的。假设有如下所示的一个继承关系：<br>&nbsp; </p>
<p>请注意，在这个继承关系中，子类没有重载任何父类的函数。那么，在派生类的实例中，其虚函数表如下所示： <br>对于实例：Derive d; 的虚函数表如下：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>我们可以看到下面几点： <br>1）虚函数按照其声明顺序放于表中。 <br>2）父类的虚函数在子类的虚函数前面。 <br>我相信聪明的你一定可以参考前面的那个程序，来编写一段程序来验证。 <br>一般继承（有虚函数覆盖）<br>覆盖父类的虚函数是很显然的事情，不然，虚函数就变得毫无意义。下面，我们来看一下，如果子类中有虚函数重载了父类的虚函数，会是一个什么样子？假设，我们有下面这样的一个继承关系。 </p>
<p>为了让大家看到被继承过后的效果，在这个类的设计中，我只覆盖了父类的一个函数：f()。那么，对于派生类的实例，其虚函数表会是下面的一个样子：<br>&nbsp; </p>
<p>我们从表中可以看到下面几点， <br>1）覆盖的f()函数被放到了虚表中原来父类虚函数的位置。 <br>2）没有被覆盖的函数依旧。 <br>这样，我们就可以看到对于下面这样的程序， <br>Base *b = new Derive(); <br>b-&gt;f(); <br>由b所指的内存中的虚函数表的f()的位置已经被Derive::f()函数地址所取代，于是在实际调用发生时，是Derive::f()被调用了。这就实现了多态。 <br>多重继承（无虚函数覆盖）<br>下面，再让我们来看看多重继承中的情况，假设有下面这样一个类的继承关系。注意：子类并没有覆盖父类的函数。 </p>
<p><br>对于子类实例中的虚函数表，是下面这个样子： </p>
<p>&nbsp;</p>
<p><br>我们可以看到： <br>1） 每个父类都有自己的虚表。 <br>2） 子类的成员函数被放到了第一个父类的表中。（所谓的第一个父类是按照声明顺序来判断的） <br>这样做就是为了解决不同的父类类型的指针指向同一个子类实例，而能够调用到实际的函数。 <br>多重继承（有虚函数覆盖）<br>下面我们再来看看，如果发生虚函数覆盖的情况。 <br>下图中，我们在子类中覆盖了父类的f()函数。 </p>
<p>下面是对于子类实例中的虚函数表的图： <br>&nbsp;</p>
<p>我们可以看见，三个父类虚函数表中的f()的位置被替换成了子类的函数指针。这样，我们就可以任一静态类型的父类来指向子类，并调用子类的f()了。如： <br>Derive d; <br>Base1 *b1 = &amp;d; <br>Base2 *b2 = &amp;d; <br>Base3 *b3 = &amp;d; <br>b1-&gt;f(); //Derive::f() <br>b2-&gt;f(); //Derive::f() <br>b3-&gt;f(); //Derive::f() <br>b1-&gt;g(); //Base1::g() <br>b2-&gt;g(); //Base2::g() <br>b3-&gt;g(); //Base3::g() <br>安全性<br>每次写C++的文章，总免不了要批判一下C++。这篇文章也不例外。通过上面的讲述，相信我们对虚函数表有一个比较细致的了解了。水可载舟，亦可覆舟。下面，让我们来看看我们可以用虚函数表来干点什么坏事吧。 <br>一、通过父类型的指针访问子类自己的虚函数 <br>我们知道，子类没有重载父类的虚函数是一件毫无意义的事情。因为多态也是要基于函数重载的。虽然在上面的图中我们可以看到Base1的虚表中有Derive的虚函数，但我们根本不可能使用下面的语句来调用子类的自有虚函数： <br>Base1 *b1 = new Derive(); <br>b1-&gt;f1(); //编译出错 <br>任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法，所以，这样的程序根本无法编译通过。但在运行时，我们可以通过指针的方式访问虚函数表来达到违反C++语义的行为。（关于这方面的尝试，通过阅读后面附录的代码，相信你可以做到这一点） <br>二、访问non-public的虚函数 <br>另外，如果父类的虚函数是private或是protected的，但这些非public的虚函数同样会存在于虚函数表中，所以，我们同样可以使用访问虚函数表的方式来访问这些non-public的虚函数，这是很容易做到的。 <br>如： <br>class Base { <br>private: <br>virtual void f() { cout &lt;&lt; "Base::f" &lt;&lt; endl; } <br>}; <br>class Derive : public Base{ <br>}; <br>typedef void(*Fun)(void); <br>void main() { <br>Derive d; <br>Fun pFun = (Fun)*((int*)*(int*)(&amp;d)+0); <br>pFun(); <br>} </p>
<img src ="http://www.cppblog.com/Leaf/aggbug/91095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2009-07-24 23:52 <a href="http://www.cppblog.com/Leaf/archive/2009/07/24/91095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] extern "C"</title><link>http://www.cppblog.com/Leaf/archive/2009/05/17/83229.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sun, 17 May 2009 15:46:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2009/05/17/83229.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/83229.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2009/05/17/83229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/83229.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/83229.html</trackback:ping><description><![CDATA[<div class=postbody>
<p>前些天，编程序是用到了很久以前写的C程序，想把里面的函数利用起来，连接发现出现了找不到具体函数的错误：</p>
<p>以下是假设旧的C程序库</p>
<p>C的头文件</p>
<pre><em><font color=#999999>/*-----------c.h--------------*/</font></em><font color=#000099><br>#ifndef _C_H_<br>#define _C_H_<br></font><font color=#990000>extern</font><font color=#ff6633> int</font> add<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font> x<strong><font color=#663300>,</font></strong><font color=#ff6633> int</font> y<strong><font color=#663300>);</font></strong><font color=#000099><br>#endif</font></pre>
<p>C的源文件</p>
<pre><em><font color=#999999>/*-----------c.c--------------*/</font></em><font color=#ff6633><br>int</font> add<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font> x<strong><font color=#663300>,</font></strong><font color=#ff6633> int</font> y<strong><font color=#663300>){</font></strong><font color=#ff0000><br>	return</font> x<strong><font color=#663300>+</font></strong>y<strong><font color=#663300>;<br>}</font></strong><br></pre>
<p>C++的调用</p>
<pre><em><font color=#999999>/*-----------cpp.cpp--------------*/</font></em><font color=#000099><br>#include "c.h"<br></font><font color=#ff6633>void</font><font color=#990000> main</font><strong><font color=#663300>()<br>{</font></strong><br>	add<strong><font color=#663300>(</font></strong><font color=#999900>1</font><strong><font color=#663300>,</font></strong><font color=#999900> 0</font><strong><font color=#663300>);<br>}</font></strong><br></pre>
<p>这样编译会产生错误cpp.obj : error LNK2001: unresolved external symbol "int __cdecl add(int,int)" (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#97;&#100;&#100;&#64;&#64;&#89;&#65;&#72;&#72;&#72;&#64;&#90;"><font color=#005880>?add@@YAHHH@Z</font></a>)，原因是找不到add的目标模块</p>
<p>这才令我想起C++重载的函数命名方式和C函数的命名方式，让我们回顾一下：C中函数编译后命名会在函数名前加以"_",比如add函数编译成obj文件时的实际命名为_add，而c++命名则不同，为了实现函数重载同样的函数名add因参数的不同会被编译成不同的名字</p>
<p>例如</p>
<p>int add(int , int)==&gt;<font color=#0000ff><u>add@@YAHHH@Z,</u></font></p>
<p><font color=#0000ff><font color=#000000>float add(float , float )==&gt;</font></font><font color=#0000ff><u>add@@YAMMM@Z</u></font><font color=#000000>,</font></p>
<p>以上是VC6的命名方式，不同的编译器会不同，总之不同的参数同样的函数名将编译成不同目标名，以便于函数重载是调用具体的函数。</p>
<p>编译cpp.cpp中编译器在cpp文件中发现add<strong><font color=#663300>(</font></strong><font color=#999900>1</font><strong><font color=#663300>,</font></strong><font color=#999900> 0</font><strong><font color=#663300>);</font></strong>的调用而函数声明为<font color=#990000>extern</font><font color=#ff6633> int</font> add<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font> x<strong><font color=#663300>,</font></strong><font color=#ff6633> int</font> y<font color=#663300><strong>);</strong></font><font color=#000000>编译器就决定去找</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#100;&#64;&#64;&#89;&#65;&#72;&#72;&#72;&#64;&#90;"><font color=#005880>add@@YAHHH@Z</font></a><font color=#000000>，可惜他找不到，因为C的源文件把<font color=#990000>extern</font><font color=#ff6633> int</font> add<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font> x<strong><font color=#663300>,</font></strong><font color=#ff6633> int</font> y<font color=#663300><strong>);</strong></font></font><font color=#000000>编译成_add了；</font></p>
<p>为了解决这个问题C++采用了extern "C",这就是我们的主题，想要利用以前的C程序库，那么你就要学会它，我们可以看以下标准头文件你会发现，很多头文件都有以下的结构</p>
<pre><font color=#000099>#ifndef __H<br>#define __H<br>#ifdef __cplusplus<br></font><font color=#990000>extern</font><font color=#009900> "C"</font><strong><font color=#663300> {</font></strong><font color=#000099><br>#endif<br></font><font color=#990000><br>extern</font><font color=#ff6633> int</font> f1<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font><strong><font color=#663300>,</font></strong><font color=#ff6633> int</font><strong><font color=#663300>);</font></strong><font color=#990000><br>extern</font><font color=#ff6633> int</font> f2<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font><strong><font color=#663300>,</font></strong><font color=#ff6633> int</font><strong><font color=#663300>);</font></strong><font color=#990000><br>extern</font><font color=#ff6633> int</font> f3<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font><strong><font color=#663300>,</font></strong><font color=#ff6633> int</font><strong><font color=#663300>);</font></strong><font color=#000099><br><br>	<br>#ifdef __cplusplus<br></font><strong><font color=#663300>}</font></strong><font color=#000099><br>#endif<br><br>#endif /*__H*/<br></font></pre>
<p>如果我们仿制该头文件可以得到</p>
<pre><font color=#000099>#ifndef _C_H_<br>#define _C_H_<br>#ifdef __cplusplus<br></font><font color=#990000>extern</font><font color=#009900> "C"</font><strong><font color=#663300> {</font></strong><font color=#000099><br>#endif<br></font><font color=#990000><br>extern</font><font color=#ff6633> int</font> add<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font><strong><font color=#663300>,</font></strong><font color=#ff6633> int</font><strong><font color=#663300>);</font></strong><font color=#000099><br><br>#ifdef __cplusplus<br></font><strong><font color=#663300>}</font></strong><font color=#000099><br>#endif<br><br>#endif /* _C_H_ */ <br></font></pre>
<p><font color=#000099><font color=#000000>这样编译</font></font></p>
<p><font color=#000099><font color=#999999><em>/*-----------c.c--------------*/</em></font><font color=#ff6633><br>int</font><font color=#000000> add</font><strong><font color=#663300>(</font></strong><font color=#ff6633>int</font><font color=#000000> x</font><strong><font color=#663300>,</font></strong><font color=#ff6633> int</font><font color=#000000> y</font><strong><font color=#663300>){</font></strong><font color=#ff0000><br>return</font><font color=#000000> x</font><strong><font color=#663300>+</font></strong><font color=#000000>y</font><strong><font color=#663300>;<br>}</font></strong><br></font></p>
<p><font color=#000099><font color=#000000>这时源文件为*.c，</font><font color=#000099>__cplusplus没有被定义，<font color=#990000>extern</font><font color=#009900> "C"</font><font color=#663300><strong> {}</strong></font><font color=#000000>这时没有生效对于C他看到只是<font color=#990000>extern</font><font color=#ff6633> int</font> add<strong><font color=#663300>(</font></strong><font color=#ff6633>int</font><strong><font color=#663300>,</font></strong><font color=#ff6633> int</font><strong><font color=#663300>);</font></strong><font color=#000099><br></font>add函数编译成_add(int, int);</font></font></font></p>
<p><font color=#000099><font color=#000099><font color=#000000>而编译c++源文件</font></font></font></p>
<p><font color=#000099><font color=#000099><font color=#999999><em>/*-----------cpp.cpp--------------*/</em></font><font color=#000099><br>#include "c.h"<br></font><font color=#ff6633>void</font><font color=#990000> main</font><strong><font color=#663300>()<br>{</font></strong><br><font color=#000000>add</font><strong><font color=#663300>(</font></strong><font color=#999900>1</font><strong><font color=#663300>,</font></strong><font color=#999900> 0</font><strong><font color=#663300>);<br>}</font></strong><br><font color=#000000>这时源文件为*.cpp,</font><font color=#000099>__cplusplus被定义,对于C++他看到的是<font color=#990000>extern</font><font color=#009900> "C"</font><font color=#663300><strong> {</strong><font color=#990000>extern</font><font color=#ff6633> int</font><font color=#000000> add</font><font color=#663300><strong>(</strong></font><font color=#ff6633>int</font><font color=#663300><strong>,</strong></font><font color=#ff6633> int</font><strong><font color=#663300>);</font>}</strong></font><font color=#000000>编译器就会知道 add<strong><font color=#663300>(</font></strong><font color=#999900>1</font><strong><font color=#663300>,</font></strong><font color=#999900> 0</font><font color=#663300><strong>);调用的C风格的函数，就会知道去c.obj中找_add(int, int)而不是</strong><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#100;&#64;&#64;&#89;&#65;&#72;&#72;&#72;&#64;&#90;"><font color=#005880>add@@YAHHH@Z</font></a>；</font></font></font></font></font></p>
<font color=#000099><font color=#000099><font color=#000099><font color=#663300>这也就为什么DLL中常看见<font color=#990000>extern</font><font color=#009900> "C"</font><font color=#663300><strong> {}，</strong>windows是采用C语言编制他首先要考虑到C可以正确调用这些DLL，而用户可能会使用C++而<font color=#990000>extern</font><font color=#009900> "C"</font><font color=#663300><strong> {}就会发生作用</strong></font></font></font></font></font></font></div>
<script type=text/javascript>
//<![cdata[
Sys.WebForms.PageRequestManager._initialize('AjaxHolder$scriptmanager1', document.getElementById('Form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tAjaxHolder$UpdatePanel1'], [], [], 90);
//]]&gt;
</script>
<img src ="http://www.cppblog.com/Leaf/aggbug/83229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2009-05-17 23:46 <a href="http://www.cppblog.com/Leaf/archive/2009/05/17/83229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++中宏的使用</title><link>http://www.cppblog.com/Leaf/archive/2009/05/17/83228.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sun, 17 May 2009 15:41:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2009/05/17/83228.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/83228.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2009/05/17/83228.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/83228.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/83228.html</trackback:ping><description><![CDATA[<div class=postbody>关于## 和 #及#@的用法<br><br><br><span style="COLOR: red">##</span> 是连接符号 连接两个宏,##被称为连接符（concatenator），用来将两个Token连接为一个Token。注意这里连接的对象是Token就行，而不一定是宏的变 <br>量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组，并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那就可以使用：宏参数## <br>固定部分。当然还可以n个##符号连接 n+1个Token，这个特性也是#符号所不具备的。 <br>#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d<br>typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);<br>// 这里这个语句将展开为：<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct _record_type name_company_position_salary;<br><br><br><span style="COLOR: red">#@</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 功能是将其后面的宏参数进行字符化。<br><br>#define makechar(x)&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#35;&#64;&#120;&#97;"><font color=#005880>#@x<br>a</font></a> = makechar(b);<br>//a = 'b';<br><br><br><span style="COLOR: red">#</span>&nbsp;&nbsp; 是把名字代替成字符串,宏体中，#的功能是将其后面的宏参数进行字符串化操作（Stringfication），简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个 <br>双引号。<br>#define WARN_IF(EXP)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do{ if (EXP)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, "Warning: " #EXP "\n"); }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(0)<br>那么实际使用中会出现下面所示的替换过程： <br>WARN_IF (divider == 0);<br>被替换为<br>do {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (divider == 0)<br>fprintf(stderr, "Warning" "divider == 0" "\n");<br>} while(0);<br>这样每次divider（除数）为0的时候便会在标准错误流上输出一个提示信息。 <br><br><br><span style="COLOR: red">
<dt><strong>!IF </strong><span class=parameter>constantexpression</span>
<dd>
<p>如果 <span class=parameter>constantexpression</span> 计算结果为非零值，则处理 <strong>!IF</strong> 和下一个 <strong>!ELSE</strong> 或 <strong>!ENDIF</strong> 之间的语句。<br><strong>!ENDIF</strong> </p>
</dd><span style="COLOR: red"><span style="COLOR: red"><font style="FONT-SIZE: 12pt" face=#ce_temp_font#>
<dd>
<p>标记 <strong>!IF</strong>、<strong>!IFDEF</strong> 或 <strong>!IFNDEF</strong> 块的结尾。同一行上 <strong>!ENDIF</strong> 后面的所有文本被忽略。</p>
</font></dd></span>
<dd></dd></span>
<dd></dd></span>
<dd></dd></div>
<script type=text/javascript>
//<![cdata[
Sys.WebForms.PageRequestManager._initialize('AjaxHolder$scriptmanager1', document.getElementById('Form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tAjaxHolder$UpdatePanel1'], [], [], 90);
//]]&gt;
</script>
<img src ="http://www.cppblog.com/Leaf/aggbug/83228.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2009-05-17 23:41 <a href="http://www.cppblog.com/Leaf/archive/2009/05/17/83228.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]通过例子学习Lua</title><link>http://www.cppblog.com/Leaf/archive/2009/05/16/83145.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sat, 16 May 2009 13:37:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2009/05/16/83145.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/83145.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2009/05/16/83145.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/83145.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/83145.html</trackback:ping><description><![CDATA[<p><span class=tpc_content>据说本文作者是OGDEV的HACK达人</span></p>
<p>通过例子学习Lua(1) ---- Hello World</p>
<p>1.前言<br>游戏中少不了用到脚本语言. Lua是一种和C/C++结合非常紧密的脚本语言，效率极高。<br>一般是对时间要求比较高的地方用C++写，而经常需要改动的地方用Lua写。</p>
<p>偶最近在学习Lua, 所以写出心得和大家共享. Lua是一种完全免费的脚本语言,<br>它的官方网站在<a href="http://www.lua.org/"><u><font color=#0000ff>http://www.lua.org</font></u></a>.在网站上可以下载到lua的源码, 没有可<br>执行版本, 不过不用担心, 因为lua源码可以在任何一种C/C++的编译器上编译.</p>
<p>如果要学习Lua, 官方网站上的Reference是必备的，上面有每个命令的用法，非常详<br>细。<br>参考手册 <a href="http://www.lua.org/manual/5.0/"><u><font color=#0000ff>http://www.lua.org/manual/5.0/</font></u></a><br>作者写的Programming in Lua <a href="http://www.lua.org/pil/"><u><font color=#0000ff>http://www.lua.org/pil/</font></u></a></p>
<p>2.编译<br>如果用的VC, 可以下载所需的project文件,地址在<br><a href="http://sourceforge.net/project/showfiles.php?group_id=32250&amp;package_id=115604"><u><font color=#0000ff>http://sourceforge.net/project/showfiles.php?group_id=32250&amp;package_id=115604</font></u></a><br>偶用的是cygwin和linux, 打入以下命令即可,<br>tar -zxvf lua-5.0.2.tar.gz<br>cd lua-5.0.2<br>sh ./configure<br>make<br>这样就OK了。<br>为了以后使用方便，最好把bin目录加入到path里面。</p>
<p>3."Hello, world!"<br>现在开始偶们的第一个小程序"Hello, world!"<br>把以下程序打入文件e01.lua</p>
<p>例1:e01.lua<br>-- Hello World in Lua <br>print("Hello World.")</p>
<p>Lua有两种执行方式，一种是嵌入到C程序中执行，还有一种是直接从命令行方式下执<br>行。<br>这里为了调试方便，采用第二种方式，执行命令 lua e01.lua</p>
<p>输出结果应该是：<br>Hello World.</p>
<p>4.程序说明<br>第一行 -- Hello World in Lua<br>这句是注释，其中--和C++中的//意思是一样的<br>第二行 print("Hello World.")<br>调用lua内部命令print，输出"Hello World."字符串到屏幕，Lua中的字符串全部是<br>由"括起来的。<br>这个命令是一个函数的调用，print是lua的一个函数，而"Hello World."是print的参<br>数。</p>
<p>5.试试看<br>在Lua中有不少字符串的处理操作，本次的课后试试看的内容就是，找出连接两个字符串<br>的操作，<br>并且print出来。<br>--<br></p>
<p>通过例子学习Lua(2) --- Lua基础</p>
<p>1. 函数的使用<br>以下程序演示了如何在Lua中使用函数, 及局部变量<br>例e02.lua<br>-- functions <br>function pythagorean(a, b)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local c2 = a^2 + b^2&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sqrt(c2) <br>end <br>print(pythagorean(3,4))</p>
<p>运行结果<br>5</p>
<p>程序说明<br>在Lua中函数的定义格式为:<br>function 函数名(参数)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>end<br>与Pascal语言不同, end不需要与begin配对, 只需要在函数结束后打个end就可以了.<br>本例函数的作用是已知直角三角形直角边, 求斜边长度. 参数a,b分别表示直角边长,<br>在函数内定义了local形变量用于存储斜边的平方. 与C语言相同, 定义在函数内的代<br>码不会被直接执行, 只有主程序调用时才会被执行.<br>local表示定义一个局部变量, 如果不加local刚表示c2为一个全局变量, local的作用域<br>是在最里层的end和其配对的关键字之间, 如if ... end, while ... end等。全局变量<br>的<br>作用域是整个程序。</p>
<p>2. 循环语句<br>例e03.lua<br>-- Loops <br>for i=1,5 do&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("i is now " .. i) <br>end</p>
<p>运行结果<br>i is now 1 <br>i is now 2 <br>i is now 3 <br>i is now 4 <br>i is now 5</p>
<p>程序说明<br>这里偶们用到了for语句<br>for 变量 = 参数1, 参数2, 参数3 do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 循环体<br>end<br>变量将以参数3为步长, 由参数1变化到参数2<br>例如:&nbsp;&nbsp;&nbsp;<br>for i=1,f(x) do print(i) end<br>for i=10,1,-1 do print(i) end</p>
<p>这里print("i is now " .. i)中，偶们用到了..，这是用来连接两个字符串的，<br>偶在(1)的试试看中提到的，不知道你们答对了没有。<br>虽然这里i是一个整型量，Lua在处理的时候会自动转成字符串型，不需偶们费心。</p>
<p>3. 条件分支语句<br>例e04.lua<br>-- Loops and conditionals <br>for i=1,5 do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;i is now &#8220; .. i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i &lt; 2 then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;small&#8221;)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif i &lt; 4 then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;medium&#8221;)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;big&#8221;)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end <br>end</p>
<p>运行结果<br>i is now 1 <br>small <br>i is now 2 <br>medium <br>i is now 3 <br>medium <br>i is now 4 <br>big <br>i is now 5 <br>big</p>
<p>程序说明<br>if else用法比较简单, 类似于C语言, 不过此处需要注意的是整个if只需要一个end,<br>哪怕用了多个elseif, 也是一个end.<br>例如<br>&nbsp;&nbsp;&nbsp; if op == "+" then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = a + b<br>&nbsp;&nbsp;&nbsp; elseif op == "-" then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = a - b<br>&nbsp;&nbsp;&nbsp; elseif op == "*" then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = a*b<br>&nbsp;&nbsp;&nbsp; elseif op == "/" then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r = a/b<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error("invalid operation")<br>&nbsp;&nbsp;&nbsp; end</p>
<p><br>4.试试看<br>Lua中除了for循环以外, 还支持多种循环, 请用while...do和repeat...until改写本文<br>中的for程序</p>
<p>--<br>通过例子学习Lua(3) ---- 数据结构 <br><br>1.简介 <br>Lua语言只有一种基本数据结构, 那就是table, 所有其他数据结构如数组啦, <br>类啦, 都可以由table实现. <br><br>2.table的下标 <br>例e05.lua <br>-- Arrays <br>myData = {} <br>myData[0] = &#8220;foo&#8221; <br>myData[1] = 42 <br><br>-- Hash tables <br>myData[&#8220;bar&#8221;] = &#8220;baz&#8221; <br><br>-- Iterate through the <br>-- structure <br>for key, value in myData do <br>print(key .. &#8220;=&#8220; .. value) <br>end <br><br>输出结果 <br>0=foo <br>1=42 <br>bar=baz <br><br>程序说明 <br>首先定义了一个table myData={}, 然后用数字作为下标赋了两个值给它. 这种 <br>定义方法类似于C中的数组, 但与数组不同的是, 每个数组元素不需要为相同类型, <br>就像本例中一个为整型, 一个为字符串. <br><br>程序第二部分, 以字符串做为下标, 又向table内增加了一个元素. 这种table非常 <br>像STL里面的map. table下标可以为Lua所支持的任意基本类型, 除了nil值以外. <br><br>Lua对Table占用内存的处理是自动的, 如下面这段代码 <br>a = {} <br>a["x"] = 10 <br>b = a -- `b' refers to the same table as `a' <br>print(b["x"]) --&gt; 10 <br>b["x"] = 20 <br>print(a["x"]) --&gt; 20 <br>a = nil -- now only `b' still refers to the table <br>b = nil -- now there are no references left to the table <br>b和a都指向相同的table, 只占用一块内存, 当执行到a = nil时, b仍然指向table, <br>而当执行到b=nil时, 因为没有指向table的变量了, 所以Lua会自动释放table所占内存 <br><br>3.Table的嵌套 <br>Table的使用还可以嵌套，如下例 <br>例e06.lua <br>-- Table &#8216;constructor&#8217; <br>myPolygon = { <br>color=&#8220;blue&#8221;, <br>thickness=2, <br>npoints=4; <br>{x=0, y=0}, <br>{x=-10, y=0}, <br>{x=-5, y=4}, <br>{x=0, y=4} <br>} <br><br>-- Print the color <br>print(myPolygon[&#8220;color&#8221;]) <br><br>-- Print it again using dot <br>-- notation <br>print(myPolygon.color) <br><br>-- The points are accessible <br>-- in myPolygon[1] to myPolygon[4] <br><br>-- Print the second point&#8217;s x <br>-- coordinate <br>print(myPolygon[2].x) <br><br>程序说明 <br>首先建立一个table, 与上一例不同的是，在table的constructor里面有{x=0,y=0}, <br>这是什么意思呢？ 这其实就是一个小table, 定义在了大table之内, 小table的 <br>table名省略了. <br>最后一行myPolygon[2].x，就是大table里面小table的访问方式. <br><br>-- <br>通过例子学习Lua(4) -- 函数的调用 <br><br>1.不定参数 <br>例e07.lua <br>-- Functions can take a <br>-- variable number of <br>-- arguments. <br>function funky_print (...) <br>for i=1, arg.n do <br>print("FuNkY: " .. arg) <br>end <br>end <br><br>funky_print("one", "two") <br><br>运行结果 <br>FuNkY: one <br>FuNkY: two <br><br>程序说明 <br>* 如果以...为参数, 则表示参数的数量不定. <br>* 参数将会自动存储到一个叫arg的table中. <br>* arg.n中存放参数的个数. arg[]加下标就可以遍历所有的参数. <br><br><br>2.以table做为参数 <br>例e08.lua <br>-- Functions with table <br>-- parameters <br>function print_contents(t) <br>for k,v in t do <br>print(k .. "=" .. v) <br>end <br>end <br>print_contents{x=10, y=20} <br><br>运行结果 <br>x=10 <br>y=20 <br><br>程序说明 <br>* print_contents{x=10, y=20}这句参数没加圆括号, 因为以单个table为参数的时候, <br>不需要加圆括号 <br>* for k,v in t do 这个语句是对table中的所有值遍历, k中存放名称, v中存放值 <br><br><br>3.把Lua变成类似XML的数据描述语言 <br>例e09.lua <br>function contact(t) <br>-- add the contact &#8216;t&#8217;, which is <br>-- stored as a table, to a database <br>end <br><br>contact { <br>name = "Game Developer", <br>email = "hack@ogdev.net", <br>url = "http://www.ogdev.net, <br>quote = [[ <br>There are <br>10 types of people <br>who can understand binary.]] <br>} <br><br>contact { <br>-- some other contact <br>} <br><br>程序说明 <br>* 把function和table结合, 可以使Lua成为一种类似XML的数据描述语言 <br>* e09中contact{...}, 是一种函数的调用方法, 不要弄混了 <br>* [[...]]是表示多行字符串的方法 <br>* 当使用C API时此种方式的优势更明显, 其中contact{..}部分可以另外存成一配置文 <br>件 <br><br>4.试试看 <br>想想看哪些地方可以用到例e09中提到的配置方法呢？ <br><br>-- <br></p>
<p>通过例子学习Lua(5) ---- Lua与C交互入门 <br><br>1.简介 <br><br>Lua与C/C++结合是很紧密的, Lua与C++交互是建立在Lua与C的基础上的, 所 <br>以偶先从Lua与C讲起. <br><br>正如第一讲所说, 运行Lua程序或者说调用Lua主要有两种方式: <br>* 通过命令行执行"Lua"命令 <br>* 通过Lua的C库 <br>虽然此前偶们一直用第一种方式, 但偶要告诉你, 通过Lua的C库执行才是游戏中 <br>常用的方式. <br><br>2.Lua的C库 <br><br>Lua的C库可以做为Shared Library调用, 但一般开发游戏时会把Lua的所有源程序 <br>都包含在内, 并不把Lua编译成共享库的形式. 因为Lua程序只有100多K, 而且几乎 <br>可以在任何编译器下Clean Compile. 带Lua源程序的另一个好处时, 可以随时对Lua <br>本身进行扩充, 增加偶们所需的功能. <br><br>Lua的C库提供一系列API: <br>* 管理全局变量 <br>* 管理tables <br>* 调用函数 <br>* 定义新函数, 这也可以完全由C实现 <br>* 垃圾收集器Garbage collector, 虽然Lua可以自动进行, 但往往不是立即执行的, <br>所以对实时性要求比较高的程序, 会自己调用垃圾收集器 <br>* 载入并执行Lua程序, 这也可以由Lua自身实现 <br>* 任何Lua可以实现的功能, 都可以通过Lua的C API实现, 这对于优化程序的运行速度 <br>有帮助. 经常调用的共用的Lua程序片断可以转成C程序, 以提高效率. 连Lua都是C写的 <br>还有什么C不能实现呢? <br><br>3.Lua与C集成的例子 <br>例e10.c <br>/* A simple Lua interpreter. */ <br>#include &lt;stdio.h&gt; <br>#include &lt;lua.h&gt; <br>int main(int argc, char *argv[]) { <br>char line[BUFSIZ]; <br>lua_State *L = lua_open(0); <br>while (fgets(line, sizeof(line), stdin) != 0) <br>lua_dostring(L, line); <br>lua_close(L); <br>return 0; <br>} <br><br>编译 <br>Linux/Cygwin <br>* 先编译Lua, 并把头文件放入include路径 <br>* gcc e10.c -llua -llualib -o e10 <br><br>VC6/VC2003 <br>* 先编译Lua, 在Option中设置头文件和库文件路径 <br>* 新建工程,在工程配置中加入附加库lua.lib和lualib.lib <br>* 编译成exe <br><br>运行结果 <br>本程序的功能是实现一个Lua解释器, 输入的每行字符都会被解释成Lua并执行. <br><br>程序说明 <br>* #include &lt;lua.h&gt; 包含lua头文件, 然后才可以使用API <br>* lua_State *L = lua_open(0) 打开一个Lua执行器 <br>* fgets(line, sizeof(line), stdin) 从标准输入里读入一行 <br>* lua_dostring(L, line) 执行此行 <br>* lua_close(L) 关闭Lua执行器 <br><br><br>例e11.c <br>/* Another simple Lua interpreter. */ <br>#include &lt;stdio.h&gt; <br>#include &lt;lua.h&gt; <br>#include &lt;lualib.h&gt; <br>int main(int argc, char *argv[]) { <br>char line[BUFSIZ]; <br>lua_State *L = lua_open(0); <br>lua_baselibopen(L); <br>lua_iolibopen(L); <br>lua_strlibopen(L); <br>lua_mathlibopen(L); <br>while (fgets(line, sizeof(line), stdin) != 0) <br>lua_dostring(L, line); <br>lua_close(L); <br>return 0; <br>} <br><br>运行结果 <br>本程序的功能是实现一个Lua解释器, 输入的每行字符都会被解释成Lua并执行. <br>与上例不同的是, 本例调用了Lua的一些标准库. <br><br>程序说明 <br>* #include &lt;lualib.h&gt; 包含Lua的标准库 <br>* 以下这几行是用来读入Lua的一些库, 这样偶们的Lua程序就可以有更多的功能. <br>lua_baselibopen(L); <br>lua_iolibopen(L); <br>lua_strlibopen(L); <br>lua_mathlibopen(L); <br><br>4.试试看 <br>把上面两个小例子在你熟悉的编译器中编译执行, 并试试能否与Lua源码树一起编译 <br><br>-- <br>通过例子学习Lua(6) ---- C/C++中用Lua函数 <br><br>参考英文文档http://tonyandpaige.com/tutorials/lua2.html <br><br>1.简介 <br>偶们这次主要说说怎么由Lua定义函数, 然后在C或者C++中调用. 这里偶们 <br>暂不涉及C++的对象问题, 只讨论调用函数的参数, 返回值和全局变量的使用. <br><br>2. <br>这里偶们在e12.lua里先定义一个简单的add(), x,y为加法的两个参数, <br>return 直接返回相加后的结果. <br><br>例e12.lua <br>-- add two numbers <br>function add ( x, y ) <br>return x + y <br>end <br><br>在前一次里, 偶们说到 lua_dofile() 可以直接在C中执行lua文件. 因为偶们 <br>这个程序里只定义了一个add()函数, 所以程序执行后并不直接结果, 效果相当 <br>于在C中定义了一个函数一样. <br><br>Lua的函数可以有多个参数, 也可以有多个返回值, 这都是由栈(stack)实现的. <br>需要调用一个函数时, 就把这个函数压入栈, 然后顺序压入所有参数, 然后用 <br>lua_call()调用这个函数. 函数返回后, 返回值也是存放在栈中. 这个过程和 <br>汇编执行函数调用的过程是一样的. <br><br>例e13.cpp 是一个调用上面的Lua函数的例子 <br>#include &lt;stdio.h&gt; <br><br>extern "C" { // 这是个C++程序, 所以要extern "C", <br>// 因为lua的头文件都是C格式的 <br>#include "lua.h" <br>#include "lualib.h" <br>#include "lauxlib.h" <br>} <br><br>/* the Lua interpreter */ <br>lua_State* L; <br><br>int luaadd ( int x, int y ) <br>{ <br>int sum; <br><br>/* the function name */ <br>lua_getglobal(L, "add"); <br><br>/* the first argument */ <br>lua_pushnumber(L, x); <br><br>/* the second argument */ <br>lua_pushnumber(L, y); <br><br>/* call the function with 2 <br>arguments, return 1 result */ <br>lua_call(L, 2, 1); <br><br>/* get the result */ <br>sum = (int)lua_tonumber(L, -1); <br>lua_pop(L, 1); <br><br>return sum; <br>} <br><br>int main ( int argc, char *argv[] ) <br>{ <br>int sum; <br><br>/* initialize Lua */ <br>L = lua_open(); <br><br>/* load Lua base libraries */ <br>lua_baselibopen(L); <br><br>/* load the script */ <br>lua_dofile(L, "e12.lua"); <br><br>/* call the add function */ <br>sum = luaadd( 10, 15 ); <br><br>/* print the result */ <br>printf( "The sum is %d\n", sum ); <br><br>/* cleanup Lua */ <br>lua_close(L); <br><br>return 0; <br>} <br><br>程序说明: <br>main中过程偶们上次已经说过了, 所以这次只说说luaadd的过程 <br>* 首先用lua_getglobal()把add函数压栈 <br>* 然后用lua_pushnumber()依次把x,y压栈 <br>* 然后调用lua_call(), 并且告诉程序偶们有两个参数一个返回值 <br>* 接着偶们从栈顶取回返回值, 用lua_tonumber() <br>* 最后偶们用lua_pop()把返回值清掉 <br><br>运行结果: <br>The sum is 25 <br><br>编译方法 <br>Linux下把程序存成e13.cpp <br>g++ e13.cpp -llua -llualib -o e13 <br>./e13 <br><br>VC下编译方法 <br>* 首先建立一个空的Win32 Console Application Project <br>* 把e13.cpp加入工程中 <br>* 点project setting,然后设置link选项, 再加上lua.lib lualib.lib两个额外的库 <br>* 最后编译 <br><br>建立好的project可以在这里下载 <br>VC http://tonyandpaige.com/tutorials/luaadd.zip <br>Linux http://tonyandpaige.com/tutorials/luaadd.tar.gz <br><br>3.全局变量 <br>上面偶们用到了lua_getglobal()但并没有详细讲, 这里偶们再举两个小例子来说下全局 <br>变量 <br>lua_getglobal()的作用就是把lua中全局变量的值压入栈 <br>lua_getglobal(L, "z"); <br>z = (int)lua_tonumber(L, 1); <br>lua_pop(L, 1); <br>假设Lua程序中定义了一个全局变量z, 这段小程序就是把z的值取出放入C的变量z中. <br><br>另外Lua中还有一个对应的函数lua_setglobal(), 作用是用栈顶的值填充指定的全局变 <br>量 <br>lua_pushnumber(L, 10); <br>lua_setglobal(L, "z"); <br>例如这段小程序就是把lua中的全局变量z设为10, 如果lua中未定义z的话, 就会自动创 <br>建一个 <br>全局变量z并设为10. <br><br>4.试试看 <br>自己写个函数用C/C++来调用下试试 <br><br>-- <br>通过例子学习Lua(7) ---- Lua中调用C/C++函数 <br><br>1.前言 <br>上次偶说到从C/C++中调用Lua的函数, 然后就有朋友问从Lua中如何调用C/C++的 <br>函数, 所以偶们这次就来说说这个问题. 首先偶们会在C++中建立一个函数, 然后 <br>告知Lua有这个函数, 最后再执行它. 另外, 由于函数不是在Lua中定义的, 所以 <br>无法确定函数的正确性, 可能在调用过程中会出错, 因此偶们还会说说Lua出错处 <br>理的问题. <br><br>2.Lua中调用C函数 <br>在lua中是以函数指针的形式调用函数, 并且所有的函数指针都必须满足如下此种 <br>类型: <br>typedef int (*lua_CFunction) (lua_State *L); <br><br>也就是说, 偶们在C++中定义函数时必须以lua_State为参数, 以int为返回值才能 <br>被Lua所调用. 但是不要忘记了, 偶们的lua_State是支持栈的, 所以通过栈可以 <br>传递无穷个参数, 大小只受内存大小限制. 而返回的int值也只是指返回值的个数 <br>真正的返回值都存储在lua_State的栈中. 偶们通常的做法是做一个wrapper, 把 <br>所有需要调用的函数都wrap一下, 这样就可以调用任意的函数了. <br><br>下面这个例子是一个C++的average()函数, 它将展示如何用多个参数并返回多个值 <br><br>例e14.cpp <br>#include &lt;stdio.h&gt; <br><br>extern "C" { <br>#include "lua.h" <br>#include "lualib.h" <br>#include "lauxlib.h" <br>} <br><br>/* the Lua interpreter */ <br>lua_State* L; <br><br>static int average(lua_State *L) <br>{ <br>/* get number of arguments */ <br>int n = lua_gettop(L); <br>double sum = 0; <br>int i; <br><br>/* loop through each argument */ <br>for (i = 1; i &lt;= n; i++) <br>{ <br>/* total the arguments */ <br>sum += lua_tonumber(L, i); <br>} <br><br>/* push the average */ <br>lua_pushnumber(L, sum / n); <br><br>/* push the sum */ <br>lua_pushnumber(L, sum); <br><br>/* return the number of results */ <br>return 2; <br>} <br><br>int main ( int argc, char *argv[] ) <br>{ <br>/* initialize Lua */ <br>L = lua_open(); <br><br>/* load Lua base libraries */ <br>lua_baselibopen(L); <br><br>/* register our function */ <br>lua_register(L, "average", average); <br><br>/* run the script */ <br>lua_dofile(L, "e15.lua"); <br><br>/* cleanup Lua */ <br>lua_close(L); <br><br>return 0; <br>} <br><br>例e15.lua <br>-- call a C++ function <br><br>avg, sum = average(10, 20, 30, 40, 50) <br><br>print("The average is ", avg) <br>print("The sum is ", sum) <br><br><br>程序说明: <br>* lua_gettop()的作用是返回栈顶元素的序号. 由于Lua的栈是从1开始编号的, <br>所以栈顶元素的序号也相当于栈中的元素个数. 在这里, 栈中元素的个数就 <br>是传入的参数个数. <br>* for循环计算所有传入参数的总和. 这里用到了数值转换lua_tonumber(). <br>* 然后偶们用lua_pushnumber()把平均值和总和push到栈中. <br>* 最后, 偶们返回2, 表示有两个返回值. <br>* 偶们虽然在C++中定义了average()函数, 但偶们的Lua程序并不知道, 所以需 <br>要在main函数中加入 <br><br>/* register our function */ <br>lua_register(L, "average", average); <br><br>这两行的作用就是告诉e15.lua有average()这样一个函数. <br>* 这个程序可以存成cpp也可以存成c, 如果以.c为扩展名就不需要加extern "C" <br><br>编译的方法偶们上次说过了, 方法相同. <br>e15.lua执行的方法只能用上例中的C++中执行, 而不能用命令行方式执行. <br><br>3.错误处理 <br>在上例中, 偶们没有对传入的参数是否为数字进行检测, 这样做不好. 所以这里偶 <br>们再加上错误处理的片断. <br><br>把这段加在for循环之内: <br>if (!lua_isnumber(L, i)) { <br>lua_pushstring(L, "Incorrect argument to 'average'"); <br>lua_error(L); <br>} <br>这段的作用就是检测传入的是否为数字. <br><br>加上这段之后, 偶们debug的时候就会简单许多. 对于结合两种语言的编程, 它们之 <br>间传递数据的正确性检测是非常重要的. <br><br>这里有别人写好的例子: <br>VC的 http://tonyandpaige.com/tutorials/luaavg.zip <br>Linux的 http://tonyandpaige.com/tutorials/luaavg.tar.gz <br><br>至此, Lua与C的结合就基本讲完了, 下次偶要开始说说Lua与面向对象. <br>但是偶自己还没有学完, 所以大家可能要多等两天了. Sorry! <br><br>-- <br></p>
<img src ="http://www.cppblog.com/Leaf/aggbug/83145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2009-05-16 21:37 <a href="http://www.cppblog.com/Leaf/archive/2009/05/16/83145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字节填充函数</title><link>http://www.cppblog.com/Leaf/archive/2009/04/18/80320.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sat, 18 Apr 2009 01:58:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2009/04/18/80320.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/80320.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2009/04/18/80320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/80320.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/80320.html</trackback:ping><description><![CDATA[<p>貌似是在《3D游戏编程大师技巧》上看到的这两个函数，当时觉得很牛耶，于是就记下来了，不过至今没有怎么用到，我想估计以后会有用吧。<br><br>//内嵌汇编的用于4字节填充的函数<br>inline&nbsp; void Mem_Set_QUAD(VOID *dest, UINT data, int count )<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; _asm<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp; edi, dest&nbsp; ; edi指向目标内存<br>　　　　　 mov&nbsp; ecx, count&nbsp; ;要移动的３２位字数<br>　　　　　 mov&nbsp; eax, data&nbsp;&nbsp; ;３２位数据<br>　　　　　 rep&nbsp; stosd&nbsp;&nbsp;&nbsp; ;移动数据<br>　　　　　｝//end asm<br>&nbsp;}//end Mem_Set_QUAD</p>
<p>//用于2字节（DWORD)数据填充的函数<br>inline&nbsp; void Mem_Set_WORD(VOID *dest, USHORT data, int count )<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; _asm<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp; edi, dest&nbsp; ; edi指向目标内存<br>　　　　　 mov&nbsp; ecx, count&nbsp; ;要移动的16位字数<br>　　　　　 mov&nbsp; ax, data&nbsp;&nbsp; ;16位数据<br>　　　　　 rep&nbsp; stosw&nbsp;&nbsp;&nbsp; ;移动数据<br>　　　　　｝//end asm<br>&nbsp;}//end Mem_Set_WORD <br><br><br><br></p>
<img src ="http://www.cppblog.com/Leaf/aggbug/80320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2009-04-18 09:58 <a href="http://www.cppblog.com/Leaf/archive/2009/04/18/80320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最原始，最纯朴的快速排序算法</title><link>http://www.cppblog.com/Leaf/archive/2009/01/04/71134.html</link><dc:creator>Render Donkey</dc:creator><author>Render Donkey</author><pubDate>Sun, 04 Jan 2009 07:48:00 GMT</pubDate><guid>http://www.cppblog.com/Leaf/archive/2009/01/04/71134.html</guid><wfw:comment>http://www.cppblog.com/Leaf/comments/71134.html</wfw:comment><comments>http://www.cppblog.com/Leaf/archive/2009/01/04/71134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Leaf/comments/commentRss/71134.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Leaf/services/trackbacks/71134.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p><br>int Partition(int a[],int l,int r)<br>{<br>&nbsp;int p = a[l];//取首元素作为划分点</p>
<p>&nbsp;while(l&lt;r)<br>&nbsp;{<br>&nbsp;&nbsp;while(l&lt;r&amp;&amp; a[r]&gt;=p)<br>&nbsp;&nbsp;&nbsp;--r;<br>&nbsp;&nbsp;a[l] = a[r];</p>
<p>&nbsp;&nbsp;while(l&lt;r&amp;&amp; a[l]&lt;=p)<br>&nbsp;&nbsp;&nbsp;++l;<br>&nbsp;&nbsp;a[r] = a[l];<br>&nbsp;}<br>&nbsp;a[l] = p;<br>&nbsp;return l;<br>}</p>
<p>void QSort(int a[],int l,int r)<br>{<br>&nbsp;int p;<br>&nbsp;if(l&lt;r)<br>&nbsp;{<br>&nbsp;&nbsp;p = Partition(a,l,r);<br>&nbsp;&nbsp;for(int i = l; i&lt; r;++i)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;cout&lt;&lt;a[i]&lt;&lt;" ";<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;cout&lt;&lt;endl;</p>
<p>&nbsp;&nbsp;QSort(a,l,p-1);<br>&nbsp;&nbsp;QSort(a,p+1,r);<br>&nbsp;}<br>}</p>
<img src ="http://www.cppblog.com/Leaf/aggbug/71134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Leaf/" target="_blank">Render Donkey</a> 2009-01-04 15:48 <a href="http://www.cppblog.com/Leaf/archive/2009/01/04/71134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>