??xml version="1.0" encoding="utf-8" standalone="yes"?>狠狠狠色丁香婷婷综合久久五月,国产精品一区二区久久不卡,久久综合色区http://www.shnenglu.com/xlander/category/2270.htmlzh-cnTue, 24 Mar 2009 03:40:42 GMTTue, 24 Mar 2009 03:40:42 GMT60利用位段让数据的含义更清?/title><link>http://www.shnenglu.com/xlander/archive/2007/12/12/38311.html</link><dc:creator>xlander</dc:creator><author>xlander</author><pubDate>Wed, 12 Dec 2007 06:47:00 GMT</pubDate><guid>http://www.shnenglu.com/xlander/archive/2007/12/12/38311.html</guid><wfw:comment>http://www.shnenglu.com/xlander/comments/38311.html</wfw:comment><comments>http://www.shnenglu.com/xlander/archive/2007/12/12/38311.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/xlander/comments/commentRss/38311.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xlander/services/trackbacks/38311.html</trackback:ping><description><![CDATA[     摘要: 使用位段可以化很多东?nbsp; <a href='http://www.shnenglu.com/xlander/archive/2007/12/12/38311.html'>阅读全文</a><img src ="http://www.shnenglu.com/xlander/aggbug/38311.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xlander/" target="_blank">xlander</a> 2007-12-12 14:47 <a href="http://www.shnenglu.com/xlander/archive/2007/12/12/38311.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于如何建立搜烦引擎的几介l性的文章http://www.shnenglu.com/xlander/archive/2006/08/22/11557.htmlxlanderxlanderTue, 22 Aug 2006 02:35:00 GMThttp://www.shnenglu.com/xlander/archive/2006/08/22/11557.htmlhttp://www.shnenglu.com/xlander/comments/11557.htmlhttp://www.shnenglu.com/xlander/archive/2006/08/22/11557.html#Feedback0http://www.shnenglu.com/xlander/comments/commentRss/11557.htmlhttp://www.shnenglu.com/xlander/services/trackbacks/11557.htmlZJAVA技术的搜烦引擎的研I与实现
http://blog.csdn.net/fasttalk/archive/2004/12/23/227178.aspx
介绍了基于英特网的搜索引擎的pȝl构Q然后从|络机器人、烦引引擎、Web服务器三个方面进行详l的说明。利用Java开源代码Lucene、Tomcat{徏立自q搜烦引擎、易于理解?/div>
 
怎么会是lucene?
http://blog.csdn.net/accesine960/archive/2004/12/23/227134.aspx
q篇文章提到了当前能搜烦到的介绍搜烦引擎的文章和站点Q以及简略情c?/div>
 
搜烦引擎l验ȝ
http://blog.csdn.net/xsc2001/archive/2006/04/03/649106.aspx
文中讲述了蜘蛛、切词、烦引、查询器{模块的一些概q和l节Q对搜烦引擎中的初学者的有一定帮?/div>


xlander 2006-08-22 10:35 发表评论
]]>Terrarium - E序?上帝http://www.shnenglu.com/xlander/archive/2006/08/22/11554.htmlxlanderxlanderTue, 22 Aug 2006 02:33:00 GMThttp://www.shnenglu.com/xlander/archive/2006/08/22/11554.htmlhttp://www.shnenglu.com/xlander/comments/11554.htmlhttp://www.shnenglu.com/xlander/archive/2006/08/22/11554.html#Feedback0http://www.shnenglu.com/xlander/comments/commentRss/11554.htmlhttp://www.shnenglu.com/xlander/services/trackbacks/11554.html    早在2001q就有了q个单却复杂的游戏,TerrariumQ即使最新的版本也是在一q前推出的。只是到了现在已l没有多h玩了Q因ZGOOGLE上已l搜索不到可用的服务器了Q只能是在自q服务器上搞个试验Q感受一下做上帝的滋呻I不过也就失去了生物多h的初衷?/div>
    Terrarium是微软公司开发的CZE序Q它是一Ƒ֐软g开发h员全面展C?NET框架应用开发技术的游戏。在Terrarium游戏中,开发h员可以创食动物、肉食动物或植物Qƈ它们放C个基?#8220;适者生?#8221;模型和对{网l结构的生态系l中。游戏既提供了一个可以测试开发h员的软g开发与{略设计水^的竞争环境,也提供了一个近乎真实的q化生物学和人工模型Q以验具有不同行为和属性的生物在生存斗争中的适应能力?br>    在创建生物时Q开发者可以自行决定生物的每一U基本属性(如眼睛的颜色、运动速度、防卫能力、攻击能力等Q,行ؓ方式Q寻N物、活动和q攻的算法等Q以及繁D能力(每隔多长旉J殖一ơ,把哪些基本信息遗传给后代Q。开发好一个生物的所有代码之后,开发者将代码~译?NETE序集(AssemblyQ以DLL动态链接库的方式存放)。本地的生态系l片断可以调入和q行该程序集Qƈ在Terrarium控制C昄一生物?br>
    开发一个生物的q程可能很容易,也可能充满挑战,可能很轻松,也可能需要全力以_关键是你惛_C么样的结果?/div>
 
Terrarium的官方网?/div>
 
Terrarium的中文简?/div>
 
Terrarium中几个比较优U的生物的代码片断


