<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>modify_rss</title>
		<link>http://ccckmit.wikidot.com</link>
		<description>陳鍾誠的首頁 -- 金門大學 資訊工程系</description>
				<copyright></copyright>
		<lastBuildDate>Sun, 17 May 2026 03:15:02 +0000</lastBuildDate>
		
					<item>
				<guid>http://ccckmit.wikidot.com/story:honestbagel</guid>
				<title>陳鍾誠閱讀的故事集 -- 良心貝果的故事</title>
				<link>http://ccckmit.wikidot.com/story:honestbagel</link>
				<description>

&lt;p&gt;以下是《蘋果橘子經濟學》裡提到的一個真實故事：&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 27 Oct 2010 07:20:29 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>以下是《蘋果橘子經濟學》裡提到的一個真實故事：</p> <hr /> <p>美國有個金融業高薪人士，在公司提供免費貝果給同事食用，反應非常良好，後來大家都來要貝果後，該位仁兄開始不勝負荷，於是決定採用《良心投幣筒》的方式收費，讓大家拿了貝果後自動投錢。</p> <p>後來這位仁兄工作不順遂，於是辭掉工作專心去賣各大公司「良心貝果」，同樣採用《良心投幣筒》的方式，沒想到卻一炮而紅，生意好得不得了，所得比他原本的薪水還高。</p> <p>但是並非每個買貝果的人都會付錢，平均而言、大約有百分之九十五的人會付錢。賣貝果的仁兄由於待過金融業，具有詳細記帳的習慣，因此會記下每個良心投幣筒的付錢比率，連續記帳二十年的結果，讓這份「貝果報告」成為研究白領犯罪的最佳統計資料。</p> <p>投幣比率根據地區、天氣、景氣、時事等因素而有所不同，一個很有趣的例子是，貝果仁兄根據其統計認為，高階主管的投幣比率較低，因為這些人可能忙於公事，因而忘了投幣。但是經濟學者 Steven D. Levitt 提醒他，會不會這些人就是因為沒良心、懂得欺騙才升上高階主管的呢？</p> <hr /> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:inline</guid>
				<title>高等 C 語言 -- 使用 Inline 函數</title>
				<link>http://ccckmit.wikidot.com/cp:inline</link>
				<description>

&lt;h1&gt;&lt;span&gt;程式範例&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 24 Jan 2011 09:35:56 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <h1><span>程式範例</span></h1> <p>檔案：inline.c</p> <div class="code"> <pre><code>inline int max(a,b) { return (a&gt;b?a:b); } inline int min(a,b) { return (a&lt;b?a:b); } int main() { int x = max(3,5); int y = min(3,5); printf(&quot;max(3,5)=%d\n&quot;, x); printf(&quot;min(3,5)=%d\n&quot;, y); }</code></pre></div> <h1><span>巨集展開結果</span></h1> <p>執行 gcc -E inline.c -o inline.i 指令之後，就會得到 inline.i</p> <p>檔案：inline.i</p> <div class="code"> <pre><code>inline int max(a,b) { return (a&gt;b?a:b); } inline int min(a,b) { return (a&lt;b?a:b); } int main() { int x = max(3,5); int y = min(3,5); printf(&quot;max(3,5)=%d\n&quot;, x); printf(&quot;min(3,5)=%d\n&quot;, y); }</code></pre></div> <h1><span>來自 jserv 的建議</span></h1> <p>原本我寫了這句：「將函數巨集化 — (inline) 使用 inline 可以增快速度，但也會讓程式碼增大」，但似乎有很大問題，所以我就拿掉了，但是我搞不清楚問題在哪？所以忠實呈現 jserv 的來信建議。</p> <div class="code"> <pre><code>&quot;將函數巨集化 — (inline) 使用 inline 可以增快速度，但也會讓程式碼增大。&quot; =&gt; 這嚴重誤導讀者！ C99 的 inline 行為和 macro 不同，請見: http://www.greenend.org.uk/rjk/tech/inline.html</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:macro</guid>
				<title>高等 C 語言 -- 巨集 (Macro)</title>
				<link>http://ccckmit.wikidot.com/cp:macro</link>
				<description>

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:macro&quot;&gt;巨集處理&lt;/a&gt; &amp;#8212; (Macro &amp;amp; Conditional Expansion)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:inline&quot;&gt;將函數巨集化&lt;/a&gt; &amp;#8212; (inline funciton)。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:includeguard&quot;&gt;引用防護&lt;/a&gt; &amp;#8212; 避免重複引用某一個引用檔，或者重複定義某結構。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:macroif&quot;&gt;條件編譯&lt;/a&gt; &amp;#8212; #if, #else, #endif, #ifdef, #ifndef, &amp;#8230;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:macrovar&quot;&gt;編譯時期變數&lt;/a&gt; &amp;#8212; &lt;span style=&quot;text-decoration: underline;&quot;&gt;FILE&lt;/span&gt;, &lt;span style=&quot;text-decoration: underline;&quot;&gt;LINE&lt;/span&gt;, &lt;span style=&quot;text-decoration: underline;&quot;&gt;DATE&lt;/span&gt;, &lt;span style=&quot;text-decoration: underline;&quot;&gt;TIME&lt;/span&gt;, &lt;span style=&quot;text-decoration: underline;&quot;&gt;STDC&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:macrofunc&quot;&gt;編譯時期函數&lt;/a&gt; &amp;#8212; #define, #undef, defined(), #error, #line, &amp;#8230;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:pragma&quot;&gt;編譯指示&lt;/a&gt; &amp;#8212; #pragma, _Pragma(), GCC dependency, GCC poison, &amp;#8230;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:stringification&quot;&gt;字串化&lt;/a&gt; &amp;#8212; Stringification, 使用 #symbol 可以將某符號字串化。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 02 Sep 2010 23:44:52 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <ul> <li><a href="http://ccckmit.wikidot.com/cp:macro">巨集處理</a> &#8212; (Macro &amp; Conditional Expansion) <ul> <li><a href="http://ccckmit.wikidot.com/cp:inline">將函數巨集化</a> &#8212; (inline funciton)。</li> <li><a href="http://ccckmit.wikidot.com/cp:includeguard">引用防護</a> &#8212; 避免重複引用某一個引用檔，或者重複定義某結構。</li> <li><a href="http://ccckmit.wikidot.com/cp:macroif">條件編譯</a> &#8212; #if, #else, #endif, #ifdef, #ifndef, &#8230;.</li> <li><a href="http://ccckmit.wikidot.com/cp:macrovar">編譯時期變數</a> &#8212; <span style="text-decoration: underline;">FILE</span>, <span style="text-decoration: underline;">LINE</span>, <span style="text-decoration: underline;">DATE</span>, <span style="text-decoration: underline;">TIME</span>, <span style="text-decoration: underline;">STDC</span>.</li> <li><a href="http://ccckmit.wikidot.com/cp:macrofunc">編譯時期函數</a> &#8212; #define, #undef, defined(), #error, #line, &#8230;</li> <li><a href="http://ccckmit.wikidot.com/cp:pragma">編譯指示</a> &#8212; #pragma, _Pragma(), GCC dependency, GCC poison, &#8230;</li> <li><a href="http://ccckmit.wikidot.com/cp:stringification">字串化</a> &#8212; Stringification, 使用 #symbol 可以將某符號字串化。</li> </ul> </li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:signal</guid>
				<title>Signal</title>
				<link>http://ccckmit.wikidot.com/cp:signal</link>
				<description>

&lt;h1&gt;&lt;span&gt;程式範例&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 31 Aug 2010 02:14:28 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <h1><span>程式範例</span></h1> <div class="code"> <div class="hl-main"> <pre><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">signal.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">stdio.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">windows.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-types">void</span><span class="hl-code"> </span><span class="hl-identifier">sigdump</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">sig</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">catch a signal:%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">sig</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">argc</span><span class="hl-code">, </span><span class="hl-types">void</span><span class="hl-code"> *</span><span class="hl-identifier">argv</span><span class="hl-brackets">[])</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">signal</span><span class="hl-brackets">(</span><span class="hl-identifier">SIGABRT</span><span class="hl-code">, &amp;</span><span class="hl-identifier">sigdump</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// Process abort signal.</span><span class="hl-code"> </span><span class="hl-identifier">signal</span><span class="hl-brackets">(</span><span class="hl-identifier">SIGFPE</span><span class="hl-code">, &amp;</span><span class="hl-identifier">sigdump</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// Erroneous arithmetic operation.</span><span class="hl-code"> </span><span class="hl-identifier">signal</span><span class="hl-brackets">(</span><span class="hl-identifier">SIGILL</span><span class="hl-code">, &amp;</span><span class="hl-identifier">sigdump</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// Illegal instruction.</span><span class="hl-code"> </span><span class="hl-identifier">signal</span><span class="hl-brackets">(</span><span class="hl-identifier">SIGINT</span><span class="hl-code">, &amp;</span><span class="hl-identifier">sigdump</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// Terminal interrupt signal. Ctrl-C</span><span class="hl-code"> </span><span class="hl-identifier">signal</span><span class="hl-brackets">(</span><span class="hl-identifier">SIGSEGV</span><span class="hl-code">, &amp;</span><span class="hl-identifier">sigdump</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// Invalid memory reference.</span><span class="hl-code"> </span><span class="hl-identifier">signal</span><span class="hl-brackets">(</span><span class="hl-identifier">SIGTERM</span><span class="hl-code">, &amp;</span><span class="hl-identifier">sigdump</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// Termination signal.</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">=</span><span class="hl-number">7</span><span class="hl-code">, </span><span class="hl-identifier">b</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-code">, </span><span class="hl-identifier">result</span><span class="hl-code">; </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">strcmp</span><span class="hl-brackets">(</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">FPE</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">==</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">result</span><span class="hl-code"> = </span><span class="hl-identifier">a</span><span class="hl-code">/</span><span class="hl-identifier">b</span><span class="hl-code">; </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">strcmp</span><span class="hl-brackets">(</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">SEGV</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">==</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> * </span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code">*</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-number">10000</span><span class="hl-brackets">)</span><span class="hl-code"> = </span><span class="hl-number">1</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-identifier">Sleep</span><span class="hl-brackets">(</span><span class="hl-number">1000</span><span class="hl-code">*</span><span class="hl-number">10</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-brackets">}</span></pre></div> </div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;gcc signal.c -o signal D:\cp&gt;signal FPE catch a signal:8 D:\cp&gt;signal SEGV catch a signal:11 D:\cp&gt;signal catch a signal:11 D:\cp&gt;signal X // 執行後請在 10 秒鐘內按下 Ctrl-C，就會出現 catch a signal:2 的訊息 catch a signal:2</code></pre></div> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>=&gt; 這個案例不好，第一個因為 &lt;windows.h&gt;，另外沒有闡述 UNIX signal 和 Windows 對於 POSIX 的支援狀況</code></pre></div> <h1><span>參考文獻</span></h1> <ol> <li>C语言编程技巧-signal(信号), 2008-12-08 来源：网络 &#8212; <a href="http://www.uml.org.cn/c++/200812083.asp">http://www.uml.org.cn/c++/200812083.asp</a></li> </ol> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:jump</guid>
				<title>高等 C 語言 -- setjump 與 longjump</title>
				<link>http://ccckmit.wikidot.com/cp:jump</link>
				<description>

