<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-4380486110383106325</atom:id><lastBuildDate>Tue, 31 Jan 2012 16:43:52 +0000</lastBuildDate><category>Windows Mobile</category><category>Plugins</category><category>Xcode</category><category>Cygwin</category><category>Game</category><category>good</category><category>PSP</category><category>Math</category><category>jaja</category><category>Windows</category><category>Interface</category><category>Test</category><category>Ini</category><category>EBNF</category><category>WTL</category><category>VM</category><category>Graphics</category><category>SDL</category><category>Debugger</category><category>OpenAL</category><category>Objective-C</category><category>Mac</category><category>Win32</category><category>stge</category><category>Lua</category><category>Parser</category><category>OpenGL</category><category>Sample</category><category>Mobile</category><category>Spirit</category><category>UEFI</category><category>C/C++</category><category>UnitTest</category><category>Design</category><category>MMOG</category><category>Audiere</category><category>DotNet</category><category>Java</category><category>Fun</category><category>API</category><category>Symbian</category><category>SDK</category><category>Editor</category><category>C#</category><category>Algorithm</category><category>Browser</category><category>iPhone</category><category>Complier</category><category>Firefox</category><category>3D</category><category>Ogg</category><category>STL</category><category>Porting</category><category>smallworld2</category><category>joke</category><category>yardparser</category><category>iPad</category><category>Boost</category><category>zlib</category><category>VS.Net</category><title>很讚的遊戲編輯器</title><description>Good Game Editor 1.2 Beta</description><link>http://good-ed.blogspot.com/</link><managingEditor>noreply@blogger.com (Waync Cheng)</managingEditor><generator>Blogger</generator><openSearch:totalResults>156</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/good-ed" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="good-ed" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">good-ed</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-5497055008827097880</guid><pubDate>Thu, 22 Dec 2011 15:43:00 +0000</pubDate><atom:updated>2011-12-22T23:43:23.759+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Lua</category><category domain="http://www.blogger.com/atom/ns#">UEFI</category><title>Lua for UEFI</title><description>利用點空閒時間將&lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt;移植到&lt;a href="http://www.uefi.org/home/"&gt;UEFI&lt;/a&gt;，作成一支Shell Application，直接執行不帶參數的話可以直接在銀幕上輸入Script，二次Enter後直接執行，執行結果立即顯示在畫面上。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-N4AXIQp8hgM/TutKNX5CvMI/AAAAAAAAAo4/mrLqh0kzW6E/s1600/uefilua1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://1.bp.blogspot.com/-N4AXIQp8hgM/TutKNX5CvMI/AAAAAAAAAo4/mrLqh0kzW6E/s320/uefilua1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
按照慣例，當然要弄個Game來玩玩，所以再把Good裡的&lt;a href="http://good-ed.blogspot.com/2009/10/blog-post.html"&gt;打磚塊&lt;/a&gt;範例拿來稍微改一下。&lt;br /&gt;
&lt;br /&gt;
這下子，在UEFI下也能打磚塊了！&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-63TIbwxxK0s/TutKjjWJEiI/AAAAAAAAApE/ZY6cGlHaCkg/s1600/uefilua2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://1.bp.blogspot.com/-63TIbwxxK0s/TutKjjWJEiI/AAAAAAAAApE/ZY6cGlHaCkg/s320/uefilua2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-5497055008827097880?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/75xXyV6L3Ms" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/12/lua-for-uefi.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-N4AXIQp8hgM/TutKNX5CvMI/AAAAAAAAAo4/mrLqh0kzW6E/s72-c/uefilua1.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-9078045086874266504</guid><pubDate>Tue, 13 Dec 2011 15:08:00 +0000</pubDate><atom:updated>2011-12-13T23:08:28.414+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Parser</category><category domain="http://www.blogger.com/atom/ns#">yardparser</category><category domain="http://www.blogger.com/atom/ns#">EBNF</category><category domain="http://www.blogger.com/atom/ns#">C/C++</category><title>以yardparser實作算式計算機</title><description>這篇文章是算式計算機系列的完結篇。&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;a href="http://good-ed.blogspot.com/2010/02/ebnf.html"&gt;(E)BNF表示式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://good-ed.blogspot.com/2010/03/blog-post.html"&gt;手工打造算式計算機&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://good-ed.blogspot.com/2010/04/lexyacc.html"&gt;以lex/yacc實作算式計算機&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://good-ed.blogspot.com/2010/06/boostspirit.html"&gt;以Boost.Spirit實作算式計算機&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
(&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=27"&gt;下載範例&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://code.google.com/p/yardparser"&gt;yardparser&lt;/a&gt;在使用上雖然沒辨法像Boost Spirit 一樣那麼直覺便利，可以將EBNF 語法規則直接定義在程式裡建立解析器，但使用類似的手法一樣可以將EBNF語法規則轉換為程式定義，建立一個語法解析器。yardparser也沒辨法像Boos Spirit那樣，可以在執行時期(run-time)動態的改變或產生新的解析器。除了上述的不同處之外，最大的差異是 yardparser 的編譯時間非常短及以 yardparser建立的parser執行速度非常快，同時產生的目的碼大小(code size)也相對小很多。&lt;br /&gt;
&lt;br /&gt;
Boost Spirit 因為大量使用了 C++ Template Meta-programming 的相關技術，很完美的將EBNF語法規則語句嵌入到C++程式碼內和我們所寫的程式碼結合在一起，相當直覺也相當神奇。只不過如果從得到的編譯時間和執行效率來看，只能說 Boost Spirit 為我們提供了相當出色的語法糖(syntactic sugar)，對於大型複雜的語法來說反而較難以適用。而 yardparser 雖然在使用上不如Boost Spirit那樣直覺便利，但至少在編譯時間和執行效率是大大滿足我們日常工作的需求。&lt;br /&gt;
&lt;br /&gt;
底下同樣以簡單範例開始，介紹yardparser的基本使用。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;A B&lt;/pre&gt;&lt;br /&gt;
上面是原EBNF表示式的寫法，用來表示一個序列，在 A之後會有個B。而使用yardparser 則寫成如下的形式。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct AB : CharSeq&amp;lt;'A', 'B'&amp;gt;
{
};&lt;/pre&gt;&lt;br /&gt;
CharSeq 是 yardparser裡面事先定義好的 一個struct，作用是對輸入來源串流讀入字元來進行匹配動作。 &lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;(AB)*&lt;/pre&gt;&lt;br /&gt;
以上定義了零個以上個AB序列的EBNF表示式的寫法，底下一樣轉換成yardparser的寫法。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct StarAB : Star&amp;lt;AB&amp;gt;
{
};&lt;/pre&gt;&lt;br /&gt;
AB是上一個例子裡定義，用來匹配 AB序列的規則。而Star是yardparser事先定義的一個struct，把AB作為它的參數，就能夠用來匹配零個以上的AB序列。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;(AB)+&lt;/pre&gt;&lt;br /&gt;
類似Star的語法，Plus是匹配一個以上的規則。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct PlusAB : Plus&amp;lt;AB&amp;gt;
{
};&lt;/pre&gt;&lt;br /&gt;
以上的規則定義用來檢驗匹配至少有一個以上的AB序列。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;(AB)?&lt;/pre&gt;&lt;br /&gt;
加上問號(?)表示這條規則是可有可無的(optional)，或者換句話說AB序列出現的次數可以是零次或一次。轉換成yardparser的語法，如下所示。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct OptionalAB : Opt&amp;lt;AB&amp;gt;
{
};&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;內建parser&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
yardparser 也內建了許多有用的parser，這些parser 或規則都以C/C++的struct 型式定義，主要可分為二大類。一類是基本規則，如 CharSeq、Star、Plus 等。另一類是 parser 類，如Digit、AlphaNum、Word等。除此之外包含於yardparser的範例中也內建了完整的C語言語法可以直接拿來應用，如DecNumber、Tok、Literal等。&lt;br /&gt;
&lt;br /&gt;
底下列出常用基本語法規則。&lt;br /&gt;
&lt;br /&gt;
&lt;table border="0"&gt;&lt;tr&gt;&lt;td width="140"&gt;Seq&lt;/td&gt;&lt;td&gt;匹配序列&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CharSeq&lt;/td&gt;&lt;td&gt;匹配字元序列&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CharSet&lt;/td&gt;&lt;td&gt;匹配其中一個字元&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CharSetRange&lt;/td&gt;&lt;td&gt;匹配字元範圍中的一個&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Star&lt;/td&gt;&lt;td&gt;零個以上匹配&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Plus&lt;/td&gt;&lt;td&gt;一個以上匹配&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Opt&lt;/td&gt;&lt;td&gt;零個或一個匹配&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Not&lt;/td&gt;&lt;td&gt;boolean not&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Or&lt;/td&gt;&lt;td&gt;boolean or&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;True_t&lt;/td&gt;&lt;td&gt;boolean true&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;False_t&lt;/td&gt;&lt;td&gt;boolean false&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;
底下是一些簡單的範例。&lt;br /&gt;
&lt;br /&gt;
&lt;table border="0"&gt;&lt;tr&gt;&lt;td width="140"&gt;ab&lt;/td&gt;&lt;td&gt;struct AB : CharSeq&amp;lt;'a', 'b'&amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;abc&lt;/td&gt;&lt;td&gt;struct ABC : CharSeq&amp;lt;'a', 'b', 'c'&amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;abc*&lt;/td&gt;&lt;td&gt;struct ABandCstar : Seq&amp;lt;AB, Star&amp;lt;Char&amp;lt;'c'&amp;gt; &amp;gt; &amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;abc+&lt;/td&gt;&lt;td&gt;struct ABandCplus : Seq&amp;lt;AB, Plus&amp;lt;Char&amp;lt;'c'&amp;gt; &amp;gt; &amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;bc&lt;/td&gt;&lt;td&gt;struct BC : CharSeq&amp;lt;'b', 'c'&amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;a(bc)+&lt;/td&gt;&lt;td&gt;struct AandBCplus : Seq&amp;lt;Char&amp;lt;'a'&amp;gt;, Plus&amp;lt;BC&amp;gt; &amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;[abc]&lt;/td&gt;&lt;td&gt;struct AorBorC : CharSet&amp;lt;'a', 'b', 'c'&amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;[a-z]&lt;/td&gt;&lt;td&gt;struct AtoZ : CharSetRange&amp;lt;'a', 'z'&amp;gt; {};&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;
下面是定義在c_grammer內的常用parser。&lt;br /&gt;
&lt;br /&gt;
&lt;table border="0"&gt;&lt;tr&gt;&lt;td width="140"&gt;WS&lt;/td&gt;&lt;td&gt;空白字元&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DecNumber&lt;/td&gt;&lt;td&gt;實數&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;HexNumber&lt;/td&gt;&lt;td&gt;以0x開頭定義的十六進制數字&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CharTok&lt;/td&gt;&lt;td&gt;匹配字元，以空白字元斷開&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Literal&lt;/td&gt;&lt;td&gt;字面常數，包含數字文字等&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;b&gt;動作程式碼&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
yardparser加入動作程式碼的方式和Boost Spirit的方式並不相同。底下以一個簡單的例子作比較，分別使用Boost Spirit及yardparser實作如下所列的簡單規則。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;S = integer&lt;/pre&gt;&lt;br /&gt;
底下是使用Boost Spirit的實作。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;void get_int(int i)
{
}

rule&lt;&gt; S = int_p [&amp;get_int];&lt;/pre&gt;&lt;br /&gt;
可以看到以Boost Spirit實作的S解析器中，語法及動作程式碼的部份是各自獨立的。我們可以很容易的把動作程式碼([&amp;get_int])的部份從語法S裡去掉，rule S仍然可以運作，因此在真正為語法加上動作程式碼之前就已經可以開始對語法測試，因此可以等到所有語法都完成實作後再回過頭來加入動作程式碼。&lt;br /&gt;
&lt;br /&gt;
現在再來看看yardparser對S的實作。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct Integer
{
};

struct Factor : Or&amp;lt;Integer, ...&amp;gt;
{
};&lt;/pre&gt;&lt;br /&gt;
從上面的範例中可以看到，yardparser的動作程式碼定義形式和一般的語法定義形式是同樣的，也就是在yardparser中動作程式碼可以視為是一特殊的語法解析器，它並不是用作在語法的匹配上，而是用於執行對應於語法規則上的操作。以上所示範例是一個最簡單的情況，而實際上常見的情況是動作程式碼會和語法規則夾雜在一塊，這在最後實際實作算式計算機時即可見到，在這方面 yardparser 和Boost Spirit比較起來就沒那麼簡單直覺。&lt;br /&gt;
&lt;br /&gt;
現在來看看yardparser的parser原型(prototype)。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct parser
{
  template&amp;lt;typename ParserState_t&amp;gt;
  static bool Match(ParserState_t&amp; p);
};&lt;/pre&gt;&lt;br /&gt;
在yardparser裡面每一個parser都定義成一個struct，struct裡面定義一個回傳值型別是bool名稱叫作Match的static函數。這條Match函數就是yardparser的核心函數，用來作語法匹配，底下透過一個簡單的範例來看看它是如何使用。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct Integer
{
    template&amp;lt;typename ParserState_T&amp;gt;
    static bool Match(ParserState_T&amp; p)
    {
        const char* p0 = p.GetPos();
        if (c_grammer::DecNumber::Match(p))
        {
            string s(p0, p.GetPos());
            int n = atoi(s.c_str());
            return true;
        }
        return false;
    }
};&lt;/pre&gt;&lt;br /&gt;
如上面的簡單範例，Integer 定義了 Match 方法，在 Match 方法中透過 yardparser 內建的c_grammer中的DecNumber解析器來匹配數字。如果DecNumber的Match方法回傳成功，則表示目前匹配的字串是一個數字。不像是Boost Spirit的動作程式碼那麼直接，每一個動作程式碼函數的參數本身就已是轉換好的資料，可以直接使用，yardparser的動作程式碼需要自行將這個數字由字串裡抽取出來，轉換成內部資料儲存。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;使用yardparser實作算式計算機&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
如下所列 ，寫下算式計算機的EBNF表示式。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;factor     := integer | '(' expression ')'
term       := factor (('*' factor) | ('/' factor))*
expression := term (('+' term) | ('-' term))*&lt;/pre&gt;&lt;br /&gt;
首先將以上的EBNF表示式轉換為使用yardparser定義，不帶動作程式碼，如下。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct Factor : Or&amp;lt;Integer, Seq&amp;lt;Char&amp;lt;'('&amp;gt;, Expression, Char&amp;lt;')'&amp;gt; &amp;gt; &amp;gt; {};
struct Term : Seq&amp;lt;Factor, Star&amp;lt;Or&amp;lt;Seq&amp;lt;Char&amp;lt;'*'&amp;gt;, Factor&amp;gt;, Seq&amp;lt;Char&amp;lt;'/'&amp;gt;, 

Factor&amp;gt; &amp;gt; &amp;gt; &amp;gt; {};
struct Expression : Seq&amp;lt;Factor, Star&amp;lt;Or&amp;lt;Seq&amp;lt;Char&amp;lt;'+'&amp;gt;, Term&amp;gt;, 
Seq&amp;lt;Char&amp;lt;'-'&amp;gt;, Term&amp;gt; &amp;gt; &amp;gt; &amp;gt; {};&lt;/pre&gt;&lt;br /&gt;
轉換後的yardparser程式定義如果沒有問題的話，應該能夠順利通過編譯，而且已經可以實際用來解析算式語法，只不過還沒加上動作程式碼所以還不能有真正的作用。&lt;br /&gt;
&lt;br /&gt;
以下開始加上動作程式碼。如同前面的範例，需要加上動作程式碼的地方有五處，其中一個是將數字取出，以及加減乘除四種運算。取出數字的動作程式碼在上一節中已列出，底下說明如何加入加減乘除運算的動作程式碼。如下所示定義為加上動作程式碼後的語法程式定義。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;struct Factor : Or&amp;lt;Integer, Seq&amp;lt;Char&amp;lt;'('&amp;gt;, Expression, Char&amp;lt;')'&amp;gt; &amp;gt; &amp;gt; {};
struct Term : Seq&amp;lt;Factor, Star&amp;lt;Or&amp;lt;DoMul&amp;lt;Seq&amp;lt;Char&amp;lt;'*'&amp;gt;, Factor&amp;gt; &amp;gt;, 
DoDiv&amp;lt;Seq&amp;lt;Char&amp;lt;'/'&amp;gt;, Factor&amp;gt; &amp;gt; &amp;gt; &amp;gt; &amp;gt; {};
struct Expression : Seq&amp;lt;Term, Star&amp;lt;Or&amp;lt;DoAdd&amp;lt;Seq&amp;lt;Char&amp;lt;'+'&amp;gt;, Term&amp;gt; &amp;gt;, 
DoSub&amp;lt;Seq&amp;lt;Char&amp;lt;'-'&amp;gt;, Term&amp;gt; &amp;gt; &amp;gt; &amp;gt; &amp;gt; {};&lt;/pre&gt;&lt;br /&gt;
以上四個動作程式碼：DoMul、DoDiv、DoAdd及DoSub 分別為四種運算的動作程式碼。可以很明顯的看出來，加上動作程式碼後，沒辨法像使用Boost Spirit一樣一眼就能夠分辨出那一部份是語法，那一部份是動作程式碼。&lt;br /&gt;
&lt;br /&gt;
最後加上一個用來作運算的數字堆疊，再整合Integer及四則運算的動作程式碼，完成算式計算機實作，其它部份程式碼如下所示。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;vector&amp;lt;int&amp;gt; stack;
template&amp;lt;class RuleT&amp;gt;
struct DoMul
{
    template&amp;lt;typename ParserState_T&amp;gt;
    static bool Match(ParserState_T&amp; p)
    {
        if (RuleT::Match(p))
        {
            stack[stack.size() - 2] *= stack[stack.size() - 1];
            stack.pop_back();
            return true;
        }
        return false;
    }
};

template&amp;lt;class RuleT&amp;gt;
struct DoDiv
{
    template&amp;lt;typename ParserState_T&amp;gt;
    static bool Match(ParserState_T&amp; p)
    {
        if (RuleT::Match(p))
        {
            stack[stack.size() - 2] /= stack[stack.size() - 1];
            stack.pop_back();
            return true;
        }
        return false;
    }
};

template&amp;lt;class RuleT&amp;gt;
struct DoAdd
{
    template&amp;lt;typename ParserState_T&amp;gt;
    static bool Match(ParserState_T&amp; p)
    {
        if (RuleT::Match(p))
        {
            stack[stack.size() - 2] += stack[stack.size() - 1];
            stack.pop_back();
            return true;
        }
        return false;
    }
};

template&amp;lt;class RuleT&amp;gt;
struct DoSub
{
    template&amp;lt;typename ParserState_T&amp;gt;
    static bool Match(ParserState_T&amp; p)
    {
        if (RuleT::Match(p))
        {
            stack[stack.size() - 2] -= stack[stack.size() - 1];
            stack.pop_back();
            return true;
        }
        return false;
    }
};

int main(void)
{
    std::string str;
    while (getline(cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;
        SimpleTextParser parser(str.c_str(), str.c_str() + str.length());
        if (!parser.Parse&amp;lt;Seq&amp;lt;Expression, EndOfInput&amp;gt; &amp;gt;())
            break;
        cout &amp;lt;&amp;lt; str &amp;lt;&amp;lt; " = " &amp;lt;&amp;lt; stack.back() &amp;lt;&amp;lt; "\n";
        stack.clear();
    }
    return 0;
}&lt;/pre&gt;&lt;br /&gt;
注意到上述的實作裡，將字元 parser Char 改為 CharTok，目的是允許在字元間可以插入額外空白，CharTok由c_grammer集合所提供。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xXrUCi9BaEg/TudqWc0yCFI/AAAAAAAAAoc/nfnvBolWF1c/s1600/57-1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="206" width="320" src="http://1.bp.blogspot.com/-xXrUCi9BaEg/TudqWc0yCFI/AAAAAAAAAoc/nfnvBolWF1c/s320/57-1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
(&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=27"&gt;下載範例&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-9078045086874266504?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/5wO2FYYTs14" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/12/yardparser.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-xXrUCi9BaEg/TudqWc0yCFI/AAAAAAAAAoc/nfnvBolWF1c/s72-c/57-1.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-6383455668594130120</guid><pubDate>Sun, 04 Dec 2011 16:28:00 +0000</pubDate><atom:updated>2011-12-05T00:28:33.764+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">DotNet</category><category domain="http://www.blogger.com/atom/ns#">C#</category><title>以ListView元件的VirtualMode實作TreeListView</title><description>(&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=26"&gt;下載範例&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
在.NET framework裡面的System.Windows.Forms元件家族中有一般常見的TreeView元件及ListView元件，但卻沒有結合這兩者的TreeListView元件或ListTreeView元件。網路上可以找到很不錯的&lt;a href="http://objectlistview.sourceforge.net/cs/index.html"&gt;資源&lt;/a&gt;，這裡另外介紹一個簡單的方式，可以透過現有的機制實作TreeListView特性。&lt;br /&gt;
&lt;br /&gt;
在.NET裡的ListView元件有一個VirtualMode，它的功能是由user自行管理ListViewItem內容。當VirtualMode啟動時，ListView元件會透過RetrieveVirtualItem事件向user要指定序號的ListViewItem。透過這一層機制，就能向我們提供一個彈性，稍加應用就能用以製作TreeListView元件功能。&lt;br /&gt;
&lt;br /&gt;
下面這個範例(C#)，使用ListView元件的VirtualMode，模倣VisualStudio在debug時的LocalVariable視窗，如面圖所示。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-5BdaKYrt6xw/TtuWOV4QxUI/AAAAAAAAAoA/s67GhIZGjJo/s1600/clip_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="184" src="http://3.bp.blogspot.com/-5BdaKYrt6xw/TtuWOV4QxUI/AAAAAAAAAoA/s67GhIZGjJo/s320/clip_1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
首先建立內部資料結構，TreeListItem。&lt;br /&gt;
&lt;pre&gt;class TreeListItem
{
&amp;nbsp;&amp;nbsp;public int Level = 0;
&amp;nbsp;&amp;nbsp;public string Name;
&amp;nbsp;&amp;nbsp;public string Value;
&amp;nbsp;&amp;nbsp;public string Type;
&amp;nbsp;&amp;nbsp;public List&lt;treelistitem&gt; Child = new List&lt;treelistitem&gt;();
&amp;nbsp;&amp;nbsp;public bool Expand = false;
&amp;nbsp;&amp;nbsp;public TreeListItem AddChild(string n, string v, string t)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TreeListItem c = new TreeListItem();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.Name = n;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.Value = v;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.Type = t;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.Level = this.Level + 1;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Child.Add(c);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return c;
&amp;nbsp;&amp;nbsp;}
}&lt;/treelistitem&gt;&lt;/treelistitem&gt;&lt;/pre&gt;Level是用來表示階層，Child串列儲存下一個階層的子項目，而Expand則用來表示在Tree中這個項目是打開或關閉的將態。AddChild用來幫助加入一個子項目。&lt;br /&gt;
&lt;br /&gt;
每當ListView元件內容變更時，我們需要手動去改變VirtualListSize的值，這時ListView元件就會透過RetrieveVirtualItem事件，向我們獲得每一個項目的內容。&lt;br /&gt;
&lt;br /&gt;
在設定VirtualListSize的值之前，我們另外需要一個串列，用來存放每一個展開的可見的項目，這是為了方便同時也簡單實作。這個串列的內容，是根據已建立好的樹狀的項目資料，以遞迴方式展開取得。&lt;br /&gt;
&lt;pre&gt;TreeListItem Root = new TreeListItem();&lt;/pre&gt;Root是一個虛擬的項目，用來存放全部的資料內容。在範例程式開始時，會ctor裡事先建立完成。&lt;br /&gt;
&lt;pre&gt;&amp;nbsp;&amp;nbsp;TreeListItem cThis = Root.AddChild("this", "{TreeListView.Form1, Text: }", "TreeListView.Form1");
&amp;nbsp;&amp;nbsp;TreeListItem cRoot = cThis.AddChild("Root", "{TreeListView.Form1.TreeListItem}", "TreeListView.Form1.TreeListItem");
&amp;nbsp;&amp;nbsp;TreeListItem cChild = cRoot.AddChild("Child", "Count = 0", "System.Collections.Generic.List&lt;treelistview.form1.treelistitem&gt;");
&amp;nbsp;&amp;nbsp;cChild.AddChild("Row View", "", "");
&amp;nbsp;&amp;nbsp;cRoot.AddChild("Expand", "false", "bool");
&amp;nbsp;&amp;nbsp;cRoot.AddChild("Level", "0", "int");
&amp;nbsp;&amp;nbsp;cRoot.AddChild("Name", "null", "string");
&amp;nbsp;&amp;nbsp;cRoot.AddChild("Value", "null", "string");&lt;/treelistview.form1.treelistitem&gt;&lt;/pre&gt;以上會建立如下結構的資料。&lt;br /&gt;
&lt;pre&gt;this
&amp;nbsp;&amp;nbsp;Root
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Child
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Root View
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Expand
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Level
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Value&lt;/pre&gt;下面的程式碼定義BuildVirtualItems，根據目前的Expand狀態以遞迴方式重建VirtualItems串列，然後重設ListView元件的VirtualListSize值。&lt;br /&gt;
&lt;pre&gt;List&lt;treelistitem&gt; VirtualItems = new List&lt;treelistitem&gt;();

void BuildVirtualItems()
{
&amp;nbsp;&amp;nbsp;VirtualItems.Clear();

&amp;nbsp;&amp;nbsp;BuildVirtualItems(Root.Child);

&amp;nbsp;&amp;nbsp;listView1.VirtualListSize = VirtualItems.Count;
}

void BuildVirtualItems(List&lt;treelistitem&gt; Items)
{
&amp;nbsp;&amp;nbsp;for (int i = 0; i &amp;lt; Items.Count; i++)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;VirtualItems.Add(Items[i]);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (Items[i].Expand)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BuildVirtualItems(Items[i].Child);
&amp;nbsp;&amp;nbsp;}
}&lt;/treelistitem&gt;&lt;/treelistitem&gt;&lt;/treelistitem&gt;&lt;/pre&gt;當ListView元件的VirtualListSize的值被改變後，ListView元件會以RetrieveVirtualItem事件去取得新的項目內容。在RetrieveVirtualItem裡只需簡單的以事件參數傳遞進來的項目索引值到VirtualItems串列裡去抓出項目資料，以這筆資料新建一個ListViewItem物件回傳即可。 &lt;br /&gt;
&lt;pre&gt;private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
&amp;nbsp;&amp;nbsp;TreeListItem c = VirtualItems[e.ItemIndex];

&amp;nbsp;&amp;nbsp;string Name = "";

&amp;nbsp;&amp;nbsp;for (int i = 0; i &amp;lt; c.Level; i++)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name += "  ";

&amp;nbsp;&amp;nbsp;if (0 &amp;lt; c.Child.Count)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (c.Expand)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name += "- ";
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name += "+ ";
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Name += "  ";

&amp;nbsp;&amp;nbsp;Name += c.Name;

&amp;nbsp;&amp;nbsp;ListViewItem Item = new ListViewItem(Name);
&amp;nbsp;&amp;nbsp;Item.SubItems.Add(c.Value);
&amp;nbsp;&amp;nbsp;Item.SubItems.Add(c.Type);

&amp;nbsp;&amp;nbsp;e.Item = Item;
}&lt;/pre&gt;這裡面用文字的+及-模擬樹狀結構的展開及關閉狀態鈕。  最後再加上一個處理滑鼠事件，處理DoubleClick用來展開或關閉項目。記得將ListView元件的FullRowSelect屬性設為true，這樣才不用只點擊第一個欄位才有作用。 &lt;br /&gt;
&lt;pre&gt;private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
&amp;nbsp;&amp;nbsp;ListViewItem lvi = listView1.GetItemAt(e.X, e.Y);
&amp;nbsp;&amp;nbsp;if (null == lvi)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;

&amp;nbsp;&amp;nbsp;TreeListItem c = VirtualItems[lvi.Index];
&amp;nbsp;&amp;nbsp;if (0 == c.Child.Count)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;

&amp;nbsp;&amp;nbsp;c.Expand = !c.Expand;

&amp;nbsp;&amp;nbsp;BuildVirtualItems();
}&lt;/pre&gt;因為+/-鈕是用文字模擬出來的，如果要在畫面上顯示更精確的狀態，則只需要自行實作DrawItem及DrawSubItem即可。&lt;br /&gt;
&lt;br /&gt;
(&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=26"&gt;下載範例&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-6383455668594130120?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/MLUR09SGR8k" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/12/listviewvirtualmodetreelistview.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-5BdaKYrt6xw/TtuWOV4QxUI/AAAAAAAAAoA/s67GhIZGjJo/s72-c/clip_1.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-8740776208873985161</guid><pubDate>Thu, 01 Dec 2011 14:19:00 +0000</pubDate><atom:updated>2011-12-01T22:19:33.963+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">iPad</category><category domain="http://www.blogger.com/atom/ns#">Mac</category><title>Zimo: Mahjong Fanatic</title><description>&lt;a href="http://itunes.apple.com/us/app/zimo-mahjong-fanatic/id479052583?mt=8"&gt;Link&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://itunes.apple.com/us/app/zimo-mahjong-fanatic/id479052583?mt=8"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-z3A887tUSDo/TteMK2UxHSI/AAAAAAAAAnk/KFmf9GI9ZRI/s1600/mzl.igorpzky.480x480-75.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://2.bp.blogspot.com/-z3A887tUSDo/TteMK2UxHSI/AAAAAAAAAnk/KFmf9GI9ZRI/s320/mzl.igorpzky.480x480-75.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-8740776208873985161?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/YIWLeMC64fU" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/12/zimo-mahjong-fanatic.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-z3A887tUSDo/TteMK2UxHSI/AAAAAAAAAnk/KFmf9GI9ZRI/s72-c/mzl.igorpzky.480x480-75.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-6996874963957308310</guid><pubDate>Thu, 03 Nov 2011 18:02:00 +0000</pubDate><atom:updated>2011-11-04T02:02:58.707+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Debugger</category><title>How to debugger? (1)</title><description>許多人都說：不懂debugger的人，不會寫程式。身為一個會寫程式的程序員，我也是十分同意這句話的。想當初我也是渾渾噩噩的寫了一陣子程式之後，才知道什麼是debugger，之後果然就好像打通任督二脈一樣，突飛猛進。所以說，要會寫程式，一定要會debugger。礙於有許多新手程序員還是不懂什麼叫作debugger，所以就寫了這篇文，對debugger作一個基本的介紹，希望能對大家有所幫忙，可以像我一樣勇猛精進。&lt;br /&gt;
&lt;br /&gt;
首先，由寫一個小小的測試程式開始，慢慢的再進入主題。&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int mul2(int a)
{
&amp;nbsp;&amp;nbsp;return 3 * a;
}

int main(void)
{
&amp;nbsp;&amp;nbsp;if (20 == mul2(10))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cout &amp;lt;&amp;lt; "debugger讚!\n";
&amp;nbsp;&amp;nbsp;else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cout &amp;lt;&amp;lt; "奇怪ㄋㄟ\n";

&amp;nbsp;&amp;nbsp;return 0;
}&lt;/pre&gt;下面是程式執行的結果。  &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ARDWzVD4nkM/TrFtNiC93jI/AAAAAAAAAlQ/rEQq8D3qS6s/s1600/56-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="127" src="http://3.bp.blogspot.com/-ARDWzVD4nkM/TrFtNiC93jI/AAAAAAAAAlQ/rEQq8D3qS6s/s320/56-1.png" width="288" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
真是奇怪ㄋㄟ，應該是要顯示"debugger讚!"才對吧！？這個時候只好來debugger一下下了，看看問題出在那裡。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;第一招，小紅點&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
下小紅點，也就是所謂的下斷點，也有人說中斷，或說breakpoint。在程式裡面放個小紅點，當程式跑到有小紅點的地方的時候就會停下來，這時候我們就抓到機會，可以去檢查看看各個可疑的地方，也可以偷偷竄改一些資料，無所不用其極的就是要把程式裡面的虫抓出來搞定它。&lt;br /&gt;
&lt;br /&gt;
下小紅點的方法有很多種，這裡我可以告訴你四種方法。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;__debugbreak();&lt;/li&gt;
&lt;li&gt;__asm int 3&lt;/li&gt;
&lt;li&gt;__asm _emit 0xCC&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
以上的方法都是手動在程式裡面放入小紅點，也就是在程式裡面塞進一個0xCC。那到底0xCC是什麼東西。去查一下x86指令集，原來0xCC就是int3。你又要問：什麼是int3？答案是：int3是個中斷，由x86硬體支援，軟體觸發。&lt;br /&gt;
&lt;br /&gt;
當CPU執行指令的時候，如果執行到的指令是0xCC，也就是int3的時候，它會發出一個中斷，也就是interrupt。中斷發生的時候，CPU會暫時停止目前手上的工作，然後跳到事先準備好的中斷處理常式去執行，就跟執行副程式沒什麼二樣。發生int3中斷時，就執行int3handler副程式，發生int21時，就執行int21handler副程式。這些中斷副程式，大多是由BIOS或作業系統提供，要不然就是應用程式提供。像這裡的int3副程式就是由debugger提供，專門用來處理debugger相關程序。&lt;br /&gt;
&lt;br /&gt;
如果你的程式是由一個debugger啟動的，那麼debugger會在你的程式開始執行之前，就已經事先安裝好debugger專用的int3副程式，這樣一來當CPU執行到int3的時候才能作適當的處理。另一方面，如果你的程式不是透過debugger啟動的，也就是說在你的程式啟動前，並沒有什麼人安裝了一個int3副程式，那麼當你的程式一執行到一個0xCC指令時，它就會當場當給你看。&lt;br /&gt;
&lt;br /&gt;
講到這裡再補充一下，當你在debugger你的程式的時候，假如你的程式是除錯版，那你一定會發現到那些未被初始化的變數內容都會是一堆0xCC。當時你一定會對這些變數的內容為什麼都是0xCC感到奇怪，現在學到了debugger第一招之後，終於了解到了這些0xCC可不是隨隨便便放進去的，它們是有特殊用意的。&lt;br /&gt;
&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
不過正常的情況下，我們都不必自己在程式裡面塞個0xCC。而是在debugger IDE裡面透過F9等方法，在執行裡放小紅點。這時候你會覺得奇怪，在開始debugger前我們的程式都已經編譯完成了，那麼用F9放小紅點的時候，這個0xCC是放到那裡去了？是插入放小紅點的位置呢？還是取代原來那個位置的指令，把它給蓋過去了？答案是後者。當然，debugger也不能那麼霸道。在它放入0xCC之前，會先把原來位置的指令儲存起來，以備在適當的時機再復原回來。&lt;br /&gt;
&lt;br /&gt;
各位，現在重點來了。當CPU執行到一個0xCC指令時，會幹什麼事呢？&lt;br /&gt;
&lt;br /&gt;
當CPU執行到一個0xCC指令時，會觸發一個int3中斷，這時CPU停下手邊工作，跳到int3副程式執行，而這個int3副程式是由debugger提供。所以說，剛剛的問題應該換成：當CPU執行到一個0xCC指令時，debugger會幹什麼事呢？&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;首先，debugger會把目前CPU所有的狀態儲存下來。這樣子，當我們對debugger說繼續跑的時候，debugger才能把原來的狀態復原，讓原來的工作能無接縫的繼續進行下去。&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;如果現在執行到的這個0xCC指令是我們自己插入到程式裡面去的，那麼debugger就不需要作什麼特別的處理。&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;如果這個0xCC指令是因為我們在debugger IDE裡透過像是按了F9等方式放進去的話，因為這個動作會取代原來的指令，所以現在要作的事情就是要把原來的指令還原，再執行原來的指令，這樣整個程式的狀態才會正確。執行動作如下：&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;將原來的指令寫回原來的位置。&lt;/li&gt;
&lt;li&gt;將CPU的狀態設定成單步執行，來執行原來的指令。CPU裡面有一個程式指位器，因為剛剛已經執行了0xCC，而本來應該是要執行原本的指令，所以在把原來指令還原後，還要再把程式指位器退回一步，這樣下次執行時才會執行到原來的指令。當CPU是單步狀態時，每執行一個指令就會觸發一次中斷，而像執行到0xCC時每次才會觸發一次int3中斷。而單步時觸發的中斷是int1，這是硬體中斷。&lt;/li&gt;
&lt;li&gt;當執行完原來的指令後，再取消CPU單步模式。控制權又回到了debugger。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;現在控制權在debugger手上，它會一直等待我們的命令，這時候我們就可以為所欲為，觀察變數內容，偷改記憶體內容等等，或再叫debugger繼續跑。&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;跳出繼續執行程式前，debugger會先把所有在一開始記錄下來的狀態復原，然後再繼續執行原來的程式。對原來的程式而言，它完全不知道被人動過什麼手腳。&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
一開始的時候講到有四種方法可以放小紅點，那麼第四種方法呢？&lt;br /&gt;
&lt;br /&gt;
上面講的三種方法是軟體中斷，剩下最後一個方法講的是硬體的中斷。有一組暫存器，透過設定你想要CPU停在那裡它就停在那裡。這是專門給debugger使用的，一般在程式裡頭不會去使用。使用硬體小紅點和軟體小紅點的差別是，用硬體小紅點不用像軟體小紅點那麼麻煩，需要在停下來時，再把原來的指令還原再執行然後再有的沒有的，再加上其它有的沒有的特殊技能。所以對於debugger內部來說，都會優先使用硬體小紅點，只不過硬體小紅點數量有限，當硬體小紅點用完了的時候，就要配合軟體小紅點。&lt;br /&gt;
&lt;br /&gt;
對了，忘了說當硬體小紅點觸發時，和CPU單步執行時一樣會發生一個int1中斷，所以也一樣會跳到int1副程式去執行。&lt;br /&gt;
&lt;br /&gt;
;&lt;br /&gt;
&lt;br /&gt;
現在將游標移動到第11行或if (20 == mul2(10))那一行，然後按下F9放一個小紅點。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Y6WuD2X3iMo/TrLOqo1WDdI/AAAAAAAAAlg/68RztN5s9XI/s1600/56-2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="150" width="320" src="http://1.bp.blogspot.com/-Y6WuD2X3iMo/TrLOqo1WDdI/AAAAAAAAAlg/68RztN5s9XI/s320/56-2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
接著按下F5開始debugger。你會看到執行到第11行的時候，程式就停下來了，在停下來的那行會有一個箭頭。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-NrUZhR_F8h8/TrLPTh95fSI/AAAAAAAAAls/KAqm6FpBlGw/s1600/56-3.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="148" width="320" src="http://4.bp.blogspot.com/-NrUZhR_F8h8/TrLPTh95fSI/AAAAAAAAAls/KAqm6FpBlGw/s320/56-3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
現在你知道，按了F9下小紅點，然後再按了F5開始debugger，然後程式在你放的小紅點停下來，這之間發生了什麼事情了。&lt;br /&gt;
&lt;br /&gt;
接下來，第二招要上場了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-6996874963957308310?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/FGROFzjmiIM" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/11/how-to-debugger-1.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-ARDWzVD4nkM/TrFtNiC93jI/AAAAAAAAAlQ/rEQq8D3qS6s/s72-c/56-1.png" height="72" width="72" /><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-3338782655114908386</guid><pubDate>Wed, 05 Oct 2011 15:33:00 +0000</pubDate><atom:updated>2011-10-05T23:33:06.149+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Sample</category><title>新增OnDraw事件及簡單繪圖API</title><description>新增一個OnDraw事件用來作OwnerDraw的支援。如：&lt;br /&gt;
&lt;br /&gt;
Level = {}&lt;br /&gt;
...&lt;br /&gt;
Level.OnDraw = function(param)&lt;br /&gt;
...&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
當物件提供OnDraw事件的Handler時，原來預設的繪圖處理就會被忽略，也就是說必須由User自行把物件繪製出來，包含其子物件。既然提供了OwnerDraw的支援，那就也必須提供繪圖函數的支援。所以另外增加了二個最基本的繪圖API：Graphics.DrawImage及Graphics.FillRect。&lt;br /&gt;
&lt;br /&gt;
有了OwnerDraw的支援後，有些動作使用OwnerDraw來繪製比起透過建立物件的方式來處理就會方便多了。底下是利用OwnerDraw功能寫的一個小Sample作為示範。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-E_PcDYnPrLM/Tox36_z5EiI/AAAAAAAAAkQ/4B4qyVO8eLY/s1600/55-1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="234" width="208" src="http://3.bp.blogspot.com/-E_PcDYnPrLM/Tox36_z5EiI/AAAAAAAAAkQ/4B4qyVO8eLY/s400/55-1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-3338782655114908386?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/saQ3zqSB0Us" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/10/ondrawapi.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-E_PcDYnPrLM/Tox36_z5EiI/AAAAAAAAAkQ/4B4qyVO8eLY/s72-c/55-1.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-4527583369945614213</guid><pubDate>Thu, 29 Sep 2011 16:29:00 +0000</pubDate><atom:updated>2011-09-30T00:29:24.657+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Editor</category><category domain="http://www.blogger.com/atom/ns#">stge</category><title>新增STGE粒子測試器</title><description>&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/al_gAY-IXBI" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-4527583369945614213?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/G_xYiuXNKyE" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/09/stge.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/al_gAY-IXBI/default.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-7038874499584766528</guid><pubDate>Fri, 02 Sep 2011 07:59:00 +0000</pubDate><atom:updated>2011-09-02T15:59:54.455+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Fun</category><title>不能Google9999999..99999999999999999999999</title><description>試著在Google裡搜尋9999999..99999999999999999999999，你會發現Google也有不能Google的東西。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-7038874499584766528?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/KMVwKYjR50A" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/09/google999999999999999999999999999999.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-4748161999154215483</guid><pubDate>Sun, 21 Aug 2011 16:39:00 +0000</pubDate><atom:updated>2011-08-22T00:39:23.964+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Game</category><title>鋤草機完全攻略</title><description>&lt;iframe width="420" height="345" src="http://www.youtube.com/embed/P-sSHRYqqg4" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
(&lt;a href="http://www.smallworld.idv.tw/dl/weederG.rar"&gt;下載&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-4748161999154215483?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/ev7fDbf1YBg" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/08/blog-post.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/P-sSHRYqqg4/default.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-4308241979495036382</guid><pubDate>Tue, 02 Aug 2011 16:16:00 +0000</pubDate><atom:updated>2011-08-03T00:16:33.714+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Algorithm</category><category domain="http://www.blogger.com/atom/ns#">Fun</category><title>充分發揮多核威力的排序法 sleep sort</title><description>&lt;b&gt;程式(sleepsort.bash):&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
while [ -n "$1" ]&lt;br /&gt;
do&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(sleep "$1"; echo "$1") &amp;amp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;shift&lt;br /&gt;
done&lt;br /&gt;
wait&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;執行例:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: lime;"&gt;user@your-c24a217e1d ~&lt;/span&gt;&lt;br /&gt;
$ bash sleepsort.bash 4 1 3&lt;br /&gt;
1&lt;br /&gt;
3&lt;br /&gt;
4&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="background-color: lime;"&gt;user@your-c24a217e1d ~&lt;/span&gt;&lt;br /&gt;
$ bash sleepsort.bash 4 2 5 1 3&lt;br /&gt;
1&lt;br /&gt;
2&lt;br /&gt;
3&lt;br /&gt;
4&lt;br /&gt;
5&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-4308241979495036382?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/ISc7NAAa_Ts" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/08/sleep-sort.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-2132118897639422547</guid><pubDate>Mon, 01 Aug 2011 03:05:00 +0000</pubDate><atom:updated>2011-08-01T11:05:22.809+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Math</category><category domain="http://www.blogger.com/atom/ns#">Fun</category><title>Batman Eqution</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-GZwFTqrvkJk/TjYXzl3arPI/AAAAAAAAAkE/KcPc8Kpih8s/s1600/CNy9J.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="387" src="http://1.bp.blogspot.com/-GZwFTqrvkJk/TjYXzl3arPI/AAAAAAAAAkE/KcPc8Kpih8s/s400/CNy9J.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-2132118897639422547?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/dWtHas0G2Wc" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/08/batman-eqution.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-GZwFTqrvkJk/TjYXzl3arPI/AAAAAAAAAkE/KcPc8Kpih8s/s72-c/CNy9J.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-1004897140225309966</guid><pubDate>Wed, 27 Jul 2011 19:17:00 +0000</pubDate><atom:updated>2011-07-28T03:17:35.203+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/C++</category><title>mutable關鍵字的用法</title><description>mutable關鍵字總是會和const關鍵字扯上關係，所以要使用mutable關鍵字前，你先要知道const關鍵字的用法。const關鍵字的使用方法這裡就不提了，這是閱讀本文的基礎知識。&lt;br /&gt;
&lt;br /&gt;
關鍵字const的用途很廣，這裡我們只需專注在和mutable有關係的部份即可，那就是const member function。&lt;br /&gt;
&lt;br /&gt;
; 範例1&lt;br /&gt;
class Sprite&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
...&lt;br /&gt;
int getWidth() const;&lt;br /&gt;
int getHeight() const;&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
如範例所示，Sprite的getWidth和getHeight函式都是const，表示說呼叫到這二個函式的時候不會變動到任何這個Sprite物件內的資料。這是一般的情況。可是有時候我們所設計的介面，雖然在語意上它是const，但在實作上我們又不得不去變動到物件內部的某些資料。&lt;br /&gt;
&lt;br /&gt;
; 範例2&lt;br /&gt;
class ResourceManager&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
...&lt;br /&gt;
bool loadResource(string const&amp; resName, ResourceItemHandle&amp; item) const;&lt;br /&gt;
...&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
在範例中ResourceManager提供的loadResource函式，依照原始的設計，這個函式它會載入指定名稱的ResourceItem，而這個動作不會對ResourceManager內部產生任何變更。可是為了增加效率，我們在實作時在ResourceManager內部作了一個Cache的動作，把載入的ResourceItem快取起來，這樣下次再載入時就可以直接用比較快的速度完成載作動作。&lt;br /&gt;
&lt;br /&gt;
這個時候就會產生如上所提到的和const衝突的情形，所以我們就只好把const修飾拿掉。拿掉const修飾字是一種解決的方法，但長遠來看這實在不是個好主意。解決的辨法是使用mutable關鍵字。&lt;br /&gt;
&lt;br /&gt;
; 範例3&lt;br /&gt;
class ResourceManager&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
...&lt;br /&gt;
bool loadResource(string const&amp; resName, ResourceItemHandle&amp; item) const;&lt;br /&gt;
...&lt;br /&gt;
private:&lt;br /&gt;
mutable ResourceItemCache cache ;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
在範例3裡面，我們加了一個用來對ResourceItem作快取的member。loadResource函式被呼叫時會先在這裡面搜尋是否同一個resource已被載入過，如果是就不再作真正的載入動作直接拿cache內的資料來使用。要不然就執行真正的載入動作，載入成功後再把載入的ResourceItem存到cache內以備下次快速載入用。&lt;br /&gt;
&lt;br /&gt;
在宣告cache時，我們對cache這個member加了mutable修飾字。這樣一來，loadResource就可以成功的通過編譯，即使它加了const修飾字。&lt;br /&gt;
&lt;br /&gt;
這樣子你的程式就可以更有魯棒性了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-1004897140225309966?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/K3VS4crxuhU" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/07/mutable.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-6732076519765351442</guid><pubDate>Thu, 21 Jul 2011 16:49:00 +0000</pubDate><atom:updated>2011-07-22T00:49:08.138+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Editor</category><title>Good Game Editor 短片</title><description>錄了二段影片。。。&lt;br /&gt;
&lt;br /&gt;
&lt;iframe width="425" height="349" src="http://www.youtube.com/embed/wo-ZAKNH8eE?hl=zh&amp;fs=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;iframe width="425" height="349" src="http://www.youtube.com/embed/w-DcTnP1nzQ?hl=zh&amp;fs=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-6732076519765351442?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/m1J1vOQ_bug" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/07/good-game-editor.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/wo-ZAKNH8eE/default.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-7492241136349959081</guid><pubDate>Sun, 17 Jul 2011 01:43:00 +0000</pubDate><atom:updated>2011-07-17T09:51:20.715+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">stge</category><category domain="http://www.blogger.com/atom/ns#">Sample</category><title>新增範例：stge2</title><description>新增一個簡單的粒子範例。(&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=25"&gt;下載&lt;/a&gt;)&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-tLofYezt2Yk/TiI-f7ifiDI/AAAAAAAAAjI/GwWUnrr6_Ng/s1600/53-1.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 380px; height: 400px;" src="http://3.bp.blogspot.com/-tLofYezt2Yk/TiI-f7ifiDI/AAAAAAAAAjI/GwWUnrr6_Ng/s400/53-1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5630131202445772850" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-PfQBAkyAxWk/TiI_Of9BPbI/AAAAAAAAAjg/AmJIZAUxn3k/s1600/53-4.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 380px; height: 400px;" src="http://3.bp.blogspot.com/-PfQBAkyAxWk/TiI_Of9BPbI/AAAAAAAAAjg/AmJIZAUxn3k/s400/53-4.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5630132002494692786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-l3HVAIKnRp8/TiI-gFWulJI/AAAAAAAAAjY/WejvM-yaY48/s1600/53-3.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 380px; height: 400px;" src="http://3.bp.blogspot.com/-l3HVAIKnRp8/TiI-gFWulJI/AAAAAAAAAjY/WejvM-yaY48/s400/53-3.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5630131205080781970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-7492241136349959081?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/VMfXSWWe-Z8" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/07/stge2.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-tLofYezt2Yk/TiI-f7ifiDI/AAAAAAAAAjI/GwWUnrr6_Ng/s72-c/53-1.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-8193138259956592188</guid><pubDate>Thu, 30 Jun 2011 16:17:00 +0000</pubDate><atom:updated>2011-07-01T00:19:42.932+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Editor</category><title>新增MRU</title><description>&lt;div&gt;新增MRU(&lt;span class="Apple-style-span" style="font-family: arial, sans-serif; line-height: 16px; font-size: small; "&gt;Most Recently Used) list。&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-8193138259956592188?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/Cy4l8GcMbcQ" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/07/mru.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-6157660899507585581</guid><pubDate>Fri, 24 Jun 2011 15:21:00 +0000</pubDate><atom:updated>2011-06-24T23:24:31.222+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Editor</category><title>2011/06/24 更新記錄</title><description>&lt;ol&gt;&lt;li&gt;修正一個拼字錯誤(You are using latest version.)&lt;/li&gt;&lt;li&gt;拿掉新增貼圖對話盒(Add new texture dialog), 簡化成開啟檔案對話盒(Open file dialog)作檔案選取&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-6157660899507585581?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/JWWyF5yAL10" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/06/20110624.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-3006513913566212770</guid><pubDate>Tue, 10 May 2011 17:14:00 +0000</pubDate><atom:updated>2011-05-11T01:44:38.849+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Editor</category><category domain="http://www.blogger.com/atom/ns#">Game</category><title>任務檢測器</title><description>翻到一個古董，再把資料檔案翻出來，還可以執行！這是第一份工作時製作的小工具之一，功能是用來檢視及測試編輯好的任務。設計的這個Script實際上就好像是在寫組合語言一樣，只不過到後來企劃也訓練的會寫組合語言了...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-dBg_V71mqR4/TclyqsezbfI/AAAAAAAAAic/zPpJSlWh1VQ/s1600/clip_1.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://1.bp.blogspot.com/-dBg_V71mqR4/TclyqsezbfI/AAAAAAAAAic/zPpJSlWh1VQ/s400/clip_1.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5605137289059724786" /&gt;&lt;/a&gt;(單步/執行結果)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-K-HiK6xpekE/TclyrA3FdfI/AAAAAAAAAik/ihX_QvCIPIU/s1600/clip_2.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://1.bp.blogspot.com/-K-HiK6xpekE/TclyrA3FdfI/AAAAAAAAAik/ihX_QvCIPIU/s400/clip_2.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5605137294530278898" /&gt;&lt;/a&gt;(玩家屬性)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-vjtTxdEU-c0/TclyrDv20mI/AAAAAAAAAis/ut5FJV8RqUA/s1600/clip_3.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://2.bp.blogspot.com/-vjtTxdEU-c0/TclyrDv20mI/AAAAAAAAAis/ut5FJV8RqUA/s400/clip_3.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5605137295305265762" /&gt;&lt;/a&gt;(任務原始碼)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-8N3aGtXNBSk/Tcl2vZ2n1JI/AAAAAAAAAi4/A0GEZDYKNdg/s1600/clip_4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://4.bp.blogspot.com/-8N3aGtXNBSk/Tcl2vZ2n1JI/AAAAAAAAAi4/A0GEZDYKNdg/s400/clip_4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5605141768005211282" /&gt;&lt;/a&gt;(字串表)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-3006513913566212770?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/9oOoJYb5sBE" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/05/blog-post.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-dBg_V71mqR4/TclyqsezbfI/AAAAAAAAAic/zPpJSlWh1VQ/s72-c/clip_1.jpg" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-1811208433180106189</guid><pubDate>Tue, 19 Apr 2011 17:53:00 +0000</pubDate><atom:updated>2011-04-20T02:00:10.877+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Editor</category><title>地圖編輯器(Map Editor)橡皮擦工具允許改變大小</title><description>根據偶然經過的旅人的&lt;a href="http://good-ed.smallworld.idv.tw/forum/viewtopic.php?f=11&amp;t=66"&gt;建議&lt;/a&gt;，將地圖編輯器(Map Editor)裡的橡皮擦改成也能夠自訂大小，這樣一來在作清除時可以自行決定方便使用的大小，改變大小的方法和在作畫時以滑鼠右鍵作區塊選取的操作相同。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-X49HwB2hYgQ/Ta3NCrJuVLI/AAAAAAAAAh8/8QSVjSmHsNg/s1600/clip_6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 362px; height: 276px;" src="http://4.bp.blogspot.com/-X49HwB2hYgQ/Ta3NCrJuVLI/AAAAAAAAAh8/8QSVjSmHsNg/s400/clip_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5597355357718336690" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-1811208433180106189?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/Ikg5nAUTqBg" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/04/map-editor.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-X49HwB2hYgQ/Ta3NCrJuVLI/AAAAAAAAAh8/8QSVjSmHsNg/s72-c/clip_6.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-5530198289099005834</guid><pubDate>Wed, 23 Mar 2011 17:01:00 +0000</pubDate><atom:updated>2011-03-24T01:03:19.205+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Sample</category><title>範例：滑鼠及訊息</title><description>這個簡單的範例，主要示範如何取得滑鼠的坐標及狀態，同時也示範如何即時將這些資訊轉換成文字顯示在畫面上。　&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=23"&gt;下載&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-RcbRN2w3Qtw/TYondqUN-QI/AAAAAAAAAhk/5bSOORYtYdo/s1600/mouse.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 317px;" src="http://4.bp.blogspot.com/-RcbRN2w3Qtw/TYondqUN-QI/AAAAAAAAAhk/5bSOORYtYdo/s400/mouse.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5587321678235302146" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-5530198289099005834?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/uOT3s-lj6Iw" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/03/blog-post_24.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-RcbRN2w3Qtw/TYondqUN-QI/AAAAAAAAAhk/5bSOORYtYdo/s72-c/mouse.png" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-1810103004135707554</guid><pubDate>Tue, 15 Mar 2011 18:41:00 +0000</pubDate><atom:updated>2011-03-16T02:44:16.398+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">good</category><category domain="http://www.blogger.com/atom/ns#">Sample</category><title>範例：遊戲存檔</title><description>新增一個範例&lt;br /&gt;&lt;br /&gt;這個簡單的範例，示範利用Lua的io模組作到簡單的遊戲存檔功能。　&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=22"&gt;下載&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-1810103004135707554?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/Qsl_P1BslSM" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/03/blog-post_16.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-5883841030666884332</guid><pubDate>Tue, 08 Mar 2011 16:20:00 +0000</pubDate><atom:updated>2011-03-09T00:23:15.875+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/C++</category><title>不可思議: for (i = 0; i &lt; 10; i++) 停不下來 !?</title><description>其實這是一個真實事件...&lt;br /&gt;&lt;br /&gt;某一天上班時，我從一早就三不五時的聽到坐在我背後的同事低聲的哇哇叫。幾次下來，我也忍不住好奇的湊過去看看到底是怎麼一回事。結果他Demo了這麼一個不可思議的for迴圈給我看，難怪他一整個早上都在哇哇叫。這位同事因為整個陷入在這個不可思議的for迴圈裡而跳不出來，找不到問題的所在。但當局者迷，我當下眉頭一皺發覺事情並不單純，問題肯定不是出在這個for迴圈上面，再怎麼去看也是白癈力氣。這種奇奇怪怪的問題，很有可能是和記憶體的使用有關係，這個不可思議的for迴圈只不過是因為其它地方的Bug，所產生的現象。我把我的想法告訴了我這位同事後，過了不了多久，果然在其它地方找到了真正的問題所在，的確是因為記憶體的使用不當造成的現象。&lt;br /&gt;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;底下在VC2003寫支小程式，立刻就能摸擬出這樣的現象。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;int main()&lt;br /&gt;{&lt;br /&gt;   int i, a[1];&lt;br /&gt;   for (i = 0; i &lt; 10; i++) {&lt;br /&gt;       a[i] = 0;&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;如上所示，我宣告了一個只有一個元素的陣列a，然後用一個for迴圈去填a的內容。這裡所要示範的一個概念是：會產生這樣的問題，是因為i的值被其它人動到了。而在這個簡單的例子，就是利用這個概念，想辨法讓在填a的內容時，因為填寫錯誤(超出範圍)，而去覆寫了i的值，而造成for迴圈停不下來的奇妙現象。&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-xtarLqKZ6bE/TXZXwuD-T9I/AAAAAAAAAg8/0vo7rQMuEcA/s1600/for1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 279px; height: 230px;" src="http://1.bp.blogspot.com/-xtarLqKZ6bE/TXZXwuD-T9I/AAAAAAAAAg8/0vo7rQMuEcA/s400/for1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5581745282682343378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;如圖在除錯模式中，在Watch裡加上檢視i和陣列a的位址和內容，然後一步步執行看看。可以發現i的位址和a[3]重疊了，但問題是a只宣告了一個元素，而這個迴圈卻打算存取10個元素。在這樣的情況下，i的值果然被覆寫了，所以這個for迴圈就這樣成為無窮迴圈而永遠跳不出來。&lt;br /&gt;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;PS: 這個實驗是在VC2003和2005上作的，在其它Compiler也許會有不一樣的結果。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-5883841030666884332?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/D8vLuKhWEFw" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/03/for-i-0-i-10-i.html</link><author>noreply@blogger.com (Waync Cheng)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-xtarLqKZ6bE/TXZXwuD-T9I/AAAAAAAAAg8/0vo7rQMuEcA/s72-c/for1.png" height="72" width="72" /><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-19707291081661996</guid><pubDate>Fri, 04 Mar 2011 08:30:00 +0000</pubDate><atom:updated>2011-03-04T16:34:57.951+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Design</category><title>關於最佳化</title><description>&lt;ul&gt;&lt;li&gt;過早作最佳化是萬惡的根源 (Premature optimization is the root of all evil.)&lt;/li&gt;&lt;li&gt;最佳化守則&lt;/li&gt;&lt;ol&gt;&lt;li&gt;別作! (Don't do it!)&lt;/li&gt;&lt;li&gt;高手專用：先別作! (For experts only: Don't do it yet!)&lt;/li&gt;&lt;/ol&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-19707291081661996?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/kTuCel0XC24" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/03/blog-post.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-7433440235463873149</guid><pubDate>Mon, 21 Feb 2011 14:11:00 +0000</pubDate><atom:updated>2011-02-21T22:20:12.637+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/C++</category><title>char *(*(**foo[][8])())[] ???</title><description>對於底下的宣告，我們很容易就能夠辨認。&lt;br /&gt;&lt;br /&gt;int i;&lt;br /&gt;&lt;br /&gt;一個int變數i。&lt;br /&gt;&lt;br /&gt;char *p;&lt;br /&gt;&lt;br /&gt;一個指向char的變數p，也就是一個char指標。&lt;br /&gt;&lt;br /&gt;那麼，底下這個宣告呢？&lt;br /&gt;&lt;br /&gt;double **d[8];&lt;br /&gt;&lt;br /&gt;比較難點了，不過要辨識還不致於太困難。這是一個有8個元素的double的指標的指標的陣列(開始...了)。&lt;br /&gt;&lt;br /&gt;那麼，底下這個呢？&lt;br /&gt;&lt;br /&gt;char *(*(**foo[][8])())[];&lt;br /&gt;&lt;br /&gt;絶大部份的人看到這樣子的宣告，肯定會嚇一大跳，心裡面想說：靠，這是什麼鬼東西！&lt;br /&gt;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;要理解這樣的宣告，可以遵循底下的三條規則：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;從變數的名稱開始看。&lt;/li&gt;&lt;li&gt;到變數的類型作結束(如上的int,char)。&lt;/li&gt;&lt;li&gt;先盡量往右看，直到有需要時再往左看(如遇到括號)。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;如下所示是分解動作。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); background-color: rgb(222, 231, 236); "&gt;Expression&lt;/th&gt;&lt;th style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); background-color: rgb(222, 231, 236); "&gt;Meaning&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;char *(*(**foo [][8])())[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *(*(**&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;foo&lt;/del&gt; [][8])())[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;foo is … char&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *(*(**&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;foo []&lt;/del&gt;[8])())[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;an array of&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *(*(**&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;foo [][8]&lt;/del&gt;)())[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;an array of 8&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *(*(*&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;*foo [][8]&lt;/del&gt;)())[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of an array of 8 &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;pointer to&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *(*&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;(**foo [][8])&lt;/del&gt;())[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of an array of 8 pointer to &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;pointer to&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *(*&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;(**foo [][8])()&lt;/del&gt;)[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of an array of 8 pointer to pointer to &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;function returning&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;(*(**foo [][8])())&lt;/del&gt;[]&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of an array of 8 pointer to pointer to function returning &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;pointer to&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char&lt;/del&gt; *&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;(*(**foo [][8])())[]&lt;/del&gt;&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of an array of 8 pointer to pointer to function returning pointer to &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;array of&lt;/strong&gt; … char&lt;/td&gt;&lt;/tr&gt;&lt;tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;&lt;code style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 12px; "&gt;&lt;del style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;char *(*(**foo [][8])())[]&lt;/del&gt;&lt;/code&gt;&lt;/td&gt;&lt;td style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(140, 172, 187); border-right-color: rgb(140, 172, 187); border-bottom-color: rgb(140, 172, 187); border-left-color: rgb(140, 172, 187); "&gt;foo is an array of an array of 8 pointer to pointer to function returning pointer to array of &lt;strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;pointer to&lt;/strong&gt; char&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;參考 : &lt;a href="http://www.unixwiz.net/techtips/reading-cdecl.html"&gt;http://www.unixwiz.net/techtips/reading-cdecl.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;不過話說回來，我自己是不可能會在程式裡面用上這種自己都搞不大清楚的東西。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-7433440235463873149?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/7gnjbz4idfU" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/02/char-foo8.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-5649517375485401492</guid><pubDate>Sun, 30 Jan 2011 18:09:00 +0000</pubDate><atom:updated>2011-01-31T03:21:53.911+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>用Java寫一個簡單的Web Server</title><description>Java的生產力很高，拿它來寫個簡單的Web Server只需要不到200行的程式碼，底下就用Java一步一步實作一個簡單的HTTP網頁伺服器。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;在開始前，需要對&lt;a href="http://zh.wikipedia.org/zh-tw/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE"&gt;HTTP協定&lt;/a&gt;有一個基本的認識，在我們這個例子裡面，只需要知道GET請求(Request)即可。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;當我們在瀏覽器的網址列輸入一個位址時，瀏覽器會送出一個GET請求到位址欄裡指定的網頁伺服器，去跟這個網頁伺服器取得網頁或檔案的內容。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;例如，我們在網址列輸入 &lt;a href="http://www.google.com.tw/"&gt;http://www.google.com.tw/&lt;/a&gt;，就是向www.google.com.tw這台伺服器要求一個檔案，而要求的檔案就是首頁(/)。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;這個動作，瀏覽器會送出如下的HTTP請求命令到伺服器去 (以Chrome為例)：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;div&gt;GET / HTTP/1.1&lt;/div&gt;&lt;div&gt;Host: www.google.com.tw&lt;/div&gt;&lt;div&gt;Connection: keep-alive&lt;/div&gt;&lt;div&gt;Cache-Control: max-age=0&lt;/div&gt;&lt;div&gt;Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,i&lt;/div&gt;&lt;div&gt;mage/png,*/*;q=0.5&lt;/div&gt;&lt;div&gt;User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.10 (&lt;/div&gt;&lt;div&gt;KHTML, like Gecko) Chrome/8.0.552.237 Safari/534.10&lt;/div&gt;&lt;div&gt;Accept-Encoding: gzip,deflate,sdch&lt;/div&gt;&lt;div&gt;Accept-Language: zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4&lt;/div&gt;&lt;div&gt;Accept-Charset: Big5,utf-8;q=0.7,*;q=0.3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;注意，這裡還有一個空行，表示結束&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;這裡的重點是第一行和最後一行。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;由第一行，伺服器可以知道Client作的是那一種類的請求，這裡可以明顯的看到Client(Chrome)作了一個GET請求。同時，在第一行裡面也可以知道Client請求的是什麼。在此例中，可以看到Client請求的是/這個檔案。在第一行最後的部份，則是註明HTTP協定的版本號。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;而最後一行，是一個空行，表示請求包的結束。伺服器在收到一個請求時，從第一行的請求命令開始，一直讀取到一個空行為止，為一個完整的封包。除了第一行和最後一行，對我們的簡單伺服器來說，中間的部份可以全都忽略不看。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;伺服器收這個GET請求後，假如可以找到到指定的檔案，接下來就會把Client請求的檔案內容回傳，使用的格式如下：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;HTTP/1.0 200 OK&lt;/div&gt;&lt;div&gt;Content-Type: text/html&lt;/div&gt;&lt;div&gt;Content-Length: &lt;length&gt;&lt;/length&gt;&lt;/div&gt;&lt;div&gt;&lt;注意，這裡還有一個空行，表示結束&gt;&lt;/div&gt;&lt;div&gt;&lt;接下來，這裡開始都是檔案資料內容，總長度為Content-Length所指定的數字&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;否則回傳我們常見的404 Not Found錯誤，如下：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;HTTP/1.0 404 File Not Found&lt;/div&gt;&lt;div&gt;&lt;注意，這裡還有一個空行，表示結束&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;有了以上這些知識後，就足夠我們寫個簡單的網頁伺服器。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;考慮到因為每一個Client的請求，都是在發出時才和伺服器建立連線，完成後就立即切斷連線。所以在設計上，我們可以用多緒(multi-thread)的方法，每一個請求都用一個獨立的執行緒來處理，處理完成後切斷連線，同時也結束這個執行緒。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;根據這個想法，很直接的就可以寫出如下的基本框架來：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;public class SimpleWebServer implements Runnable {&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　ServerSocket server = null ;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　public static void main(String args[]) throws Exception {&lt;/div&gt;&lt;div&gt;　　new SimpleWebServer(80);&lt;/div&gt;&lt;div&gt;　}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　public SimpleWebServer(int port) throws Exception {&lt;/div&gt;&lt;div&gt;　　server = new ServerSocket(port) ;&lt;/div&gt;&lt;div&gt;　　run();&lt;/div&gt;&lt;div&gt;　}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　public void run() {&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　try {&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　　//&lt;/div&gt;&lt;div&gt;　　　// 1, 等待一個新的連接請求(Request).&lt;/div&gt;&lt;div&gt;　　　//&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　　Socket s = server.accept();&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　　//&lt;/div&gt;&lt;div&gt;　　　// 2, 開新Thread處理新連接請求.&lt;/div&gt;&lt;div&gt;　　　//&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　　Thread task = new Thread(this);&lt;/div&gt;&lt;div&gt;　　　task.start();&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　　//&lt;/div&gt;&lt;div&gt;　　　// 3, 處理請求內容.&lt;/div&gt;&lt;div&gt;　　　//&lt;/div&gt;&lt;div&gt;　　　&lt;/div&gt;&lt;div&gt;　　　handleRequest(...);&lt;/div&gt;&lt;div&gt;　　}&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;如上，在進入點main我們開了一個SimpleWebServer，給它一個80的port number(80是HTTP的port number)。SimpleWebServer的Constructor會建立一個&lt;a href="http://download.oracle.com/javase/1.4.2/docs/api/java/net/ServerSocket.html"&gt;ServerSocket&lt;/a&gt;的實體，然後啟動主執行緒。執行緒的主體非常簡單，它只作三件事情。&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;等待一個新的請求連線進來。&lt;/li&gt;&lt;li&gt;開啟一個新的執行緒繼續等待下一個新的連線請求進來。&lt;/li&gt;&lt;li&gt;處理這個請求。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;完成這三件事情後，這條連線被關閉，執行緒結束。&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;以上的部份，已經是一個可以執行的最簡易版伺服器，差別只在於它完全不處理作任事。接下來，我們再把最後處理請求的部份完成。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;void handleRequest(Socket s, BufferedReader reader, DataOutputStream os) throws Exception {&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　try {&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　//&lt;/div&gt;&lt;div&gt;　　// 1, 讀取HTTP Header字串.&lt;/div&gt;&lt;div&gt;　　//&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　//&lt;/div&gt;&lt;div&gt;　　// 2, 解出請求的資源路徑.&lt;/div&gt;&lt;div&gt;　　//&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　//&lt;/div&gt;&lt;div&gt;　　// 3, 處理請求的資源.&lt;/div&gt;&lt;div&gt;　　// (測試: 只處理Homepage的請求)&lt;/div&gt;&lt;div&gt;　　//&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;　　if ("/".equals(path) || "index.html".equals(path)) {&lt;/div&gt;&lt;div&gt;　　　String homepage = "Hello Simple Web Server";&lt;/div&gt;&lt;div&gt;　　　os.writeBytes(&lt;/div&gt;&lt;div&gt;　　　　　"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nContent-Length: " +&lt;/div&gt;&lt;div&gt;　　　　　homepage.length() +&lt;/div&gt;&lt;div&gt;　　　　　"\r\n\r\n" +&lt;/div&gt;&lt;div&gt;　　　　　homepage);&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　　return;&lt;/div&gt;&lt;div&gt;　　}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;　　os.writeBytes("HTTP/1.0 404 File Not Found\r\n\r\n");&lt;/div&gt;&lt;div&gt;　} catch (Exception e) {&lt;/div&gt;&lt;div&gt;　　os.writeBytes("HTTP/1.0 500 Internal Server Error\r\n\r\n");&lt;/div&gt;&lt;div&gt;　}&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;處理請求的部份也是分為三個步驟：&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;讀出HTTP請求內容。&lt;/li&gt;&lt;li&gt;從讀出的HTTP請求裡，取出請求的檔案名稱路徑。&lt;/li&gt;&lt;li&gt;傳送請求的檔案內容。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;因為我們只實作一個最簡單的網頁伺服器，所以只處埋Homepage的請求。如果Client要求的是首頁，就回傳首頁的內容，這邊只回傳一個簡單的字串"Hello Simple Web Server"表示首頁。否則回傳找不到檔案的錯誤404 Not Found。其它狀況，則回傳伺服器錯誤500的錯誤碼。(更多的錯誤碼可以在&lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;這裡&lt;/a&gt;找到。)&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;完整的原始程式碼，在&lt;a href="http://good-ed.smallworld.idv.tw/forum/download/file.php?id=20"&gt;這裡&lt;/a&gt;下載。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-5649517375485401492?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/OYTvNF9e04s" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/01/javaweb-server.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4380486110383106325.post-1872457110343743964</guid><pubDate>Sat, 22 Jan 2011 13:36:00 +0000</pubDate><atom:updated>2011-01-22T21:40:25.030+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Game</category><category domain="http://www.blogger.com/atom/ns#">Fun</category><title>Youtube密技</title><description>&lt;ol&gt;&lt;li&gt;進入&lt;a href="http://www.youtube.com/?gl=TW&amp;amp;hl=zh-TW"&gt;Youtube&lt;/a&gt;&lt;/li&gt;&lt;li&gt;隨便開啟一個影片&lt;/li&gt;&lt;li&gt;影片開始播放後按下暫停&lt;/li&gt;&lt;li&gt;同時按下鍵盤的↑和←鍵&lt;/li&gt;&lt;li&gt;進入貪食蛇模式&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4380486110383106325-1872457110343743964?l=good-ed.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/good-ed/~4/UT_7rpCzDOc" height="1" width="1"/&gt;</description><link>http://good-ed.blogspot.com/2011/01/youtube.html</link><author>noreply@blogger.com (Waync Cheng)</author><thr:total>0</thr:total></item></channel></rss>