xlander 2006-08-22 10:33 发表评论
]]>有关l胞自动机的略介l?/title><link>http://www.shnenglu.com/xlander/archive/2006/08/22/11553.html</link><dc:creator>xlander</dc:creator><author>xlander</author><pubDate>Tue, 22 Aug 2006 02:32:00 GMT</pubDate><guid>http://www.shnenglu.com/xlander/archive/2006/08/22/11553.html</guid><wfw:comment>http://www.shnenglu.com/xlander/comments/11553.html</wfw:comment><comments>http://www.shnenglu.com/xlander/archive/2006/08/22/11553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/xlander/comments/commentRss/11553.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xlander/services/trackbacks/11553.html</trackback:ping><description><![CDATA[<div> </div> <div>在Hiker的blog上找到几介l元胞自动机的文章,可以_略的了解一下?/div> <div><a >http://www.xjtublog.com/user1/1034/subject/6351.shtml</a> </div> <div> </div> <div>元胞自动机可用来研究很多一般现象。其中包括通信、信息传?Communicahon)、计?(Compulation)、构?(ConsTruction)、生?(Growth)、复?(Reproductionj、竞?Competition)与进?EvolutioQ]){?Smith A.,1969;PerrierQJ.Y.,1996)。同时。它为动力学pȝ理论中有关秩?(Ordering)、紊?(Turbulence)、؜?(Chaos)、非对称(Symmetry-Breaking)、分?Fractality){系l整体行Z复杂现象的研I提供了一个有效的模型工具 (Vichhac。GQ?984; BennettQC,1985)?br></div> <div> </div> <div>GOOGLE搜烦到的几个元胞自动机的应用Q?/div> <div> </div> <div><a >http://nlsc.ustc.edu.cn/</a> </div> <div>中国U技大学非线性科学中?/div> <div> </div> <div><a >http://lgisrs.nju.edu.cn/project.htm</a> </div> <div> <div>农村城市化的元胞自动机模型研I?/div> <div> </div> </div> <div><a >http://pandeng.dlut.edu.cn/NewsView.asp?id=154</a> </div> <div>传染病的二维元胞自动机模?br>Z元胞自动机和Penna模型的生态系l模拟模?/div> <div> </div> <div><a >http://www.zydl.net/Article_Show.asp?ArticleID=2914</a> </div> <div>都市区城市扩展模?/div> <div> </div> <div>周成虎,U学出版C《地理元胞自动机研究》中有基于元胞自动机的林火模?/div> <div> </div> <div><a >http://www.cnblogs.com/maweifeng/articles/255344.html</a> </div> <div>ZMA和CA的交通空间决{模?/div> <div> </div> <div><a >http://www.ncgia.ucsb.edu/projects/gig/project_gig.htm</a> </div> <div>城市扩散模型Q英文)</div> <div> </div> <div><a >http://www.swarmagents.com/complex/models/caintro.htm</a> </div> <div>元胞自动机全ȝ</div> <div> </div> <div><a >http://gz.house.sina.com.cn/news/2005-11-26/1929689.html</a> </div> <div>黎夏Q元胞自动机与多只能体在城市规划中的应用</div> <div class="iiysg4q" id="div_cppblog_ad_article"></div><img src ="http://www.shnenglu.com/xlander/aggbug/11553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xlander/" target="_blank">xlander</a> 2006-08-22 10:32 <a href="http://www.shnenglu.com/xlander/archive/2006/08/22/11553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>公交换乘的初步思?/title><link>http://www.shnenglu.com/xlander/archive/2006/07/21/10293.html</link><dc:creator>xlander</dc:creator><author>xlander</author><pubDate>Fri, 21 Jul 2006 02:13:00 GMT</pubDate><guid>http://www.shnenglu.com/xlander/archive/2006/07/21/10293.html</guid><wfw:comment>http://www.shnenglu.com/xlander/comments/10293.html</wfw:comment><comments>http://www.shnenglu.com/xlander/archive/2006/07/21/10293.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/xlander/comments/commentRss/10293.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xlander/services/trackbacks/10293.html</trackback:ping><description><![CDATA[ <div>思\Q?br />用图Z的最短\径来解决问题?/div> <div> </div> <div> </div> <div>囄创徏Q?br />l点Q公交站炏V?br />边:公交路线在两个站点之间的行路线?/div> <div> <br /> </div> <div>路线的求解:<br />法可以参考最短\径算法?br />以经q的路线的距L旉作ؓ评h标准Q优先选择同一条公交线路的下一站点Q如果发生换乘,以换乘的ơ数辑ֈ限制作ؓ局部中止条Ӟ以便抛弃不必要的遍历q程?/div> <div class="4kkge44" id="div_cppblog_ad_article"></div><img src ="http://www.shnenglu.com/xlander/aggbug/10293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xlander/" target="_blank">xlander</a> 2006-07-21 10:13 <a href="http://www.shnenglu.com/xlander/archive/2006/07/21/10293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>界面化在Y件开发过E中的安?/title><link>http://www.shnenglu.com/xlander/archive/2006/07/21/10292.html</link><dc:creator>xlander</dc:creator><author>xlander</author><pubDate>Fri, 21 Jul 2006 02:12:00 GMT</pubDate><guid>http://www.shnenglu.com/xlander/archive/2006/07/21/10292.html</guid><wfw:comment>http://www.shnenglu.com/xlander/comments/10292.html</wfw:comment><comments>http://www.shnenglu.com/xlander/archive/2006/07/21/10292.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/xlander/comments/commentRss/10292.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/xlander/services/trackbacks/10292.html</trackback:ping><description><![CDATA[ <p>    人机界面的重要性是无庸|疑的,观、h性化的界面给人带来的是美的n受和工作的乐。但qƈ不是说要把界面开发放在不可替代的重要位置?/p> <p>    在Y件开发的初期Q不应过度关注界面开发,而应侧重点攑֜pȝ功能、系l流E的实现上。这样可以快速的实现pȝ模型的实玎ͼ系l调试尽量早的提前,那些由界面开发所带来的大量BUG控制在模型搭建完成之后,减少界面BUG对系l模型的影响?/p> <div class="c42gsms" id="div_cppblog_ad_article"></div><img src ="http://www.shnenglu.com/xlander/aggbug/10292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/xlander/" target="_blank">xlander</a> 2006-07-21 10:12 <a href="http://www.shnenglu.com/xlander/archive/2006/07/21/10292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软g中应对全部工作完成的旉做出预测http://www.shnenglu.com/xlander/archive/2006/07/21/10291.htmlxlanderxlanderFri, 21 Jul 2006 02:11:00 GMThttp://www.shnenglu.com/xlander/archive/2006/07/21/10291.htmlhttp://www.shnenglu.com/xlander/comments/10291.htmlhttp://www.shnenglu.com/xlander/archive/2006/07/21/10291.html#Feedback0http://www.shnenglu.com/xlander/comments/commentRss/10291.htmlhttp://www.shnenglu.com/xlander/services/trackbacks/10291.html如果一个计过E比较费Ӟ除了要给出所有运的工作量、当前已l完成的工作量,
q要对全部工作完成的旉做出预测?/div>
如果工作是现行的当然好办了,如果是非U性的Q比方说冒排序Q在排序的后期,工作量越来越。所以,q个预测Q还要从全局着|l合法的结构才行?/div>