&lt;h1&gt;&lt;span&gt;程式範例： setjump 與 longjump&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 30 Aug 2010 08:31:56 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <h1><span>程式範例： setjump 與 longjump</span></h1> <div class="code"> <div class="hl-main"> <pre><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">stdio.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">setjmp.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-identifier">jmp_buf</span><span class="hl-code"> </span><span class="hl-identifier">jumper</span><span class="hl-code">; </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">div</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">, </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">b</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">b</span><span class="hl-code"> == </span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-comment">// can't divide by 0</span><span class="hl-code"> </span><span class="hl-identifier">longjmp</span><span class="hl-brackets">(</span><span class="hl-identifier">jumper</span><span class="hl-code">, -</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code"> / </span><span class="hl-identifier">b</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">argc</span><span class="hl-code">, </span><span class="hl-types">char</span><span class="hl-code"> *</span><span class="hl-identifier">argv</span><span class="hl-brackets">[])</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">jstatus</span><span class="hl-code"> = </span><span class="hl-identifier">setjmp</span><span class="hl-brackets">(</span><span class="hl-identifier">jumper</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">jstatus</span><span class="hl-code"> == </span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code"> = </span><span class="hl-identifier">atoi</span><span class="hl-brackets">(</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">])</span><span class="hl-code">; </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">b</span><span class="hl-code"> = </span><span class="hl-identifier">atoi</span><span class="hl-brackets">(</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">2</span><span class="hl-brackets">])</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">%d/%d</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">a</span><span class="hl-code">, </span><span class="hl-identifier">b</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">result</span><span class="hl-code"> = </span><span class="hl-identifier">div</span><span class="hl-brackets">(</span><span class="hl-identifier">a</span><span class="hl-code">, </span><span class="hl-identifier">b</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">result</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">jstatus</span><span class="hl-code"> == -</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string"> --&gt; Error:divide by zero</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">Unhandled Error Case</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-brackets">}</span></pre></div> </div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;gcc jump.c -o jump D:\cp&gt;jump 7 2 7/2=3 D:\cp&gt;jump 7 0 7/0 --&gt; Error:divide by zero</code></pre></div> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>=&gt; 請提及 C 語言作例外處理的重要性，以及如何用 setjump/longjump 實做 user-level thread 和 coroutine 可參見拙作: http://blog.linux.org.tw/~jserv/archives/001848.html</code></pre></div> <h1><span>參考文獻</span></h1> <ol> <li>Java2s (C / ANSI-C) » setjmp.h » longjmp, <a href="http://www.java2s.com/Code/C/setjmp.h/longjmplongjump.htm">http://www.java2s.com/Code/C/setjmp.h/longjmplongjump.htm</a></li> <li>Exception Handling in C without C++ &#8212; Clean error handling without overhead, by Tom Schotland and Peter Petersenhttp://www.on-time.com/ddj0011.htm</li> <li><a href="http://se.csai.cn/ExpertEyes/No152.htm">第16集 C语言中一种更优雅的异常处理机制</a>, 作者：王胜祥　来源：希赛网　<a href="http://www.csai.cn%E3%80%802005%E5%B9%B45%E6%9C%8819">http://www.csai.cn　2005年5月19</a>日</li> <li><a href="http://se.csai.cn/ExpertEyes/No153.htm">第17集 全面了解setjmp与longjmp的使用</a>, 作者：王胜祥　来源：希赛网　<a href="http://www.csai.cn%E3%80%802005%E5%B9%B45%E6%9C%8821">http://www.csai.cn　2005年5月21</a>日</li> </ol> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:strlib</guid>
				<title>C 語言的字串函式庫</title>
				<link>http://ccckmit.wikidot.com/cp:strlib</link>
				<description>

&lt;h1&gt;&lt;span&gt;K&amp;amp;R 對字串的設計理念&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 29 Aug 2010 09:51:04 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <h1><span>K&amp;R 對字串的設計理念</span></h1> <p>既然如此，那麼為何 C 語言要設計出像 strcpy(), strcat(), strtok(), strcmp(), strlen() 這樣的字串函式庫，而不直接使用像上述的動態字串函式庫取代就好了呢？關於這個問題，我們必須回到當初 K &amp; R 兩人設計 C 語言的初始環境，才能看出其原因。</p> <p>K &amp; R 設計 C 語言時，還沒有物件導向的概念，因此不太可能設計出像範例五這樣具有物件導向概念的字串函式庫。當時電腦的記憶體極為有限，而且 K&amp;R 一心只想設計出 UNIX 作業系統，因此才設計出像 strcpy()、strcmp() 這樣的函數，可以同時支援字串陣列與指標。</p> <p>K &amp; R 所設計的字串函式庫可不是用來支援應用程式的，而是用在設計作業系統上的，特別是在基本文字檔的處理上。當時的環境不像我們現在這麼奢侈，有好幾 GB 的記憶體可以用，幾乎可以將任何文字檔都全部讀到記憶體中再進行處理，而是必須一個字一個字的讀，或者是一行一行的讀，因此這些靜態的字串函式庫就已經相當夠用了。</p> <p>這些字串函式庫所處理的對象，就是從檔案中讀出來，不超過一行長度的字串，就當時的環境，我們可以假設檔案中任一行的長度不會超過 127 個字元，因此您只要宣告像 char line[128] 這樣的變數，就足以處理任何的文字檔了。</p> <p>理解了這個背景，相信讀者應該能夠感覺到為何 K&amp;R 沒有發展出動態字串函式庫了吧？</p> <p>但是在 C 語言漫長的發展過程中，為何動態字串函式庫沒有被納入標準函式庫中，這或許才是真正的問題，也是學習者之所以誤用 C 語言的原因之所在，關於這點，或許牽涉到了太多的歷史，筆者也無從考證起了。</p> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>=&gt; 沒有「C 語言的字串函式庫」的說法 整體是 C Library: http://www.tutorialspoint.com/c_standard_library/string_h.htm ==&gt; &quot;但是在 C 語言漫長的發展過程中，為何動態字串函式庫沒有被納入標準函式庫中，&quot; 這句值得商榷</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:introduction</guid>
				<title>高等 C 語言 -- 簡介</title>
				<link>http://ccckmit.wikidot.com/cp:introduction</link>
				<description>

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:dir&quot;&gt;目錄&lt;/a&gt; &amp;#8212; (Directory)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:introduction&quot;&gt;簡介&lt;/a&gt; &amp;#8212; (Introduction)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:preface&quot;&gt;前言&lt;/a&gt; &amp;#8212; 寫給專業人士看的 C 語言的書，初學者請勿閱讀。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:advancec&quot;&gt;高等 C 語言&lt;/a&gt; &amp;#8212; C 語言是許多作業系統與嵌入式系統的共同語言，其威力也正在系統程式上。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:history&quot;&gt;C 語言的歷史&lt;/a&gt; &amp;#8212; Ken Thompson &amp;amp; Dennis M. Ritchie 發明的 C 語言，至今已超過 40 年。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 02 Sep 2010 23:28:19 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <ul> <li><a href="http://ccckmit.wikidot.com/cp:dir">目錄</a> &#8212; (Directory)</li> <li><a href="http://ccckmit.wikidot.com/cp:introduction">簡介</a> &#8212; (Introduction) <ul> <li><a href="http://ccckmit.wikidot.com/cp:preface">前言</a> &#8212; 寫給專業人士看的 C 語言的書，初學者請勿閱讀。</li> <li><a href="http://ccckmit.wikidot.com/cp:advancec">高等 C 語言</a> &#8212; C 語言是許多作業系統與嵌入式系統的共同語言，其威力也正在系統程式上。</li> <li><a href="http://ccckmit.wikidot.com/cp:history">C 語言的歷史</a> &#8212; Ken Thompson &amp; Dennis M. Ritchie 發明的 C 語言，至今已超過 40 年。</li> </ul> </li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:preface</guid>
				<title>免費電子書：高等 C 語言 -- 前言</title>
				<link>http://ccckmit.wikidot.com/cp:preface</link>
				<description>

&lt;p&gt;當我還是一個大學生的時候，總覺得 C 語言就是這樣了。但是在 10 年後我進入職場時，才發現原來我並不太認識這個語言。產業界所使用的 C 語言有許多是大學所沒有教授過的，像是 #ifdef、make、GNU 工具等等。又過了 10 年，當我研究嵌入式系統時，這個感覺又出現了，我仍然不太認識 C 語言，嵌入式系統中所使用的「記憶體映射輸出入、volatile、組合語言連接、Linker Script」等，又讓我耳目一新，我再度重新認識了 C 語言一次。然後，當我研讀 Linux 核心的程式碼時，看到 Torvalds 所使用的「鏈結串列、行程切換技巧」等，又再度讓我大為驚訝，C 語言竟然還可以這樣用。然後，當我開始研究 Google Android 手機平台的架構時，又看到了如何用 C 語言架構出網路、視窗、遊戲、瀏覽器等架構，於是我必須再度學習一次 C 語言。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 28 Aug 2010 22:54:25 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>當我還是一個大學生的時候，總覺得 C 語言就是這樣了。但是在 10 年後我進入職場時，才發現原來我並不太認識這個語言。產業界所使用的 C 語言有許多是大學所沒有教授過的，像是 #ifdef、make、GNU 工具等等。又過了 10 年，當我研究嵌入式系統時，這個感覺又出現了，我仍然不太認識 C 語言，嵌入式系統中所使用的「記憶體映射輸出入、volatile、組合語言連接、Linker Script」等，又讓我耳目一新，我再度重新認識了 C 語言一次。然後，當我研讀 Linux 核心的程式碼時，看到 Torvalds 所使用的「鏈結串列、行程切換技巧」等，又再度讓我大為驚訝，C 語言竟然還可以這樣用。然後，當我開始研究 Google Android 手機平台的架構時，又看到了如何用 C 語言架構出網路、視窗、遊戲、瀏覽器等架構，於是我必須再度學習一次 C 語言。</p> <p>當我翻閱坊間的書籍時，不禁如此想著，如果有人能直接告訴我這些 C 語言的學習歷程，那應該有多好。難道，我們真的必需花上數十年的時間去學習 C 語言，才能得到這些知識嗎？這些知識在初學者的眼中，看來簡直像是「奇技淫巧」。然而這些「奇技淫巧」，正是 C 語言為何如此強大的原因，我希望能透過這本書，告訴各位這些「奇技淫巧」，讓各位讀者不需要再像我一樣，花上二十年功夫，才能學會這些技術。</p> <p>在我的眼中，C 語言就像一把鋒利的雙面刃，初出茅廬的人往往功力不夠深厚，反而將這個神兵利器往自己身上砍，因而身受重傷。但是在專家的手中，C 語言卻具有無比的威力，這種神兵利器具有「十年磨一劍、十步殺一人」的驚人力量。筆者希望能透過這本書，讓讀者能夠充分發揮 C 語言的力量，快速的掌握這個難以駕馭的神兵利器。</p> <div style="text-align: right;"> <p>陳鍾誠 於金門大學 2010 年 8 月 29 日</p> </div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:unicode</guid>
				<title>C 語言中的寬字串 -- 包含 Unicode</title>
				<link>http://ccckmit.wikidot.com/cp:unicode</link>
				<description>

&lt;p&gt;要在 C 語言中使用 Unicode 字串，假如您用的是 gcc 編譯器或 Linux，您可以使用寬字元 wchar_t 這個形態，以取代 char，然後用對應的函數取代原本的字串函數，以下是常見字串函數的寬字元版對應表。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 30 Aug 2010 06:45:49 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>要在 C 語言中使用 Unicode 字串，假如您用的是 gcc 編譯器或 Linux，您可以使用寬字元 wchar_t 這個形態，以取代 char，然後用對應的函數取代原本的字串函數，以下是常見字串函數的寬字元版對應表。</p> <table class="wiki-content-table"> <tr> <th>窄字元</th> <th>寬字元</th> <th>說明</th> </tr> <tr> <td>strlen()</td> <td>wcslen()</td> <td>字串長度</td> </tr> <tr> <td>strcat()</td> <td>wcscat()</td> <td>字串連接</td> </tr> <tr> <td>strcmp()</td> <td>wcscmp()</td> <td>字串比較</td> </tr> <tr> <td>strcoll()</td> <td>wcscoll()</td> <td>字串比較 (不分大小寫)</td> </tr> <tr> <td>strcpy()</td> <td>wcscpy()</td> <td>字串複製</td> </tr> <tr> <td>strchr()</td> <td>wcschr()</td> <td>尋找字元</td> </tr> <tr> <td>strstr()</td> <td>wcswcs()</td> <td>尋找字串</td> </tr> <tr> <td>strtok()</td> <td>wcstok()</td> <td>字串分割</td> </tr> <tr> <td>strcspn()</td> <td>wcscspn()</td> <td>傳回字串中第一個符合字元集的位置</td> </tr> <tr> <td>strpbrk()</td> <td>wcspbrk()</td> <td>傳回字串中第一個符合字元集的指標</td> </tr> <tr> <td>strxfrm()</td> <td>wcsxfrm()</td> <td>根據區域設定 locale() 轉換字元集</td> </tr> </table> <p>簡而言之，就是將原本 strXXX() 函數，轉換成 wcsXXX() 函數，然後照著原本的方法使用，只是對象從 char* 改為 wchar_t * 即可，請看下列範例。</p> <h1><span>程式範例：Unicode 寬字串處理函數</span></h1> <p>檔案：unicode.c</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">stdio.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">locale.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">(</span><span class="hl-types">void</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-code">!</span><span class="hl-identifier">setlocale</span><span class="hl-brackets">(</span><span class="hl-identifier">LC_CTYPE</span><span class="hl-code">, </span><span class="hl-quotes">&quot;&quot;</span><span class="hl-brackets">))</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">fprintf</span><span class="hl-brackets">(</span><span class="hl-identifier">stderr</span><span class="hl-code">, </span><span class="hl-quotes">&quot;</span><span class="hl-string">Error:Please check LANG, LC_CTYPE, LC_ALL.</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">1</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">wchar_t</span><span class="hl-code"> *</span><span class="hl-identifier">str1</span><span class="hl-code">=</span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">Hi!你好</span><span class="hl-quotes">&quot;</span><span class="hl-code">; </span><span class="hl-comment">// 輸出結果 (範例)</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">str1=%ls</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">str1</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// str1=Hi!你好</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcslen(str1)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">wcslen</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcslen(str1)=5</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcschr(str1,%lc)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-code">'好', </span><span class="hl-identifier">wcschr</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-code">'好'</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcschr(str1,好)=4206648</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcswcs(str1,%ls)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">你好</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">wcsstr</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">你好</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcswcs(str1,你好)=4206646</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcsspn(str1,aeiou)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">wcsspn</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">aeiou</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcsspn(str1,aeiou)=0</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcsspn(str1,EFGH)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">wcsspn</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">EFGH</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcsspn(str1,EFGH)=1</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">address(str1)=%p</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">str1</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// address(str1)=00403030</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcssbrk(str1,aeiou)=%p</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">wcspbrk</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">aeiou</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcssbrk(str1,aeiou)=00403032</span><span class="hl-code"> </span><span class="hl-types">wchar_t</span><span class="hl-code"> </span><span class="hl-identifier">str2</span><span class="hl-brackets">[</span><span class="hl-number">20</span><span class="hl-brackets">]</span><span class="hl-code">; </span><span class="hl-identifier">wcscpy</span><span class="hl-brackets">(</span><span class="hl-identifier">str2</span><span class="hl-code">, </span><span class="hl-identifier">str1</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">str2=%ls</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">str2</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// str2=Hi!你好</span><span class="hl-code"> </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">wcscmp(str1,str2)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">wcscmp</span><span class="hl-brackets">(</span><span class="hl-identifier">str1</span><span class="hl-code">, </span><span class="hl-identifier">str2</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-comment">// wcscmp(str1,str2)=0</span><span class="hl-code"> </span><span class="hl-identifier">wcscat</span><span class="hl-brackets">(</span><span class="hl-identifier">str2</span><span class="hl-code">, </span><span class="hl-identifier">L</span><span class="hl-quotes">&quot;</span><span class="hl-string">,我是John</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">str2=%ls</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">str2</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-comment">// str2=Hi!你好,我是John</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code">}</span></pre></div> </div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;gcc unicode.c -o unicode D:\cp&gt;unicode str1=Hi!你好 wcslen(str1)=5 wcschr(str1,好)=4206648 wcswcs(str1,你好)=4206646 wcsspn(str1,aeiou)=0 wcsspn(str1,EFGH)=1 address(str1)=00403030 wcssbrk(str1,aeiou)=00403032 str2=Hi!你好 wcscmp(str1,str2)=0 str2=Hi!你好,我是John</code></pre></div> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>&quot;&quot;&quot; 寬字串函數 — 寬字串的處理，在 C 語言中，通常寬字串指的是 Unicode (但不限定於 Unicode) &quot;&quot;&quot; wide-character 翻譯為「寬字串」，我覺得有本質的問題。 以下摘錄 CLDP: http://linux.org.tw/CLDP/OLD/doc/i18n-introduction.html &quot;wcs&quot; 是 &quot;wide-chararater string&quot; 的縮寫，而 &quot;mbs&quot; 是 &quot;multi-byte string&quot; 的縮寫，二者分別代表字串的表現方式。所謂的 multi-byte 是指數個 char 組成 一個字 (如全形字或中文字是由兩個 char 組成)，而 wide-char 是指一個 wchar_t type 就是一個字, 而 sizeof(wchar_t) 的大小與系統有關，一般而言是 4 bytes。 一般我們可以直接看、輸出輸入等都是 multi-byte, 如: char *str = &quot;這是一個句子: abcd&quot;; 但我們會建議在程式內部，用 mbstowcs() 將它轉成 wchar_t 來統一處理，這個 轉換其實是根據 locale 中的 LC_CTYPE 的機制，它定義了 multi-byte 與 wide- char 值二者間的對應關係。做這樣轉換的好處是，您不用擔心全形、半形的問題， 因為一個 wchar_t 矩陣元就是一個字。 wchar_t 有一組與 string.h 中相對應的字串處理函式，就定義在 wchar.h 中，讓我們可以如同處理 (char *) 那樣 地處理 (wchar_t *), 其部分的對應關係如下，其他的可以直接看 wchar.h 的內容: wcscpy() &lt;====&gt; strcpy() wcsncpy() &lt;====&gt; strncpy() wcslen() &lt;====&gt; strlen() wcsdup() &lt;====&gt; strdup() wcscmp() &lt;====&gt; strcmp() wcsncmp() &lt;====&gt; strncmp() ........................................ 由於 mbs 碼與 wcs 碼的對應關係是由該 locale 的 LC_CTYPE 來決定的，也就是不 同的 locale 寫法其對應關係可能會不一樣。就我們的 glibc2, zh_TW.Big5 locale 而言，由 mbs 轉成的 wcs 即為 unicode (有關 unicode 的資訊可以在 http://www.unicode.org/ 中找到)，但不能保證在其他的系統或環境下也是如此。 故最保險的做法，是將字串儲存成 multi-byte, 然後在 run-time 時才用 mbstowcs() 轉成 wide-char 來運作。 ==&gt; 可以看出重點不在於字串 (C 語言的 string 只是一個寫法，本質上仍是連續記憶體) 的「寬度」，而是 character 與 character set 的「範圍寬度」 ==&gt; 建議保留原文 &quot;wide character&quot;，真要翻譯的話，可寫「擴充字元」</code></pre></div> <h1><span>後記</span></h1> <p>寬字串的處理函數有很多，並不限於上列的函數，幾乎所有具有字串的標準 C 函數都有寬版，關於更多的寬版函數請參考下列網頁。</p> <blockquote> <p><a href="http://www.java2s.com/Tutorial/C/0300__Wide-Character-String/WideCharacterFunctions.htm">http://www.java2s.com/Tutorial/C/0300__Wide-Character-String/WideCharacterFunctions.htm</a></p> </blockquote> <h1><span>參考文獻</span></h1> <ol> <li>简明手册:使你的C/C++代码支持Unicode &#8212; <a href="http://www.i18nguy.com/unicode/c-unicode.zh-CN.html">http://www.i18nguy.com/unicode/c-unicode.zh-CN.html</a></li> <li>Programming with wide characters By Leslie P. Polzer on February 11, 2006 (8:00:00 AM) &#8212; <a href="http://www.linux.com/archive/feature/51836">http://www.linux.com/archive/feature/51836</a></li> <li><a href="http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf">The current Standard (C99 with Technical corrigenda TC1, TC2, and TC3 included) (PDF)</a>, (3.61&#160;MB). Pages 397, 398 and 400.</li> </ol> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:file</guid>
				<title>高等 C 語言 -- 檔案 (File)</title>
				<link>http://ccckmit.wikidot.com/cp:file</link>
				<description>

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:file&quot;&gt;檔案&lt;/a&gt; &amp;#8212; (File)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:filebuffer&quot;&gt;檔案緩衝區&lt;/a&gt; &amp;#8212; 如何指定緩衝區大小與位址。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:tempfile&quot;&gt;臨時暫存檔&lt;/a&gt; &amp;#8212; 如何建立暫存檔案。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:ferror&quot;&gt;檔案錯誤&lt;/a&gt; &amp;#8212; 如何處理檔案的錯誤狀況。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:dirapi&quot;&gt;目錄管理&lt;/a&gt; &amp;#8212; 建立目錄、切換路徑、取得目前路徑。&lt;/li&gt;
&lt;li&gt;來自 jserv 的建議 &amp;#8212; 這整章節沒有把 C 語言的溫床 &amp;#8212; UNIX 背後的思維闡述好，希望能多談 standard I/O file，descriptors 的概念，以及 C standard library 提供哪些包裝，這樣探討 buffering 才有意思。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 02 Sep 2010 23:56:09 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <ul> <li><a href="http://ccckmit.wikidot.com/cp:file">檔案</a> &#8212; (File) <ul> <li><a href="http://ccckmit.wikidot.com/cp:filebuffer">檔案緩衝區</a> &#8212; 如何指定緩衝區大小與位址。</li> <li><a href="http://ccckmit.wikidot.com/cp:tempfile">臨時暫存檔</a> &#8212; 如何建立暫存檔案。</li> <li><a href="http://ccckmit.wikidot.com/cp:ferror">檔案錯誤</a> &#8212; 如何處理檔案的錯誤狀況。</li> <li><a href="http://ccckmit.wikidot.com/cp:dirapi">目錄管理</a> &#8212; 建立目錄、切換路徑、取得目前路徑。</li> <li>來自 jserv 的建議 &#8212; 這整章節沒有把 C 語言的溫床 &#8212; UNIX 背後的思維闡述好，希望能多談 standard I/O file，descriptors 的概念，以及 C standard library 提供哪些包裝，這樣探討 buffering 才有意思。</li> </ul> </li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:memcheck</guid>
				<title>C 語言的記憶體漏洞檢查</title>
				<link>http://ccckmit.wikidot.com/cp:memcheck</link>
				<description>