xlander 2006-07-21 10:11 发表评论
]]>集装q攄问题http://www.shnenglu.com/xlander/archive/2006/07/21/10290.htmlxlanderxlanderFri, 21 Jul 2006 02:09:00 GMThttp://www.shnenglu.com/xlander/archive/2006/07/21/10290.htmlhttp://www.shnenglu.com/xlander/comments/10290.htmlhttp://www.shnenglu.com/xlander/archive/2006/07/21/10290.html#Feedback0http://www.shnenglu.com/xlander/comments/commentRss/10290.htmlhttp://www.shnenglu.com/xlander/services/trackbacks/10290.html在网上看到的题目Q一直没有思\Q留记?/p>

有四种规格?0个小子Q放于两U规格的大箱?有无C)中,
要如何放|才会大箱使用最而且分配最合理,
需考虑横放竖放

箱子有三种规格:
5*3*2?0个 
5*3*1 5?
10*3*2 15? 
2*3*2 20个 

大箱子有两种规格Q?br />10*10*6  
8*5*6



xlander 2006-07-21 10:09 发表评论
]]>
~写高效的C代码http://www.shnenglu.com/xlander/archive/2006/07/21/10289.htmlxlanderxlanderFri, 21 Jul 2006 02:07:00 GMThttp://www.shnenglu.com/xlander/archive/2006/07/21/10289.htmlhttp://www.shnenglu.com/xlander/comments/10289.htmlhttp://www.shnenglu.com/xlander/archive/2006/07/21/10289.html#Feedback1http://www.shnenglu.com/xlander/comments/commentRss/10289.htmlhttp://www.shnenglu.com/xlander/services/trackbacks/10289.html~写高效的C代码

原文标题QWriting Efficient C and C Code Optimization
原文地址Q?a >http://www.codeproject.com/cpp/C___Code_Optimization.asp
原文作者:Koushik Ghosh
译文作者:zhigang

前言
前段旉Q我开发了一个轻量的JPEG库,用来在某U移动设备上不失真地昄囑փ。我注意C些技巧可以ɽE序q行的更快。在q篇文章里,我收集和整理了所有的q些ҎQ用来在q行速度和内存占用方面对C代码q行优化?br />管~写C代码Q已l有了许多指导原则可以参考,但这q不表示你已l彻底的了解你正在用的~译器和CPU?br /> l常的,Z使代码运行的更快Q会D代码长度的增加,所谓以I间换时_但是代码长度的增加有一U负面作用就是ɽE序的复杂度增加、可L减弱。尤其是当你的程序最l运行环境是手机、PDA之类的对内存要求比较苛刻的设备的时候,q将会是不可接受的。所以,我们优化的宗旨就是ɽE序在内存占用和q行速度两个斚w都要得到优化?/p>

声明
实际上,在我的那个项目中Q我使用了ARM公司的一文章中提到的技巧,因ؓ我的E序是基于ARMq_的,你可以从q里http://www.arm.com/pdfs/DAI0034A_efficient_c.pdf取得q篇文章Q我也从Internet上收集了许多其它的文章。但q不是每文章中提到的所有技巧都有用Q所以,在这里,我只攉了有用且有效的,q有Q我修改了其中的一些技巧它几乎适用于所有情况,而不仅仅是ARM?br />我所作的工作只是各个站点的技巧收集到一P其是我在上面提到的那个PDF文gQ我从来没有说过q些技巧我自q发明。在本文末尾的参考文献部分,我罗列了所有技巧的来源?/p>

哪里需要优?br />没有q一点,所有的讨论都无从谈赗首先也是最重要的是要找出哪里需要优化,E序的那一部分或者那个模块运行速度慢或者用大量内存。程序的每个部分都被分别优化Q自然而然的整个程序又会变得运行的比较快了?br />优化应该主要针对E序中最l常q行的部分,其是被内部循环反复调用的函数?br /> 一个经验丰富的E序员会很容易找出程序中需要着重优化的部分Q另外,q有许多工具可以用来定q些部分。我曄用Visual C++ 的IDE内徏的ProfilerQ另外一个我用过的工hIntel VtuneQ这是一个非常好用的ProfilerQ都可以用来LE序中最Ҏ的地斏V以我的l验来看Q导致程序运行速度慢得|魁R可能是某个内部或嵌套@环,也可能是对第三方库函数的调用?/p>

整型?/ Integers
  如果一个变量的取D围是非负的,我们应该使用unsigned intQ而不是int。一些处理器在处理无W号整型数要比处理符h型数快得多,q也是一个好的习惯,有利于代码的自我文档?self-documenting)?br />  那么Q在一个小循环Qtight loopQ中Q定义一个整型变量,最好类DP
register unsigned int variable_name;
然而,我们不能保证~译器会注意到那个register关键字,也有可能Q对某种处理器来_有没有unsigned是一L。这两个关键字ƈ不是可以在所有的~译器中应用?br />CQ整形数q算要比点数运快得多Q因为处理器可以直接q行整型数运,点数运需要依赖于外部的QҎ处理器或者QҎ数学库?br />我们处理数的时候要_ֿ些,比方说我们在做一个简单的l计E序Ӟ要限制结果不能超q?00Q要可能晚的把它{化成点数?/p>

除法和余?/ Division and Remainder
  在一般的处理器中Q根据分子和分母的不同,一?2位的除法需?0-140个时钟周期,{于一个固定的旉加上每个位被除的旉?br />Time (分子/ 分母) = C0 + C1* log2 (分子/分母)
      = C0 + C1 * (log2 (分子) - log2 (分母)).
  现在的ARM处理器需要消?0+4.3N个时钟周期,q是一个非常费时的操作Q要可能的避免。在有些情况下,除法表达式可以用乘法表达是来重写。比方说Q?a/b)>c可以写成a>(c*b),条g是我们已l知道b为非负数而且b*c不会过整型数的取D围。如果我们能够确定其中的一个操作数为unsignedQ那么用无W号除法会更好Q因为它要比有符号除法快得多?/p>

合ƈ除法q算和取余运?/ Combining division and remainder
  在一些情况下Q除法运和取余q算都需要用刎ͼ在这U情况下Q编译器会将除法q算和取余运合qӞ因ؓ除法q算L同时q回商和余数。如果两个运都要用刎ͼ我们可以他们写CP译者:不要l究下面的代码的含义Q只是阐q写?#8220;一?#8221;Q?br />int func_div_and_mod (int a, int b) {
        return (a / b) + (a % b);
    }