&lt;p&gt;在 C 語言中，如果有人用 malloc() 等函數分配了記憶體，卻忘了用 free() 等函數進行釋放，那就會產生記憶體漏洞。要解決這個問題，必須遵循幾個原則，第一個是程式紀律的問題，例如一個很好的習慣是，採用物件導向的寫法，然後在物件的建構函數中分配記憶體，並在解構函數中，釋放該物件所分配的所有記憶體。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 07 Sep 2010 06:39:48 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>在 C 語言中，如果有人用 malloc() 等函數分配了記憶體，卻忘了用 free() 等函數進行釋放，那就會產生記憶體漏洞。要解決這個問題，必須遵循幾個原則，第一個是程式紀律的問題，例如一個很好的習慣是，採用物件導向的寫法，然後在物件的建構函數中分配記憶體，並在解構函數中，釋放該物件所分配的所有記憶體。</p> <p>第二個原則是程式測試的問題，您可以使用記憶體檢查函數，進行記憶體漏洞檢查，像是 Linux 當中就有 mtrace 這樣的套件可以使用，您只要引用 &lt;mcheck.h&gt; 這個標頭檔即可，以下是一個使用 mtrace 進行記憶體檢查的範例。</p> <h1><span>mtrace 的使用 (Linux)</span></h1> <p>檔案：leak.c</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">stdlib.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">mcheck.h</span><span class="hl-quotes">&gt;</span><span class="hl-prepro"> // mtrace 的標頭檔</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> *</span><span class="hl-identifier">a</span><span class="hl-code">; </span><span class="hl-identifier">mtrace</span><span class="hl-brackets">()</span><span class="hl-code">; </span><span class="hl-comment">// 啟用 mtrace</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code"> = </span><span class="hl-identifier">malloc</span><span class="hl-brackets">(</span><span class="hl-reserved">sizeof</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-brackets">))</span><span class="hl-code">; 分配記憶體 *</span><span class="hl-identifier">a</span><span class="hl-code"> = </span><span class="hl-number">7</span><span class="hl-code">; </span><span class="hl-comment">// 忘了釋放</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-identifier">EXIT_SUCCESS</span><span class="hl-code">; </span><span class="hl-brackets">}</span></pre></div> </div> <p>執行方法：</p> <div class="code"> <pre><code>setenv MALLOC_TRACE /home/karthik/temp/trace.txt // 設定 mtrace 的環境變數 MALLOC_TRACE $ gcc -g -Wall -ansi -pedantic leak.c -o leak.o // 編譯 $ ./leak // 執行 $ mtrace leak.o /home/karthik/temp/trace.txt // 追蹤記憶體漏洞 Memory not freed: ----------------- Address Size Caller 0x08049910 0x4 at /home/karthik/tips/leak.c:9 // 發現在 leak.c 的第 9 行，有 4 byte 沒釋放</code></pre></div> <h1><span>簡單的檢查方法</span></h1> <p>假如您沒有辦法使用像 mtrace 這種由系統所提供的記憶體檢查方法，也可以自己製作一個很簡單的版本。為了示範這種作法，我們設計了 new(), del() 與 mcheck() 等三個巨集，以示範這種簡單的漏洞檢查法。</p> <p>程式範例：mcheck.c</p> <div class="code"> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; int newSize = 0; int delSize = 0; #define new(TYPE, n) malloc(n*sizeof(TYPE)); newSize+=n*sizeof(TYPE) #define del(ptr, TYPE, n) free(ptr); delSize+=n*sizeof(TYPE) #define mcheck() printf(&quot;Memory:newSize=%d delSize=%d leakSize=%d\n&quot;, \ newSize, delSize, newSize-delSize); int main() { int *ip = new(int, 10); char *cp = new(char, 5); del(ip, int, 10); mcheck(); }</code></pre></div> <p>執行結果：</p> <div class="code"> <pre><code>D:\cp&gt;gcc mcheck.c -o mcheck D:\cp&gt;mcheck Memory:newSize=45 delSize=40 leakSize=5</code></pre></div> <p>有了這樣的函數，您就可以知道是否有記憶體漏洞的存在了，雖然不像 mtrace 那樣可以直接告訴您產生漏洞的程式位置，但至少可以讓您檢查是否存在記憶體漏洞。</p> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>mtrace 是 glibc (GNU C Library) 提供的記憶體分析工具，但 Linux (kernel) 不見得搭配 glibc，實際可用 uClibc, musl-libc, bionic libc, diet libc 等等。後幾者就沒有 mtrace 這樣方便的機制了。</code></pre></div> <h1><span>參考文獻</span></h1> <ol> <li>Identifying Memory Leaks in Linux for C++ Programs &#8212; <a href="http://www.devx.com/tips/Tip/20915">http://www.devx.com/tips/Tip/20915</a></li> </ol> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:environment</guid>
				<title>C 語言的執行環境</title>
				<link>http://ccckmit.wikidot.com/cp:environment</link>
				<description>