除数是2的幂的除法和取余 / Division and remainder by powers of two
  如果除法q算中的除数是2的幂Q我们对q个除法q算q可以进一步优化,~译器会使用UMq算来进行这U除法运。所以,我们要尽可能~放比例为2的幂(比方说要用6Q而不用6Q?。如果是无符hQ它要比有符L快得多?br />    typedef unsigned int uint;
    uint div32u (uint a) {
     return a / 32;
    }
    int div32s (int a){
     return a / 32;
    }
q两个除法都会避免调用除法函敎ͼ另外Q无W号的除法要比有W号的除法用更的指o。有W号的除法要耗费更多的时_因ؓ除法是最l结果趋向于零的Q而移位则是趋向于负无I?/p>

取模q算的变?/ An alternative for modulo arithmetic
我们一般用取余运进行取模,不过Q有时候用if语句也是可行的。考虑下面的两个例子:
    uint modulo_func1 (uint count)
    {
       return (++count % 60);
    }
    uint modulo_func2 (uint count)
    {
       if (++count >= 60)
      count = 0;
      return (count);
    }
W二个例子要比第一个更可取Q因为由它生的代码会更快,注意Q这只是在count取D围在0 – 59之间的时候才行?/p>

使用数组索引 / Using array indices
假设你要依据某个变量的|讄另一个变量的取gؓ特定的字W,你可能会q样做:
    switch ( queue ) {
    case 0 :   letter = 'W';
       break;
    case 1 :   letter = 'S';
       break;
    case 2 :   letter = 'U';
       break;
    }
或者这P
    if ( queue == 0 )
      letter = 'W';
    else if ( queue == 1 )
      letter = 'S';
    else
      letter = 'U';
有一个简z且快速的方式是简单的变量的取值做成一个字W串索引Q例如:
static char *classes="WSU";
letter = classes[queue];

全局变量 / Global variables
全局变量不会被分配在寄存器上Q修改全局变量需要通过指针或者调用函数的方式间接q行。所以编译器不会全局变量存储在寄存器中,那样会带来额外的、不必要的负担和存储I间。所以在比较关键的@环中Q我们要不用全局变量?br />如果一个函数要频繁的用全局变量Q我们可以用局部变量,作ؓ全局变量的拷贝,q样可以用寄存器了。条件是本函数调用的M子函C使用q些全局变量?br />举个例子Q?br />    int f(void);
    int g(void);
    int errs;
    void test1(void)
    {
      errs += f();
      errs += g();
    }

    void test2(void)
    {
      int localerrs = errs;
      localerrs += f();
      localerrs += g();
      errs = localerrs;
    }
可以看到test1()中每ơ加法都需要读取和存储全局变量errsQ而在test2()中,localerrs分配在寄存器上,只需要一条指令?/p>

使用别名 / Using Aliases
考虑下面的例子:
    void func1( int *data )
    {
        int i;
        for(i=0; i<10; i++)
        {
              anyfunc( *data, i);
        }
    }
即*data从来没有变化Q编译器却不知道anyfunc()没有修改它,于是E序每次用到它的时候,都要把它从内存中d来,可能它只是某些变量的别名Q这些变量在E序的其他部分被修改。如果能够确定它不会被改变,我们可以q样写:
    void func1( int *data )
    {
        int i;
        int localdata;
        localdata = *data;
        for(i=0; i<10; i++)
        {
              anyfunc ( localdata, i);
        }
    }
q样会给~译器优化工作更多的选择余地?/p>

zȝ变量和泄?/ Live variables and spilling
寄存器的数量在每个处理器当中都是固定的,所以在E序的某个特定的位置Q可以保存在寄存器中的变量的数量是有限制的?br />有些~译器支?#8220;生命周期分割”Qlive-range splittingQ,也就是说在程序的不同部分Q变量可以被分配C同的寄存器或者内存中。变量的生命范围被定义成QvҎ对该变量的一ơ空间分配,l点是在下次I间分配之前的最后一ơ用之间。在q个范围内,变量的值是合法的,是活的。在生命范围之外Q变量不再被使用Q是ȝQ它的寄存器可以供其他变量用,q样Q编译器可以安排更多的变量到寄存器当中?br />可分配到寄存器的变量需要的寄存器数量等于经q生命范围重叠的变量的数目,如果q个数目过可用的寄存器的数量,有些变量必被暂时的存储到内存中。这U处理叫?#8220;泄漏(spilling)”?br />~译器优先泄漏最不频J用的变量Q将泄漏的代价降到最低。可以通过以下方式避免变量?#8220;泄漏”Q?br />?#160;限制zd量的最大数目:通常可以使用单小巧的表达式,在函数内部不使用太多的变量。把大的函数分割成更加简单的、更加小巧的多个函数Q也可能会有所帮助?br />?#160;使用关键字register修饰最l常使用的变量:告诉~译器这个变量将会被l常用到Q要求编译器使用非常高的优先U将此变量分配到寄存器中。尽如此,在某些情况下Q变量还是可能被泄漏?/p>

变量cd / Variable Types
C~译器支持基本的变量cdQchar、short、int、long(signed、unsigned)、float、double。ؓ变量定义最恰当的类型,非常重要Q因样可以减代码和数据的长度,可以非常显著的提高效率?/p>

局部变?/ Local variables
如果可能Q局部变量要避免使用char和short。对于char和shortcdQ编译器在每ơ分配空间以后,都要这U局部变量的寸减少?位或16位。这对于W号变量来说UCؓW号扩展Q对无符号变量称为无W号扩展。这U操作是通过寄存器左移24?6位,然后再有W号Q或无符LQ右UdL位数来实现的Q需要两条指令(无符号字节变量的无符h展需要一条指令)?br />q些UM操作可以通过使用int和unsigned int的局部变量来避免。这对于那些首先数据调到局部变量然后利用局部变量进行运的情况其重要。即使数据以8位或16位的形式输入或输出,把他们当?2位来处理仍是有意义的?br />我们来考虑下面的三个例子函敎ͼ
    int wordinc (int a)
    {
       return a + 1;
    }
    short shortinc (short a)
    {
        return a + 1;
    }
    char charinc (char a)
    {
        return a + 1;
    }
他们的运结果是相同的,但是W一个代码片断要比其他片断运行的要快?/p>

指针 / Pointers
如果可能Q我们应该用结构体的引用作为参敎ͼ也就是结构体的指针,否则Q整个结构体׃被压入堆栈,然后传递,q会降低速度。程序适用g递可能需要几K字节Q而一个简单的指针也可以达到同L目的Q只需要几个字节就可以了?br />  如果在函数内部不会改变结构体的内容,那么应该将参数声明为const型的指针。D个例子:
    void print_data_of_a_structure ( const Thestruct  *data_pointer)
    {
        ...printf contents of the structure...
    }
  q个例子代码告知~译器在函数内部不会改变外部l构体的内容Q访问他们的时候,不需要重诅R还可以保~译器捕捉Q何修改这个只ȝ构体的代码,l结构体以额外的保护?/p>

指针?/ Pointer chains
指针铄常被用来讉Kl构体的信息Q比如,下面的这D常见的代码Q?br />    typedef struct { int x, y, z; } Point3;
    typedef struct { Point3 *pos, *direction; } Object;

    void InitPos1(Object *p)
    {
       p->pos->x = 0;
       p->pos->y = 0;
       p->pos->z = 0;
    }
代码中,处理器在每次赋值操作的时候都要重新装载p->posQ因为编译器不知道p->pos->x不是p->pos的别名。更好的办法是将p->pos~存成一个局部变量,如下Q?br />    void InitPos2(Object *p)
    {
       Point3 *pos = p->pos;
       pos->x = 0;
       pos->y = 0;
       pos->z = 0;
    }
另一个可能的Ҏ是将Point3l构体包含在Objectl构体中Q完全避免指针的使用?/p>

有条件的执行 / Conditional Execution
条g执行主要用在if语句中,同时也会用到由关p运?<,==,>{?或boolq算(&&,!{?l成的复杂的表达式?br />可能的保持if和else语句的简单是有好处的Q这h能很好的条g化。关p表辑ּ应该被分成包含相似条件的若干块?br />下面的例子演CZ~译器如何用条件执行:
    int g(int a, int b, int c, int d)
    {
       if (a > 0 && b > 0 && c < 0 && d < 0) 
       //分组化的条g被捆l在一?br />          return a + b + c + d;
       return -1;
    }
条g被分l,便以其能够条件化他们?/p>

Boolean表达式和范围?/ Boolean Expressions & Range checking
有一U常见的boolean表达式被用来查是否一个变量取值在某个特定的范围内Q比方说Q检查一个点是否在一个窗口内?br />    bool PointInRectangelArea (Point p, Rectangle *r)
    {
       return (p.x >= r->xmin && p.x < r->xmax &&
                          p.y >= r->ymin && p.y < r->ymax);
    }
q里q有一个更快的ҎQ把(x >= min && x < max) 转换?(unsigned)(x-min) < (max-min). 其是min?Ӟ更ؓ有效。下面是优化后的代码Q?br />    bool PointInRectangelArea (Point p, Rectangle *r)
    {
        return ((unsigned) (p.x - r->xmin) < r->xmax &&
       (unsigned) (p.y - r->ymin) < r->ymax);
    }

Boolean表达?amp;与零的比?/ Boolean Expressions & Compares with zero
在比?CMP)指o后,相应的处理器标志位就会被讄。这些标志位也可以被其他的指令设|,诸如MOV, ADD, AND, MUL, 也就是基本的数学和逻辑q算指oQ数据处理指令)。假如一条数据处理指令要讄q些标志位,那么N和Z标志位的讄Ҏ跟把数字和零比较的设|方法是一L。N标志位表C结果是不是负数QZ标志位表C结果是不是零?br />在C语言中,处理器中的N和Z标志位对应的有符h的关p运符是x < 0, x >= 0, x == 0, x != 0Q无W号数对应的是x == 0, x != 0 (or x > 0)?br />C语言中,每用C个关p运符Q编译器׃产生一个比较指令。如果关p运符是上面的其中一个,在数据处理指令紧跟比较指令的情况下,~译器就会将比较指o优化掉。比如:
    int aFunction(int x, int y)
    {
       if (x + y < 0)
          return 1;
      else
         return 0;
    }
q样做,会在关键循环中节省比较指令,使代码长度减,效率增加。C语言中没有借位(carry)标志位和溢出(overflow)标志位的概念Q所以如果不使用内嵌汇编语言Q要讉KC和V标志位是不可能的。尽如此,~译器支持借位标志位(无符h溢出Q,比方_
    int sum(int x, int y)
    {
       int res;
       res = x + y;
       if ((unsigned) res < (unsigned) x) // carry set?  //
         res++;
       return res;
    }

Lazy Evaluation Exploitation
In a if(a>10 && b=4) type of thing, make sure that the first part of the AND expression is the most likely to give a false answer (or the easiest/quickest to calculate), therefore the second part will be less likely to be executed.

用switch() 代替if...else...
在条仉择比较多的情况下,可以用if…else…else…Q像q样Q?br />    if( val == 1)
        dostuff1();
    else if (val == 2)
        dostuff2();
    else if (val == 3)
        dostuff3();
使用switch可以更快Q?br />    switch( val )
    {
        case 1: dostuff1(); break;
        case 2: dostuff2(); break;
        case 3: dostuff3(); break;
    }
在if语句中,即是最后一个条件成立,也要先判断所有前面的条g是否成立。Switch语句能够去除q些额外的工作。如果你不得不用if…elseQ那把最可能的成立的条g攑֜前面?/p>

二进制分?/ Binary Breakdown
 把判断条件做成二q制的风|比如Q不要用下面的列表Q?br />    if(a==1) {
    } else if(a==2) {
    } else if(a==3) {
    } else if(a==4) {
    } else if(a==5) {
    } else if(a==6) {
    } else if(a==7) {
    } else if(a==8)
    {
    }
而采用:
    if(a<=4) {
        if(a==1)     {
        }  else if(a==2)  {
        }  else if(a==3)  {
        }  else if(a==4)   {
        }
    }
    else
    {
        if(a==5)  {
        } else if(a==6)   {
        } else if(a==7)  {
        } else if(a==8)  {
        }
    }
甚至Q?br />    if(a<=4)
    {
        if(a<=2)
        {
            if(a==1)
            {
                /* a is 1 */
            }
            else
            {
                /* a must be 2 */
            }
        }
        else
        {
            if(a==3)
            {
                /* a is 3 */
            }
            else
            {
                /* a must be 4 */
            }
        }
    }
    else
    {
        if(a<=6)
        {
            if(a==5)
            {
                /* a is 5 */
            }
            else
            {
                /* a must be 6 */
            }
        }
        else
        {
            if(a==7)
            {
                /* a is 7 */
            }
            else
            {
                /* a must be 8 */
            }
        }
    }
慢速、低?#160;快速、高?br />       c=getch();
       switch(c){
           case 'A':
           {
               do something; 
               break; 
           }
           case 'H':
           {
               do something;
               break;
           } 
           case 'Z':
           {
                do something;
                break;
            }
        } c=getch();
        switch(c){
            case 0: 
            {
                do something;
                break;
            } 
            case 1:
            {
                do something;
                break;
            }
            case 2:
            {
                do something;
                break;
            }
        }
以上是两个case语句之间的比?/p>

switch语句和查找表 / Switch statement vs. lookup tables
switch语句通常用于以下情况Q?br />?#160;调用几个函数中的一?br />?#160;讄一个变量或q回?br />?#160;执行几个代码片断中的一?br />如果case表示是密集的Q译者:q箋的?Q,在用switch语句的前两种情况中,可以使用效率更高的查找表。比如下面的两个实现汇编代码转换成字W串的例E:
    char * Condition_String1(int condition) {
      switch(condition) {
         case 0: return "EQ";
         case 1: return "NE";
         case 2: return "CS";
         case 3: return "CC";
         case 4: return "MI";
         case 5: return "PL";
         case 6: return "VS";
         case 7: return "VC";
         case 8: return "HI";
         case 9: return "LS";
         case 10: return "GE";
         case 11: return "LT";
         case 12: return "GT";
         case 13: return "LE";
         case 14: return "";
         default: return 0;
      }
    }

    char * Condition_String2(int condition) {
       if ((unsigned) condition >= 15) return 0;
          return
          "EQ\0NE\0CS\0CC\0MI\0PL\0VS\0VC\0HI\0LS\0GE\0LT\0GT\0LE\0\0" +
           3 * condition;
    }
W一个例E需?40个字节,W二个只需?2个?/p>

循环 / Loops
在大多数E序中,循环是一U常见的l构Q相当数量的执行旉被消耗在循环上,因此在时间苛ȝ循环上付出注意是值得的?/p>

循环l止 / Loop termination
如果~写循环l止条g是不加留意,可能会l程序带来明昄负担。我们应该尽量?#8220;倒数到零”的@环,使用单的循环l止条g。@环终止条件相对简单,E序在执行的时候也会消耗相对少的时间。拿下面两个计算n!的例子来_W一个例子用递增循环Q第二个使用递减循环?br />    int fact1_func (int n)
    {
        int i, fact = 1;
        for (i = 1; i <= n; i++)
          fact *= i;
        return (fact);
    }

    int fact2_func(int n)
    {
        int i, fact = 1;
        for (i = n; i != 0; i--)
           fact *= i;
        return (fact);
    }
l果是,W二个例子要比第一个快得多?/p>

更快的for()循环 / Faster for() loops
q是一个简单而有效的概念Q通常情况下,我们习惯把for循环写成q样Q?br />for( i=0;  i<10;  i++){ ... }
igơؓQ?,1,2,3,4,5,6,7,8,9
在不在乎循环计数器顺序的情况下,我们可以q样Q?br />for( i=10; i--; ) { ... }
igơؓ: 9,8,7,6,5,4,3,2,1,0,而且循环要更?br />q种Ҏ是可行的Q因为它是用更快的i--作ؓ试条g的,也就是说“i是否为非零数Q如果是减一Q然后l?#8221;。相对于原先的代码,处理器不得不“把i减去10Q结果是否ؓ非零敎ͼ如果是,增加iQ然后l?#8221;Q在紧密循环(tight loop)中,q会产生显著的区别?br /> q种语法看v来有一炚w生,却完全合法。@环中的第三条语句是可选的Q无限@环可以写成这样for(;;)Q?下面的写法也可以取得同样的效果:
for(i=10; i; i--){}
或?
for(i=10; i!=0; i--){}
我们唯一要小心的地方是要C循环需要停止在0Q如果@环是?0-80Q这样做׃行了Q,而且循环的计数器为倒计数方式?br />另外Q我们还可以把计数器分配到寄存器上,可以产生更ؓ有效的代码。这U将循环计数器初始化成@环次敎ͼ然后递减到零的方法,同样适用于while和do语句?/p>

混合循环/ Loop jamming
在可以用一个@环的场合Q决不要使用两个。但是如果你要在循环中进行大量的工作Q超q处理器的指令缓冲区Q在q种情况下,使用两个分开的@环可能会更快Q因为有可能q两个@环都被完整的保存在指令缓冲区里了?br />        //原先的代?br />        for(i=0; i<100; i++){
            stuff();
        }
       
        for(i=0; i<100; i++){
            morestuff();
        }       
         //更好的做?br />        for(i=0; i<100; i++){
            stuff();
            morestuff();
        }

函数循环 / Function Looping
调用函数的时候,在性能上就会付Z定的代h。不光要改变E序指针Q还要将那些正在使用的变量压入堆栈,分配新的变量I间。ؓ了提高程序的效率Q在E序的函数结构上Q有很多工作可以做。保证程序的可读性的同时Q还要尽量控制程序的大小?br /> 如果一个函数在一个@环中被频J调用,可以考虑这个@环放在函数的里面Q这样可以免去重复调用函数的负担Q比如:
    for(i=0 ; i<100 ; i++)
    {
        func(t,i);
    }

    void func(int w,d)
    {
        lots of stuff.
    }
可以写成…
    func(t);

    void func(w)
    {
        for(i=0 ; i<100 ; i++)
        {
            //lots of stuff.
        }
    }

循环的拆?/ Loop unrolling
Z提高效率Q可以将的循环解开Q不q这样会增加代码的尺寸。@环被拆开后,会降低@环计数器更新的次敎ͼ减少所执行的@环的分支数目。如果@环只重复几次Q那它完全可以被拆解开Q这P由@环所带来的额外开销׃消失?/p>

比如:
        for(i=0; i<3; i++){
            something(i);
        }
       
        //更高效的方式
         something(0);
        something(1);
        something(2);
因ؓ在每ơ的循环中,i的值都会增加,然后查是否有效。编译器l常会把q种单的循环解开Q前提是q些循环的次数是固定的。对于这L循环Q?br />for(i=0;i< limit;i++) { ... }
׃可能被拆解,因ؓ我们不知道它循环的次数到底是多少。不q,这U类型的循环拆解开q不是不可能的?/p>

与简单@环相比,下面的代码的长度要长很多Q然而具有高得多的效率。选择8作ؓ分块大小Q只是用来演C,M合适的长度都是可行的。例子中Q@环的成立条g每八ơ才被检验一ơ,而不是每ơ都要检验。如果需要处理的数组的大是定的,我们可以用数l的大小作ؓ分块的大(或者是能够整除数组长度的数|。不q,分块的大跟pȝ的缓存大有兟?br />    //?
    #include<STDIO.H>
    #define BLOCKSIZE (8)
    void main(void)
    {
    int i = 0;
    int limit = 33;  /* could be anything */
    int blocklimit;

    /* The limit may not be divisible by BLOCKSIZE,
     * go as near as we can first, then tidy up.
     */
    blocklimit = (limit / BLOCKSIZE) * BLOCKSIZE;

    /* unroll the loop in blocks of 8 */
    while( i < blocklimit )
    {
        printf("process(%d)\n", i);
        printf("process(%d)\n", i+1);
        printf("process(%d)\n", i+2);
        printf("process(%d)\n", i+3);
        printf("process(%d)\n", i+4);
        printf("process(%d)\n", i+5);
        printf("process(%d)\n", i+6);
        printf("process(%d)\n", i+7);
        /* update the counter */
        i += 8;
    }
    /*
     * There may be some left to do.
     * This could be done as a simple for() loop,
     * but a switch is faster (and more interesting)
     */
    if( i < limit )
    {
        /* Jump into the case at the place that will allow
         * us to finish off the appropriate number of items.
         */
        switch( limit - i )
        {
            case 7 : printf("process(%d)\n", i); i++;
            case 6 : printf("process(%d)\n", i); i++;
            case 5 : printf("process(%d)\n", i); i++;
            case 4 : printf("process(%d)\n", i); i++;
            case 3 : printf("process(%d)\n", i); i++;
            case 2 : printf("process(%d)\n", i); i++;
            case 1 : printf("process(%d)\n", i);
        }
    }
    }
人口l计-计算非零位的个数 / Population count - counting the number of bits set
?试单个的最低位Q计敎ͼ然后UM。例2则是先除4Q然后计被4处的每个部分。@环拆解经怼l程序优化带来新的机会?br />    //Example - 1
    int countbit1(uint n)
    {
      int bits = 0;
      while (n != 0)
      {
        if (n & 1) bits++;
        n >>= 1;
       }
      return bits;
    }
    //Example - 2
    int countbit2(uint n)
    {
       int bits = 0;
       while (n != 0)
       {
          if (n & 1) bits++;
          if (n & 2) bits++;
          if (n & 4) bits++;
          if (n & 8) bits++;
          n >>= 4;
       }
       return bits;
    }

及早的退出@?/ Early loop breaking
通常没有必要遍历整个循环。D例来_在数l中搜烦一个特定的|我们可以在找到我们需要g后立刻退出@环。下面的例子?0000个数字中搜烦-99?br />    found = FALSE;
    for(i=0;i<10000;i++)
    {
        if( list[i] == -99 )
        {
            found = TRUE;
        }
    }
    if( found ) printf("Yes, there is a -99. Hooray!\n");
q样做是可行的,但是不管q个被搜索到的项目出现在什么位|,都会搜烦整个数组。跟好的Ҏ是,再找到我们需要的数字以后Q立刻退出@环?br />    found = FALSE;
    for(i=0; i<10000; i++)
    {
        if( list[i] == -99 )
        {
            found = TRUE;
            break;
        }
    }
    if( found ) printf("Yes, there is a -99. Hooray!\n");
如果数字出现在位|?3上,循环׃l止Q忽略剩下的9977个?/p>

函数设计 / Function Design
保持函数短小_悍Q是对的。这可以使编译器能够跟高效地q行其他的优化,比如寄存器分配?/p>

调用函数的开销 / Function call overhead
对处理器而言Q调用函数的开销是很的Q通常Q在被调用函数所q行的工作中Q所占的比例也很。能够用寄存器传递的函数参数个数是有限制的。这些参数可以是整型兼容的(char,short,int以及float都占用一个字Q,或者是4个字以内的结构体Q包?个字的double和long longQ。假如参数的限制?Q那么第5个及后面的字都会被保存到堆栈中。这会增加在调用函数是存储这些参数的Q以及在被调用函C恢复q些参数的代仗?br />    int f1(int a, int b, int c, int d) {
       return a + b + c + d;
    }
    int g1(void) {
       return f1(1, 2, 3, 4);
    }
    int f2(int a, int b, int c, int d, int e, int f) {
      return a + b + c + d + e + f;
    }
    ing g2(void) {
     return f2(1, 2, 3, 4, 5, 6);
    }
g2函数中,W??个参数被保存在堆栈中Q在f2中被恢复Q每个参数带?ơ内存访问?/p>

最化参数传递开销 / Minimizing parameter passing overhead
Z传递参数给函数的代价降x低,我们可以Q?br />可能确保函数的形参不多于四个,甚至更少Q这样就不会使用堆栈来传递参数?br />如果一个函数Ş参多于四个,那就保在这个函数能够做大量的工作,q样可以抵消由传递堆栈参数所付出的代仗?br />用指向结构体的指针作形参Q而不是结构体本n?br />把相关的参数攑ֈ一个结构里里面Q然后把它的指针传给函数Q可以减参数的个数Q增加程序的可读性?br />longcd的参数的个数降到最,因ؓ它用两个参数的I间。对于double也同样适用?br />避免出现参数的一部分使用寄存器传输,另一部分使用堆栈传输的情c这U情况下参数被全部压到堆栈里?br />避免出现函数的参CC定的情况。这U情况下Q所有参数都使用堆栈?/p>

叶子函数 / Leaf functions
如果一个函C再调用其他函敎ͼq样的函数被UCؓ叶子函数。在许多应用E序中,大约一半的函数调用是对叶子函数的调用。叶子函数在所有^C都可以得到非帔R效的~译Q因Z们不需要进行参数的保存和恢复。在入口压栈和在出口退栈的代hQ跟一个够复杂的需?个或?个参数的叶子函数所完成的工作相比,是非常小的。如果可能的话,我们p量安排l常被调用的函数成ؓ叶子函数。函数被调用的次数可以通过模型工具Qprofiling facilityQ来定。这里有几种Ҏ可以保函数被编译成叶子函数Q?br />不调用其他函敎ͼ包括那些被{换成调用C语言库函数的q算Q比如除法、Q点运?br />使用关键字__inline修饰的函数?/p>

内嵌函数 / Inline functions
对于所有调试选项Q内嵌函数是被禁止的。用inline关键字修饰函数后Q跟普通的函数调用不同Q代码中对该函数的调用将会被函数体本w代ѝ这会是代码更快Q另一斚w它会影响代码的长度,其是内嵌函数比较大而且l常被调用的情况下?br />    __inline int square(int x) {
       return x * x;
    }
    #include <MATH.H>
    double length(int x, int y){
        return sqrt(square(x) + square(y));
    }
使用内嵌函数有几个优点:
没有调用函数的开销。因为函数被直接代替Q没有Q何额外的开销Q比如存储和恢复寄存器?br />更低的参数赋值开销。参C递的开销通常会更低,因ؓ它不需要复制变量。如果其中一些参数是帔RQ编译器q可以作q一步的优化?br />内嵌函数的缺Ҏ如果函数在许多地方被调用Q将会增加代码的长度。长度差别的大小显著依赖于内嵌函数的大小和调用的ơ数?br />仅将数关键函数讄成内嵌函数是明智的。如果设|得当,内嵌函数可以减少代码的长度,一ơ函数调用需要一定数量的指oQ但是,使用优化q的内嵌函数可以~译成更的指o?/p>

使用查找?/ Using Lookup Tables
有些函数可以q似成查找表Q这样可以显著的提高效率。查找表的精度一般比计算公式的精度低Q不q在大多数程序中Q这U精度就_了?br />许多信号处理软gQ比如MODEM调制软gQ会大量的用sin和cos函数Q这些函C带来大量的数学运。对于实时系l来__ֺ不是很重要,sin/cos查找表显得更加实用。用查找表的时候,量相q的q算合ƈ成一个查找表Q这栯比用多个查找表要更快和使用更少的空间?/p>

点q算 / Floating-Point Arithmetic
管点q算对于M处理器来讲都是很Ҏ间的Q有的时候,我们q是不得不用到负点运,比方说实C号处理。尽如此,~写点q算代码的时候,我们要牢讎ͼ
点除法是慢的。除法要比加法或者乘法慢两倍,我们可以把被一个常数除的运写成被q个数的倒数乘(比如Qx=x/3.0写成x=x*(1.0/3.0)Q。倒数的计在~译阶段p完成?br />使用float代替double。Float型变量消耗更的内存和寄存器Q而且因ؓ它的低精度所以具有更高的效率。在_ֺ_的情况下Q就要用float?br />不要使用先验函数Qtranscendental functionsQ,先验函数Q比如sinQcosQlogQ是通过使用一pd的乘法和加法实现的,所以这些运会比普通的乘法?0倍以上?br />化Q点表辑ּ。编译器在整型跟点型؜合的q算中不会进行太多的优化。比? * (x / 3) 不会被优化成xQ因为Q点运通常会导致精度的降低Q甚臌辑ּ的顺序都是重要的Q?(a + b) + c 不等?a + (b + c)。因此,q行手动的优化是有好处的?br />不过Q在特定的场合下QQ点运的效率达不到指定的水^Q这U情况下Q最好的办法可能是放弃Q点运,转而用定点运。当变量的变化范围够的,定点q算要比点q算_ֺ更高、速度更快?/p>

其他的技?/ Misc tips
一般情况下Q可以用存储I间换取旉。你可以~存那些l常用到的数据,而不是每ơ都重新计算、或者重新装载。比如sin/cos表,或者伪随机数的表(如果你不是真的需要随机数Q你可以在开始的时候计?000个,在随后的代码中重复利用就是了Q?br />量的使用全局变量?br />一个文件内部的变量声明成静态的Q除非它有必要成为全局的?br />不要使用递归。递归可以使代码非常整齐和观Q但会生大量的函数调用和开销?br />讉K单维数组要比多位数组?br />使用#defined宏代替经常用到的函数?/p>

参考文?/ References
Q译者略Q?/p>

其他|络资源 / Other URLs
http://www.xs4all.nl/~ekonijn/loopy.html
http://www.public.asu.edu/~sshetty/Optimizing_Code_Manual.doc
http://www.abarnett.demon.co.uk/tutorial.html

译者声明:作者对我的q片译文q不知情Q我在完全不知会作者的情况下翻译了其发表于www.codeproject.com的文章,但我保留了原文的作者信息。请您仅此文用于学术研I目的。如果您要将此文用于其它目的Q请与原作者联pR如果您认ؓ文章译的有问题Q译者将非常高兴看到您提出的宝贵意见?br />



xlander 2006-07-21 10:07 发表评论
]]>
þ޾ƷVA| ƷþþþӰԺ۲| ձƬҹþ| ޹Ʒþþϼ2 | ŷպƷþ| ˾þô߽槼| 9þ9þþƷ| һһþþƷۺ | ޹Ʒþþ| ŷһþþƷ| ޹Ʒþ| þþƷƵһ| һɫþ88ۺ޾Ʒ| ˾þþƷavһ| þAV˳׽| þۺ| 99Ʒþ| ھƷѾþӰԺ| þ¾ƷĻ| þþþþþþþþþƷ| þSEƷһ| þþþѿӰƬ| 㽶þþþ| þۺձ츾| ݺݾþ| þۺϾþۺϾþ| ޹˾ƷŮ˾þþ| ˾þþƷavһ| պһþþþþ| þֹۺ޾Ʒ| þþŮ붯ȺëƬ| ۺϾþúݺɫ99h| 㽶þҹɫƷ| ھƷ˾þþþavһ | Ʒþþþþ| þþþ޾Ʒ˵| þ99ֻоƷ| Ʒһþ| ƷþþþþĻ| þ޾ƷƵ| ھƷþþþӰԺ޹²|