&lt;p&gt;要理解 C 語言的設計理念，首先要能理解Ｃ語言程式在電腦中的執行環境。一個 C 語言程式在電腦中的執行環境，大致包含五個區段，分別是程式段、資料段、堆積段、堆疊段等。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 29 Aug 2010 07:25:22 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>要理解 C 語言的設計理念，首先要能理解Ｃ語言程式在電腦中的執行環境。一個 C 語言程式在電腦中的執行環境，大致包含五個區段，分別是程式段、資料段、堆積段、堆疊段等。</p> <p>程式段 (.text) 主要存放程式的機器碼，資料段 (.data) 則是存放全域變數的資料，BSS 段 (.bss) 存放的是未初始化的全域變數，堆積段 (.heap) 則是在程式使用 malloc 進行記憶體分配時，可以分配的動態記憶空間，而堆疊段 (.stack) 則存放「參數、函數返回點、區域變數、框架指標」等資料。圖一顯示了 C 語言的執行環境，左半部的 (a) 是這五個區段的初始狀況，而右半部的 (b) 則是在程式執行中，堆疊與堆積已經進行某些分配後的狀況。</p> <div class="image-container aligncenter"><a href="http://ccckmit.wdfiles.com/local--files/cp:environment/CEnvironment.jpg"><img src="http://ccckmit.wdfiles.com/local--resized-images/cp:environment/CEnvironment.jpg/medium.jpg" alt="CEnvironment.jpg" class="image" /></a></div> <p style="text-align: center;">圖一、C 語言的執行環境</p> <p>請讀者將焦點先放在堆疊與堆積這兩段上，C 語言中的「參數、函數返回點、區域變數、框架指標」等資料，被儲存在堆疊段中，這個區段會隨著函數呼叫的層次數目而增長或縮短。如果這個區段成長過頭，導致堆疊段覆蓋到堆積段的空間時，就被稱為堆疊溢位 (Stack Overflow)，這種情況通常是因為程式進行遞回呼叫，卻又沒有正確判斷終止條件，導致遞迴層數過多所產生的錯誤情況。</p> <p>讓我們將焦點轉到堆積段中，假如我們用 malloc() 函數分配記憶體空間，則 malloc() 函數會從堆積段 (heap) 中找到一個夠大的區塊，分配給 malloc() 函數傳回。然後，當我們使用 free() 函數釋放記憶體空間時，則原先分配的區塊會歸還給堆積系統，此時通常會在堆積的記憶空間中留下一個空洞。在程式的執行過程當中，malloc() 與 free() 會交錯執行，因而導致整個堆積區塊開始產生許多空洞，這將會造成記憶體管理的負擔，假如堆積系統無法找到足夠大的堆積區塊時，就會造成記憶體分配失敗的情況，因而導致程式無法繼續執行。</p> <p>對於現今的電腦而言，由於記憶體的容量龐大，而且通常有分頁機制可以幫助作業系統進行記憶體管理，因此堆積分配失敗的情況較為少見，但是對於早期的電腦，或者是嵌入式系統而言，堆積的分配就是一個相當難以處理的問題。</p> <p>在 C 語言的函式庫設計上，通常會盡量避免使用 malloc() 等函數分配堆積空間，因為這會造成記憶體管理的困擾，也會讓程式的執行效率難以預料。因此，您可以看到 C 語言的字串函數，通常會盡可能避免使用 malloc() 函數分配空間。</p> <h1><span>一個誤用的 C 語言字串範例</span></h1> <p>在 Java 這樣的語言當中，字串的長度是可以改變的，您可能會使用下列程式，很自由的讓字串大小增大，Java 會自動的幫您分配字串所需要的記憶空間，而不會產生太大的問題。</p> <p>範例一、字串連接的 Java 程式</p> <div class="code"> <pre><code>String s = &quot;&quot;; for (i=0; i&lt;100; i++) s = s + token[i];</code></pre></div> <p>但是在 C 語言當中，您就會遇到一個困擾，假如我要撰寫一個類似的程式，那麼字串 s 的長度應該要設定為多長呢？請看下列範例。</p> <p>範例二、字串連接的 C 程式</p> <div class="code"> <pre><code>char s[1000]; for (i=0; i&lt;100; i++) strcat(s, token[i]);</code></pre></div> <p>您可能會懷疑，長度 1000 到底夠不夠呢？假如 token 陣列中的字串長度平均超過 10 個字，那麼 s 的長度 1000 就會不夠了。這樣看來，Java 的字串函式庫設計似乎比 C 語言要好得多了，不是嗎？</p> <p>如果您不夠理解 C 語言，就很可能會寫出像範例二這樣的程式，但是這對 C 語言來說其實是一種誤用，誤用的原因是：「想要用靜態的字串處理動態的問題」。</p> <p>假如您真的必需撰寫像範例二這樣的程式，那麼應該自行設計一個動態的字串函式庫，或者採用某個現成的動態字串函式庫，而不是直接用 C 語言內建的標準函數。但是 C 語言的初學者往往沒有這樣一個函式庫，因而寫出像範例二這樣的程式。</p> <p>程度稍好的資訊系學生，可能理解到這個問題不能採用靜態的解決方式，因此使用 malloc() 函數進行記憶體分配，以解決這個令人困擾的問題，於是就寫出了下列的程式碼。</p> <p>範例三、字串連接的 C 程式 (malloc 版)</p> <div class="code"> <pre><code>char *s = malloc(1); s[0] = '\0'; for (i=0; i&lt;100; i++) { char *t = malloc(strlen(s)+strlen(token[i])+1); sprintf(t, &quot;%s%s&quot;, s, token[i]); free(s); s = t; }</code></pre></div> <p>但是這樣撰寫 C 語言，仍然是初學者會犯的錯誤之ㄧ，這種用法完全誤用了 C 語言的能力，造成了很多次的 malloc() 分配，卻又很沒效率的處理字串長度的成長問題。</p> <p>歸根究底，這個問題是由於 C 語言沒有提供一個標準的動態字串而造成的，如果您真的需要一個這樣的程式，那麼就應該採用一個支援動態字串的函式庫，然後將程式改寫如下。</p> <p>範例四、字串連接的 C 程式 (動態字串版)</p> <div class="code"> <pre><code>Str *s = StrNew(); for (i=0; i&lt;100; i++) { StrAppend(s, token[i]); }</code></pre></div> <p>這樣範例四的 C 語言程式，其實就與範例一的 Java 程式，看來相差不大了，最大的差別是 C 語言沒有支援物件的概念而已。</p> <h1><span>動態字串</span></h1> <p>要能撰寫像範例四這樣的一個程式，動態字串函式庫至少要能支援 StrNew() 與 StrAppend() 這兩個函數，那麼我們應該怎麼做呢？其實，要自己打造這樣一個程式相當容易，筆者可以馬上撰寫一個，如範例五所示。</p> <p>範例五：實作動態字串函式庫</p> <div class="code"> <pre><code>typedef struct Str { int len, size; char *s; }; Str *StrNew(); void StrAppend(Str *str, char *s); Str *StrNew() { Str *str = malloc(sizeof(Str)); str-&gt;s = malloc(1); str-&gt;s[0] = '\0'; str-&gt;len = 0; str-&gt;size = 1; } void StrAppend(Str *str, char *s) { int newLen = str-&gt;len + strlen(s); if (newLen+1 &gt; str-&gt;size) { int newSize = max(str-&gt;size*2, newLen+1); char *t = malloc(newSize); sprintf(t, &quot;%s%s&quot;, str-&gt;s, s); free(str-&gt;s); str-&gt;s = t; str-&gt;len = newLen; str-&gt;size = newSize; } else { strcat(&amp;str-&gt;s[str-&gt;len], s); str-&gt;len += strlen(s); } }</code></pre></div> <p>只要有了這樣一個函式庫，那麼我們就不需要為了 C 語言缺乏動態字串而困擾了，也就不需要每次都寫出像範例二或範例三這樣難看且沒有效率的程式了，而是直接寫出像範例四這樣乾淨，簡潔的函式庫了。</p> <h1><span>C 語言標準字串函式庫的設計理念</span></h1> <p>既然如此，那麼為何 C 語言要設計出像 strcpy(), strcat(), strtok() 這樣的字串函式庫，而不直接使用像上述的動態字串函式庫取代就好了呢？關於這個問題，我們必須回到當初 K &amp; R 兩人設計 C 語言的初始環境，才能看出其原因。</p> <p>K &amp; R 設計 C 語言時，還沒有物件導向的概念，因此不太可能設計出像範例五這樣具有物件導向概念的字串函式庫。當時電腦的記憶體極為有限，而且 K&amp;R 一心只想設計出 UNIX 作業系統，因此像 strcpy()、strcat()、strtok() 這樣的函數，可以同時支援字串陣列與指標，因而發展出這樣一套 C 語言函式庫。</p> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>內文提到: &quot;&quot;&quot; K &amp; R 設計 C 語言時，還沒有物件導向的概念，因此不太可能設計出像範例五這樣具有物件導向概念的字串函式庫。當時電腦的記憶體極為有限，而且 K&amp;R 一心只想設計出 UNIX 作業系統，因此像 strcpy()、strcat()、strtok() 這樣的函數，可以同時支援字串陣列與指標，因而發展出這樣一套 C 語言函式庫。 &quot;&quot;&quot; ==&gt; 這說法不正確。事實上，我們在 UNIX 在 1974 年的經典論文，不時可見 &quot;object&quot; 字樣，甚至檔案系統的設計本來就有 OOP 風格。合理的說法是，C 語言的設計者將記憶體管理交給程式開發者去負責，UNIX 和 C 語言一樣的原則是，充分相信程式開發者，特別在記憶體管理的議題上。</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:cobject</guid>
				<title>以 C 語言撰寫物件導向程式</title>
				<link>http://ccckmit.wikidot.com/cp:cobject</link>
				<description>

&lt;p&gt;C 語言雖然不是一種物件導向的語言，但是由於具有函數指標 (function pointer) 與結構 (struct)，因此可以讓我們模擬出類似物件導向的語法。在本章中，我們將說明如何用 C 語言設計物件導向的程式。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 02 Sep 2010 00:39:05 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>C 語言雖然不是一種物件導向的語言，但是由於具有函數指標 (function pointer) 與結構 (struct)，因此可以讓我們模擬出類似物件導向的語法。在本章中，我們將說明如何用 C 語言設計物件導向的程式。</p> <p>物件導向語言大致上具有三個主要的特徵 &#8212; 「封裝、繼承與多型」，以下是這三種特徵的基本描述與範例。</p> <p>封裝：將資料與函數放在一種稱為物件的結構中。</p> <p>繼承：子物件可以繼承父物件的所有欄位與屬性，並且可以新增欄位或修改函數。</p> <p>多型：多種不同的子物件繼承同一種上層物件時，我們可以用上層物件容納之，在呼叫時仍然會根據真實物件型態呼叫對應的子物件函數。</p> <h1><span>物件導向的三種基本特徵</span></h1> <p>封裝：</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-reserved">class</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">area</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0.0</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-brackets">}</span></pre></div> </div> <p>繼承：</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-reserved">class</span><span class="hl-code"> </span><span class="hl-identifier">Circle</span><span class="hl-code"> </span><span class="hl-reserved">extends</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">r</span><span class="hl-code">; </span><span class="hl-identifier">Circle</span><span class="hl-brackets">(</span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">pr</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">r</span><span class="hl-code"> = </span><span class="hl-identifier">pr</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">area</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">3.14</span><span class="hl-code">*</span><span class="hl-identifier">r</span><span class="hl-code">*</span><span class="hl-identifier">r</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-brackets">}</span></pre></div> </div> <p>多型：</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-code"> </span><span class="hl-identifier">s</span><span class="hl-brackets">[]</span><span class="hl-code"> = </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-brackets">()</span><span class="hl-code">, </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Circle</span><span class="hl-brackets">(</span><span class="hl-number">3.0</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">}</span><span class="hl-code">; </span><span class="hl-reserved">for</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">i</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code">&lt;</span><span class="hl-identifier">s</span><span class="hl-code">.</span><span class="hl-identifier">length</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code">++</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">area()=</span><span class="hl-quotes">&quot;</span><span class="hl-code">+</span><span class="hl-identifier">s</span><span class="hl-brackets">[</span><span class="hl-identifier">i</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">area</span><span class="hl-brackets">())</span><span class="hl-code">;</span></pre></div> </div> <h1><span>完整程式範例</span></h1> <div class="code"> <div class="hl-main"> <pre><span class="hl-reserved">class</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">area</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0.0</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-types">static</span><span class="hl-code"> </span><span class="hl-types">void</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">(</span><span class="hl-identifier">String</span><span class="hl-brackets">[]</span><span class="hl-code"> </span><span class="hl-identifier">argv</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-code"> </span><span class="hl-identifier">s</span><span class="hl-brackets">[]</span><span class="hl-code"> = </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-brackets">()</span><span class="hl-code">, </span><span class="hl-reserved">new</span><span class="hl-code"> </span><span class="hl-identifier">Circle</span><span class="hl-brackets">(</span><span class="hl-number">3.0</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">}</span><span class="hl-code">; </span><span class="hl-reserved">for</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">i</span><span class="hl-code">=</span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code">&lt;</span><span class="hl-identifier">s</span><span class="hl-code">.</span><span class="hl-identifier">length</span><span class="hl-code">; </span><span class="hl-identifier">i</span><span class="hl-code">++</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">System</span><span class="hl-code">.</span><span class="hl-identifier">out</span><span class="hl-code">.</span><span class="hl-identifier">println</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">area()=</span><span class="hl-quotes">&quot;</span><span class="hl-code">+</span><span class="hl-identifier">s</span><span class="hl-brackets">[</span><span class="hl-identifier">i</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">area</span><span class="hl-brackets">())</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-reserved">class</span><span class="hl-code"> </span><span class="hl-identifier">Circle</span><span class="hl-code"> </span><span class="hl-reserved">extends</span><span class="hl-code"> </span><span class="hl-identifier">Shape</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">public</span><span class="hl-code"> </span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">r</span><span class="hl-code">; </span><span class="hl-identifier">Circle</span><span class="hl-brackets">(</span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">pr</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">r</span><span class="hl-code"> = </span><span class="hl-identifier">pr</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">double</span><span class="hl-code"> </span><span class="hl-identifier">area</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">3.14</span><span class="hl-code">*</span><span class="hl-identifier">r</span><span class="hl-code">*</span><span class="hl-identifier">r</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-brackets">}</span></pre></div> </div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;javac Shape.java D:\cp&gt;java Shape area()=0.0 area()=28.259999999999998</code></pre></div> <p>在本文中，我們介紹了如何使用 Java 實作封裝、繼承、多型等三種物件導向的基本特性，在本章的後續小節中，我們將同樣以 Shape 這個範例，說明如何用 C 語言實作出這些物件導向功能。</p> <h1><span>來自 jserv 的建議</span></h1> <div class="code"> <pre><code>&quot;&quot;&quot; C 語言雖然不是一種物件導向的語言，但是由於具有函數指標 (function pointer) 與結構 (struct)，因此可以讓我們模擬出類似物件導向的語法。在本章中，我們將說明如何用 C 語言設計物件導向的程式。 &quot;&quot;&quot; =&gt; 說法不精確，object-oriented programming (OOP) [1] 是種 programming paradigm，用淺顯的話語，就是「物件導向是一種程式開發的態度」，請不要把 OOP 和 OOPL 混淆了，後者是程式語言層面提供 OO 思維。我建議改為以下: &quot;&quot;&quot; C 語言一開始並非針對物件導向程式開發而設計的程式語言，但我們可藉由函式指標和結構體，將物件導向落實在 C 程式中。 &quot;&quot;&quot; 注意: C 語言規格書出現 &quot;object&quot; 字樣近八百次！ 另外，內文還提到: &quot;&quot;&quot; 物件導向語言大致上具有三個主要的特徵 — 「封裝、繼承與多型」，以下是這三種特徵的基本描述與範例。 &quot;&quot;&quot; =&gt; 這個說法不正確，不該把「落實物件導向的機制」當作物件導向，這樣因果錯位實在不好。OOP 的落實有兩種方向： (a) object-based: 如 Java, C++ (b) prototype-based: 如 JavaScript 後者在 C 語言的落實機制可見拙作: http://blog.linux.org.tw/~jserv/archives/002057.html [1] OOP: https://en.wikipedia.org/wiki/Object-oriented_programming</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:linkedlistembed</guid>
				<title>以 C 語言實作鏈結串列 -- 外包物件版</title>
				<link>http://ccckmit.wikidot.com/cp:linkedlistembed</link>
				<description>

&lt;p&gt;本範例的實作靈感來自 Linux 核心中的雙向鏈結串列，為了簡單起見，我們改為單向鏈結串列，以便讓讀者容易理解。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 01 Sep 2010 05:35:13 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>本範例的實作靈感來自 Linux 核心中的雙向鏈結串列，為了簡單起見，我們改為單向鏈結串列，以便讓讀者容易理解。</p> <h1><span>程式範例：</span></h1> <p>檔案：LinkedListEmbed.c</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">stdio.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-prepro">#define</span><span class="hl-code"> </span><span class="hl-identifier">offsetof</span><span class="hl-brackets">(</span><span class="hl-identifier">type</span><span class="hl-code">, </span><span class="hl-identifier">member</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">((</span><span class="hl-identifier">size_t</span><span class="hl-brackets">)</span><span class="hl-code"> &amp;</span><span class="hl-brackets">((</span><span class="hl-identifier">type</span><span class="hl-code"> *</span><span class="hl-brackets">)</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">member</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-prepro">#define</span><span class="hl-code"> </span><span class="hl-identifier">ListEntry</span><span class="hl-brackets">(</span><span class="hl-identifier">ptr</span><span class="hl-code">,</span><span class="hl-identifier">type</span><span class="hl-code">,</span><span class="hl-identifier">member</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">((</span><span class="hl-identifier">type</span><span class="hl-code"> *</span><span class="hl-brackets">)((</span><span class="hl-types">char</span><span class="hl-code"> *</span><span class="hl-brackets">)(</span><span class="hl-identifier">ptr</span><span class="hl-brackets">)</span><span class="hl-code">-</span><span class="hl-brackets">(</span><span class="hl-types">unsigned</span><span class="hl-code"> </span><span class="hl-types">long</span><span class="hl-brackets">)(</span><span class="hl-code">&amp;</span><span class="hl-brackets">((</span><span class="hl-identifier">type</span><span class="hl-code"> *</span><span class="hl-brackets">)</span><span class="hl-number">0</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">member</span><span class="hl-brackets">)))</span><span class="hl-code"> </span><span class="hl-prepro">#define</span><span class="hl-code"> </span><span class="hl-identifier">ListNew</span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">((</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">next</span><span class="hl-code">=</span><span class="hl-prepro">NULL</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-prepro">#define</span><span class="hl-code"> </span><span class="hl-identifier">ListAdd</span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-code">, </span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">next</span><span class="hl-code">=</span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">next</span><span class="hl-code">; </span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">next</span><span class="hl-code"> = </span><span class="hl-brackets">(</span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-prepro">#define</span><span class="hl-code"> </span><span class="hl-identifier">ListEach</span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-code">, </span><span class="hl-identifier">pos</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">for</span><span class="hl-code"> </span><span class="hl-brackets">(</span><span class="hl-identifier">pos</span><span class="hl-code"> = </span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code">-&gt;</span><span class="hl-identifier">next</span><span class="hl-code">; </span><span class="hl-identifier">pos</span><span class="hl-code"> != </span><span class="hl-prepro">NULL</span><span class="hl-code">; </span><span class="hl-identifier">pos</span><span class="hl-code"> = </span><span class="hl-identifier">pos</span><span class="hl-code">-&gt;</span><span class="hl-identifier">next</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-types">typedef</span><span class="hl-code"> </span><span class="hl-types">struct</span><span class="hl-code"> </span><span class="hl-identifier">listnode</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">struct</span><span class="hl-code"> </span><span class="hl-identifier">listnode</span><span class="hl-code"> *</span><span class="hl-identifier">next</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-identifier">ListNode</span><span class="hl-code">; </span><span class="hl-types">typedef</span><span class="hl-code"> </span><span class="hl-types">struct</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-types">char</span><span class="hl-code"> *</span><span class="hl-identifier">name</span><span class="hl-code">; </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">age</span><span class="hl-code">; </span><span class="hl-identifier">ListNode</span><span class="hl-code"> </span><span class="hl-identifier">node</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-identifier">Person</span><span class="hl-code">; </span><span class="hl-types">void</span><span class="hl-code"> </span><span class="hl-identifier">PersonListPrint</span><span class="hl-brackets">(</span><span class="hl-identifier">ListNode</span><span class="hl-code"> *</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">ListNode</span><span class="hl-code"> *</span><span class="hl-identifier">ptr</span><span class="hl-code">; </span><span class="hl-identifier">ListEach</span><span class="hl-brackets">(</span><span class="hl-identifier">head</span><span class="hl-code">, </span><span class="hl-identifier">ptr</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">Person</span><span class="hl-code"> *</span><span class="hl-identifier">person</span><span class="hl-code"> = </span><span class="hl-identifier">ListEntry</span><span class="hl-brackets">(</span><span class="hl-identifier">ptr</span><span class="hl-code">, </span><span class="hl-identifier">Person</span><span class="hl-code">, </span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">%s is %d years old</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">person</span><span class="hl-code">-&gt;</span><span class="hl-identifier">name</span><span class="hl-code">, </span><span class="hl-identifier">person</span><span class="hl-code">-&gt;</span><span class="hl-identifier">age</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-comment">// 請注意，在本程式中，ListEach 會忽略表頭節點，因此 head 不應該包在 Person 裡面。</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">ListNode</span><span class="hl-code"> </span><span class="hl-identifier">head</span><span class="hl-code">; </span><span class="hl-identifier">Person</span><span class="hl-code"> </span><span class="hl-identifier">john</span><span class="hl-code"> = </span><span class="hl-brackets">{</span><span class="hl-code"> .</span><span class="hl-identifier">name</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">John</span><span class="hl-quotes">&quot;</span><span class="hl-code">, .</span><span class="hl-identifier">age</span><span class="hl-code"> = </span><span class="hl-number">40</span><span class="hl-code">, </span><span class="hl-brackets">}</span><span class="hl-code">; </span><span class="hl-identifier">Person</span><span class="hl-code"> </span><span class="hl-identifier">mary</span><span class="hl-code"> = </span><span class="hl-brackets">{</span><span class="hl-code"> .</span><span class="hl-identifier">name</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">Mary</span><span class="hl-quotes">&quot;</span><span class="hl-code">, .</span><span class="hl-identifier">age</span><span class="hl-code"> = </span><span class="hl-number">32</span><span class="hl-code">, </span><span class="hl-brackets">}</span><span class="hl-code">; </span><span class="hl-identifier">Person</span><span class="hl-code"> </span><span class="hl-identifier">george</span><span class="hl-code"> = </span><span class="hl-brackets">{</span><span class="hl-code"> .</span><span class="hl-identifier">name</span><span class="hl-code"> = </span><span class="hl-quotes">&quot;</span><span class="hl-string">George</span><span class="hl-quotes">&quot;</span><span class="hl-code">, .</span><span class="hl-identifier">age</span><span class="hl-code"> = </span><span class="hl-number">26</span><span class="hl-code">, </span><span class="hl-brackets">}</span><span class="hl-code">; </span><span class="hl-identifier">ListNew</span><span class="hl-brackets">(</span><span class="hl-code">&amp;</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">ListAdd</span><span class="hl-brackets">(</span><span class="hl-code">&amp;</span><span class="hl-identifier">head</span><span class="hl-code">, &amp;</span><span class="hl-identifier">john</span><span class="hl-code">.</span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">ListAdd</span><span class="hl-brackets">(</span><span class="hl-code">&amp;</span><span class="hl-identifier">head</span><span class="hl-code">, &amp;</span><span class="hl-identifier">mary</span><span class="hl-code">.</span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">ListAdd</span><span class="hl-brackets">(</span><span class="hl-code">&amp;</span><span class="hl-identifier">head</span><span class="hl-code">, &amp;</span><span class="hl-identifier">george</span><span class="hl-code">.</span><span class="hl-identifier">node</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-identifier">PersonListPrint</span><span class="hl-brackets">(</span><span class="hl-code">&amp;</span><span class="hl-identifier">head</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code">; </span><span class="hl-brackets">}</span></pre></div> </div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;gcc LinkedListEmbed.c -o LinkedListEmbed D:\cp&gt;LinkedListEmbed George is 26 years old Mary is 32 years old John is 40 years old</code></pre></div> <h1><span>來自 jserv 的建議</span></h1> <p>` =&gt; 內文沒提到將資料搬出 list 結構的優勢，建議提供 for_each 的使用案例: http://stackoverflow.com/questions/15754236/how-do-i-use-the-list-for-each-macro-in-list-h-from-the-linux-kernel-properly `</p> <p>問題是，除了巨集展開不需要進函數， 速度可能會比較快之外，我也想不出其他的優勢了，所以就請大家自己想想，或者問 jserv 。</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:structure</guid>
				<title>高等 C 語言 -- 結構 (Structure)</title>
				<link>http://ccckmit.wikidot.com/cp:structure</link>
				<description>

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:structure&quot;&gt;結構&lt;/a&gt; &amp;#8212; (Structure)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:structinit&quot;&gt;結構的初始化&lt;/a&gt; &amp;#8212; (Initialization) C 語言可以直接設定整個結構的欄位初始值。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:structbits&quot;&gt;結構中的位元欄&lt;/a&gt; &amp;#8212; (Bits Field) 位元欄位，讓您位每個位元取名字。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:structpointer&quot;&gt;結構的指標算術&lt;/a&gt; &amp;#8212; (Pointer Arithmatics) 利用結構存取欄位，或從欄位計算結構起始點。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:linkedlist&quot;&gt;鏈結串列-基礎版&lt;/a&gt; &amp;#8212; (Linked List) 最簡單的單向鏈結串列實作。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:linkedlistobj&quot;&gt;鏈結串列：內含物件版&lt;/a&gt; &amp;#8212; 通用性鏈結串列，一般性的寫法。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:linkedlistembed&quot;&gt;鏈結串列：外包物件版&lt;/a&gt; &amp;#8212; 模仿 Linux 核心的作法的鏈結串列。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 02 Sep 2010 23:39:01 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <ul> <li><a href="http://ccckmit.wikidot.com/cp:structure">結構</a> &#8212; (Structure) <ul> <li><a href="http://ccckmit.wikidot.com/cp:structinit">結構的初始化</a> &#8212; (Initialization) C 語言可以直接設定整個結構的欄位初始值。</li> <li><a href="http://ccckmit.wikidot.com/cp:structbits">結構中的位元欄</a> &#8212; (Bits Field) 位元欄位，讓您位每個位元取名字。</li> <li><a href="http://ccckmit.wikidot.com/cp:structpointer">結構的指標算術</a> &#8212; (Pointer Arithmatics) 利用結構存取欄位，或從欄位計算結構起始點。</li> <li><a href="http://ccckmit.wikidot.com/cp:linkedlist">鏈結串列-基礎版</a> &#8212; (Linked List) 最簡單的單向鏈結串列實作。</li> <li><a href="http://ccckmit.wikidot.com/cp:linkedlistobj">鏈結串列：內含物件版</a> &#8212; 通用性鏈結串列，一般性的寫法。</li> <li><a href="http://ccckmit.wikidot.com/cp:linkedlistembed">鏈結串列：外包物件版</a> &#8212; 模仿 Linux 核心的作法的鏈結串列。</li> </ul> </li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:structinit</guid>
				<title>C 語言中的結構初始化</title>
				<link>http://ccckmit.wikidot.com/cp:structinit</link>
				<description>

&lt;h1&gt;&lt;span&gt;程式範例&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 30 Aug 2010 03:41:57 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <h1><span>程式範例</span></h1> <p>這個範例程式為 C99 的《指定器初始化》( Designated Initializers)，使用 gcc 時建議加上 -std=C99 的參數。</p> <div class="code"> <pre><code>#include &lt;stdio.h&gt; typedef struct { char *name; int age; } person; int main() { person p = { .name = &quot;John&quot;, .age = 40 }; printf(&quot;%s is %d years old&quot;, p.name, p.age); }</code></pre></div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp\code&gt;gcc structInit.c -std=C99 -o structInit D:\cp\code&gt;structInit John is 40 years old</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:functionpointertype</guid>
				<title>函數指標的型態</title>
				<link>http://ccckmit.wikidot.com/cp:functionpointertype</link>
				<description>

&lt;p&gt;假如我們希望定義一個具有一個參數的函數指標形態，則可以採用下列方式。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 01 Sep 2010 02:57:11 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>假如我們希望定義一個具有一個參數的函數指標形態，則可以採用下列方式。</p> <blockquote> <p>typedef void(*F1)(void*);</p> </blockquote> <h1><span>程式範例：函數指標的型態</span></h1> <div class="code"> <div class="hl-main"> <pre><span class="hl-prepro">#include </span><span class="hl-quotes">&lt;</span><span class="hl-string">stdio.h</span><span class="hl-quotes">&gt;</span><span class="hl-code"> </span><span class="hl-types">typedef</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-brackets">(</span><span class="hl-code">*</span><span class="hl-identifier">OP</span><span class="hl-brackets">)(</span><span class="hl-types">int</span><span class="hl-code">,</span><span class="hl-types">int</span><span class="hl-brackets">)</span><span class="hl-code">; </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">add</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">, </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">b</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">+</span><span class="hl-identifier">b</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">mult</span><span class="hl-brackets">(</span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">, </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">b</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-identifier">a</span><span class="hl-code">*</span><span class="hl-identifier">b</span><span class="hl-code">; </span><span class="hl-brackets">}</span><span class="hl-code"> </span><span class="hl-types">int</span><span class="hl-code"> </span><span class="hl-identifier">main</span><span class="hl-brackets">()</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"> </span><span class="hl-identifier">OP</span><span class="hl-code"> </span><span class="hl-identifier">op</span><span class="hl-code"> = </span><span class="hl-identifier">add</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">op(3,5)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">op</span><span class="hl-brackets">(</span><span class="hl-number">3</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-identifier">op</span><span class="hl-code"> = </span><span class="hl-identifier">mult</span><span class="hl-code">; </span><span class="hl-identifier">printf</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">op(3,5)=%d</span><span class="hl-special">\</span><span class="hl-string">n</span><span class="hl-quotes">&quot;</span><span class="hl-code">, </span><span class="hl-identifier">op</span><span class="hl-brackets">(</span><span class="hl-number">3</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">))</span><span class="hl-code">; </span><span class="hl-brackets">}</span></pre></div> </div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;gcc fpointertype.c -o fpointertype D:\cp&gt;fpointertype op(3,5)=8 op(3,5)=15</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:functionpointer</guid>
				<title>C 語言中的函數指標</title>
				<link>http://ccckmit.wikidot.com/cp:functionpointer</link>
				<description>

&lt;p&gt;範例：函數指標的用法&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 30 Aug 2010 03:30:34 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>範例：函數指標的用法</p> <div class="code"> <pre><code>#include &lt;stdio.h&gt; int add(int a, int b) { return a+b; } int mult(int a, int b) { return a*b; } int main() { int (*op)(int a, int b); op = add; printf(&quot;op(3,5)=%d\n&quot;, op(3,5)); op = mult; printf(&quot;op(3,5)=%d\n&quot;, op(3,5)); }</code></pre></div> <p>執行結果：</p> <div class="code"> <pre><code>D:\cp\code&gt;gcc fpointer.c -o fpointer D:\cp\code&gt;fpointer op(3,5)=8 op(3,5)=15</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:function</guid>
				<title>高等 C 語言 -- 函式</title>
				<link>http://ccckmit.wikidot.com/cp:function</link>
				<description>

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:function&quot;&gt;函數&lt;/a&gt; &amp;#8212; (function)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:functionpointer&quot;&gt;函數指標&lt;/a&gt; &amp;#8212; (function pointer) 函式指標是 C 語言當中威力強大的工具，專業人士必定會善用之。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:functionpointertype&quot;&gt;函數指標型態&lt;/a&gt; &amp;#8212; (function pointer type) 用 typedef 將函數指標宣告成一種型態。&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccckmit.wikidot.com/cp:vaarg&quot;&gt;變動參數&lt;/a&gt; &amp;#8212; (va_arg, va_list) 變動個數參數，也就是使用 &amp;#8230; 宣告的參數，要如何使用呢？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Thu, 02 Sep 2010 23:30:26 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <ul> <li><a href="http://ccckmit.wikidot.com/cp:function">函數</a> &#8212; (function) <ul> <li><a href="http://ccckmit.wikidot.com/cp:functionpointer">函數指標</a> &#8212; (function pointer) 函式指標是 C 語言當中威力強大的工具，專業人士必定會善用之。</li> <li><a href="http://ccckmit.wikidot.com/cp:functionpointertype">函數指標型態</a> &#8212; (function pointer type) 用 typedef 將函數指標宣告成一種型態。</li> <li><a href="http://ccckmit.wikidot.com/cp:vaarg">變動參數</a> &#8212; (va_arg, va_list) 變動個數參數，也就是使用 &#8230; 宣告的參數，要如何使用呢？</li> </ul> </li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://ccckmit.wikidot.com/cp:ptradd</guid>
				<title>C 語言中的指標算術</title>
				<link>http://ccckmit.wikidot.com/cp:ptradd</link>
				<description>

&lt;p&gt;在 C 語言當中，指標型態的變數，像是下列範例中的 char *cp; int* ip; 等，其加減法的表現，會根據型態而有所不同。&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=296763&amp;amp;amp;size=small&amp;amp;amp;timestamp=1778987702&quot; alt=&quot;ccckmit&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=296763)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/ccckmit&quot;  &gt;ccckmit&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 31 Aug 2010 06:14:28 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>在 C 語言當中，指標型態的變數，像是下列範例中的 char *cp; int* ip; 等，其加減法的表現，會根據型態而有所不同。</p> <p>舉例而言，假如 cp = 0x0022FF77，那麼 cp+1 就是 0x0022FF78，因為 cp 是一種字元指標，這種結果是理所當然的。</p> <p>但是，假如 ip = 0x0022FF6C，那麼 ip+1 卻是 0x0022FF70，這是因為 ip 是整數指標，因此當我們將 ip 加上 1 單位距離時，這個一單位距離的大小就相當於整數 int 的大小，也就是 sizeof(int) = 4。</p> <h1><span>範例程式</span></h1> <div class="code"> <pre><code>#include &lt;stdio.h&gt; int main() { char c = 'a'; char *cp = &amp;c; printf(&quot;&amp;c=%p\n&quot;, &amp;c); printf(&quot;cp=%p\n&quot;, cp); printf(&quot;cp+1=%p\n&quot;, cp+1); printf(&quot;cp+3=%p\n&quot;, cp+3); int i = 1; int *ip = &amp;i; printf(&quot;&amp;i=%p\n&quot;, &amp;i); printf(&quot;ip=%p\n&quot;, ip); printf(&quot;ip+1=%p\n&quot;, ip+1); printf(&quot;ip+3=%p\n&quot;, ip+3); }</code></pre></div> <h1><span>執行結果</span></h1> <div class="code"> <pre><code>D:\cp&gt;gcc ptradd.c -o ptradd D:\cp&gt;ptradd &amp;c=0022FF77 cp=0022FF77 cp+1=0022FF78 cp+3=0022FF7A &amp;i=0022FF6C ip=0022FF6C ip+1=0022FF70 ip+3=0022FF78</code></pre></div> <h1><span>習題</span></h1> <p>這個設計的邏輯，是為了讓您寫程式時，可以都用 ptr ++ 來將指標前進一格，而不需要用 ptr += sizeof(*ptr) 這樣複雜的寫法，但是這也造成了一些問題。</p> <p>假如您的認知錯誤，很可能會多此一舉，萬一您自己計算大小以便調整指標時，就會產生錯誤的結果，像是以下程式一樣。</p> <div class="code"> <pre><code>#include &lt;stdio.h&gt; int main() { int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *ptr = a; int i; for (i=0; i&lt;3; i++) { printf(&quot;%d &quot;, *ptr); ptr += sizeof(int); } }</code></pre></div> <p>習題的輸出</p> <div class="code"> <pre><code>D:\cp&gt;gcc ptrerror.c -o ptrerror D:\cp&gt;ptrerror 1 5 9</code></pre></div> <p>如果您已經讀懂了上面的範例，那麼，您一定可以看出為何下列程式會有那樣奇怪的輸出了吧？這顯然是一個不容易理解的 bug。</p> <h1><span>補充</span></h1> <p>根據 jserv 的來信補充，提到下列這幾點，是本文原本所沒提到的：</p> <div class="code"> <pre><code>* pointer type 的變數可以對一個純量作 '+' 和 '-' 操作 * 兩個 pointer type 的變數可以施加 '-' 操作，以得知位移量 (offset)，但不能施加 '+' 操作 意思是說，假設: int a, b; void *ptrA = &amp;a, *ptrB = &amp;b; 那麼： ptrB - ptrA; // 合法 ptrA + 1; 合法 ptrA - 1; 合法 ptrA + ptrB; // 不合法 ptrA / 1; // 不合法</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/ccckmit" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=296763&amp;amp;size=small&amp;amp;timestamp=1778987702" alt="ccckmit" style="background-image:url(http://www.wikidot.com/userkarma.php?u=296763)" /></a><a href="http://www.wikidot.com/user:info/ccckmit" >ccckmit</a></span></p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>