<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="lyceum/1.0.3" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>工程师的Blog</title>
	<link>http://xysblogs.org/eng</link>
	<description>只动手指的工程师</description>
	<pubDate>Fri, 16 Jul 2010 04:20:19 +0000</pubDate>
	<generator>http://lyceum.ibiblio.org/?v=1.0.3</generator>
	<language>en</language>
			<item>
		<title>记几件小事</title>
		<link>http://xysblogs.org/eng/archives/7807</link>
		<comments>http://xysblogs.org/eng/archives/7807#comments</comments>
		<pubDate>Fri, 16 Jul 2010 04:20:19 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>杂谈</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/7807</guid>
		<description><![CDATA[N年以前我被人拉去上教堂，在路上一开始被讲解什么是三位一体，还觉得有点意思，后来被教导要&#8220;呼主名&#8221;，恶心得我要吐了。
M年以前第一次看到成功学的书，一开始看看一个一个小故事还有点意思，看到一半开始想吐。
K年以前见一同学母亲手捧一本类似成功学或是心灵鸡汤的书，直接表达了我对这类书的轻蔑，结果是同学很尴尬。
几分钟前看到一张唐粉书架照片，一下子想起以前这些鸡毛蒜皮的小事，且记一下。
]]></description>
			<content:encoded><![CDATA[<p>N年以前我被人拉去上教堂，在路上一开始被讲解什么是三位一体，还觉得有点意思，后来被教导要&ldquo;呼主名&rdquo;，恶心得我要吐了。</p>
<p>M年以前第一次看到成功学的书，一开始看看一个一个小故事还有点意思，看到一半开始想吐。</p>
<p>K年以前见一同学母亲手捧一本类似成功学或是心灵鸡汤的书，直接表达了我对这类书的轻蔑，结果是同学很尴尬。</p>
<p>几分钟前看到一张唐粉书架照片，一下子想起以前这些鸡毛蒜皮的小事，且记一下。</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/7807/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The C Book － 第一章  C语言概述 (6)</title>
		<link>http://xysblogs.org/eng/archives/7437</link>
		<comments>http://xysblogs.org/eng/archives/7437#comments</comments>
		<pubDate>Thu, 27 May 2010 07:09:44 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>编程</category>

		<category>翻译</category>

		<category>The_C_Book</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/7437</guid>
		<description><![CDATA[
第1.5节 术语
&#160;
在C语言程序中有两种不同类型的东西，一类是用来存放数值的，另一类则是函数。与其编造一个着意于这两者区别的名字来做为这两类东西的统称，还不如把它们笼统地称为&#8220;对象&#8221;更好一些。我们以后会常常这样做，因为这两类东西差不多可以用同样的规则来处理。不过，要注意的是，在C语言标准中&#8220;对象&#8221;一词有不同的含义。在C语言标准中，&#8220;对象&#8221;仅仅指存放数值用的区域，而函数则是不同的东西。这样一来，C语言标准中就经常得说&#8220;函数与对象&#8221;如何如何。我们认为，使用笼统的&#8220;对象&#8221;来统称这两者一般不会导致歧义，而会使文字更容易理解。因此我们将继续使用&#8220;对象&#8221;一词来指代这两者。当确实需要区分这两者的时候，我们会使用&#8220;数据对象&#8221;和&#8220;函数&#8221;这样的术语，以明确表示两者的区别。
&#160;
如果你要去读C语言标准的话，请注意这点区别。
&#160;
第1.6节 小结
&#160;
本章以不太严格的方式介绍了C语言的基本知识。在这里，函数是构成C语言的基本结构。在第四章中，我们会详细解说这些基本对象，不过你现在应该已经有了足够的知识来理解它们在中间章节里的用法。
&#160;
尽管本章中介绍了库函数，我们还没来得及仔细解说这些库函数对于C语言应用程序员的重要之处。在第九章中将会讲到的标准函数库，是非常重要的。它既可以让一般程序更容易移植，也可以让程序员利用它里面提供的很有用的函数来提高效率。
&#160;
我们即将详细讲解变量、表达式以及算术运算。如同本章所述，C语言在简单的层面上和其它现代编程语言没有太大区别。
&#160;
我们已经非常简单的介绍了一下数组，不过对于结构数据类型的使用，我们将在后面讲解。
&#160;
第1.7节 习题
&#160;
题1.1、 在你的系统上输入并测试例1.1中的程序。
&#160;
题1.2、 用例1.2为参考，编写一个程序来输出质数对。&#8220;质数对&#8221;指的是相差为2的两个质数，例如11和13、29和31。（如果你发现了质数对之间有什么规律，那么就要恭喜你了。你要么是天才，要么是做错了。）
题1.3、 编写一个函数。这个函数从getchar读入数字字符，并返回这个字符串所代表的整数值。比如，这个函数先读到一个1，再读入4，再读入6，那么它就应该返回数值146。你可以假设数字0-9在计算机里的表达方式是连续的（C语言标准里这样规定的），而且你的函数只需要处理有效的数字和回车符，而不需要进行错误检验。
题1.4、 用上题所写的函数读入一系列数值。通过不断地调用这个函数，将这些数值放入 main 函数中所声明的数组中。将这些数值按升序排序，并打印出结果。
&#160;
题1.5、 同样，用题1.3中所编写的函数来编写一个程序。这个程序从输入中读入数字，然后以十进制、二进制以及十六进制的格式输出这些数字。除了本章所讲的内容以外，不可以使用 printf 函数的其它功能（特别是十六进制格式输出的功能）。你必需计算要输出的每一个字符，并保证这些字符以正确的顺序输出。这并不是很难，但也不是很容易。
&#160;
]]></description>
			<content:encoded><![CDATA[<p><span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: 'Bitstream Vera Sans Mono'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"></span></p>
<h2 style="font-size: 14pt;"><a name="sec1.5"></a>第1.5节 术语</h2>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">在C语言程序中有两种不同类型的东西，一类是用来存放数值的，另一类则是函数。与其编造一个着意于这两者区别的名字来做为这两类东西的统称，还不如把它们笼统地称为&ldquo;对象&rdquo;更好一些。我们以后会常常这样做，因为这两类东西差不多可以用同样的规则来处理。不过，要注意的是，在C语言标准中&ldquo;对象&rdquo;一词有不同的含义。在C语言标准中，&ldquo;对象&rdquo;仅仅指存放数值用的区域，而函数则是不同的东西。这样一来，C语言标准中就经常得说&ldquo;函数与对象&rdquo;如何如何。我们认为，使用笼统的&ldquo;对象&rdquo;来统称这两者一般不会导致歧义，而会使文字更容易理解。因此我们将继续使用&ldquo;对象&rdquo;一词来指代这两者。当确实需要区分这两者的时候，我们会使用&ldquo;数据对象&rdquo;和&ldquo;函数&rdquo;这样的术语，以明确表示两者的区别。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">如果你要去读C语言标准的话，请注意这点区别。</div>
<p>&nbsp;</p>
<h2 style="font-size: 14pt;"><a name="sec1.6"></a>第1.6节 小结</h2>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">本章以不太严格的方式介绍了C语言的基本知识。在这里，函数是构成C语言的基本结构。在第四章中，我们会详细解说这些基本对象，不过你现在应该已经有了足够的知识来理解它们在中间章节里的用法。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">尽管本章中介绍了库函数，我们还没来得及仔细解说这些库函数对于C语言应用程序员的重要之处。在第九章中将会讲到的标准函数库，是<strong>非常</strong>重要的。它既可以让一般程序更容易移植，也可以让程序员利用它里面提供的很有用的函数来提高效率。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">我们即将详细讲解变量、表达式以及算术运算。如同本章所述，C语言在简单的层面上和其它现代编程语言没有太大区别。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">我们已经非常简单的介绍了一下数组，不过对于结构数据类型的使用，我们将在后面讲解。</div>
<p>&nbsp;</p>
<h2 style="font-size: 14pt;"><a name="sec1.7"></a>第1.7节 习题</h2>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">题1.1、 在你的系统上输入并测试例1.1中的程序。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">题1.2、 用例1.2为参考，编写一个程序来输出质数对。&ldquo;质数对&rdquo;指的是相差为2的两个质数，例如11和13、29和31。（如果你发现了质数对之间有什么规律，那么就要恭喜你了。你要么是天才，要么是做错了。）</div>
<p>题1.3、 编写一个函数。这个函数从getchar读入数字字符，并返回这个字符串所代表的整数值。比如，这个函数先读到一个1，再读入4，再读入6，那么它就应该返回数值146。你可以假设数字0-9在计算机里的表达方式是连续的（C语言标准里这样规定的），而且你的函数只需要处理有效的数字和回车符，而不需要进行错误检验。</p>
<div style="margin-top: 0px; margin-bottom: 0px;">题1.4、 用上题所写的函数读入一系列数值。通过不断地调用这个函数，将这些数值放入 main 函数中所声明的数组中。将这些数值按升序排序，并打印出结果。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">题1.5、 同样，用题1.3中所编写的函数来编写一个程序。这个程序从输入中读入数字，然后以十进制、二进制以及十六进制的格式输出这些数字。除了本章所讲的内容以外，不可以使用 printf 函数的其它功能（特别是十六进制格式输出的功能）。你必需计算要输出的每一个字符，并保证这些字符以正确的顺序输出。这并不是很难，但也不是很容易。</div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/7437/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The C Book － 第一章 C语言概述 (5)</title>
		<link>http://xysblogs.org/eng/archives/7436</link>
		<comments>http://xysblogs.org/eng/archives/7436#comments</comments>
		<pubDate>Wed, 26 May 2010 09:24:19 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>编程</category>

		<category>翻译</category>

		<category>The_C_Book</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/7436</guid>
		<description><![CDATA[


第1.4节 更多的程序例

乘我们还在不是很严谨的时候，让我们再来看看两个程序例。这次你得自己想想里面的一些代码是做什么的，不过当新的或有趣的东西出现时，我们还是会讲解的。

1.4.1 一个寻找质数的程序
&#160;&#160; &#160;/*&#160; Dumb program that generates prime numbers. */&#160;
&#160;&#160; &#160;#include &#60;stdio.h&#62;&#160;
&#160;&#160; &#160;#include &#60;stdlib.h&#62;&#160;
&#160;&#160; &#160;
&#160;&#160; &#160;main(){&#160;
&#160;&#160; &#160;&#160;&#160; &#160;int this_number, divisor, not_prime;&#160;
&#160;
&#160;&#160; &#160;&#160;&#160; &#160;this_number = 3;&#160;
&#160;
&#160;&#160; &#160;&#160;&#160; &#160;while(this_number &#60; 10000){&#160;
&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;divisor = this_number / 2;&#160;
&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;not_prime = 0;&#160;
&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;while(divisor &#62; 1){&#160;
&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;if(this_number % divisor == 0){&#160;
&#160;&#160; [...]]]></description>
			<content:encoded><![CDATA[<p><span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: 'Bitstream Vera Sans Mono'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"></span></p>
<div style="margin-top: 0px; margin-bottom: 0px;">
<div style="margin-top: 0px; margin-bottom: 0px;">
<h2 style="font-size: 14pt;">第1.4节 更多的程序例</h2>
<p><span class="Apple-style-span" style="font-size: small;"><br /></span></p>
<p style="margin: 0px;">乘我们还在不是很严谨的时候，让我们再来看看两个程序例。这次你得自己想想里面的一些代码是做什么的，不过当新的或有趣的东西出现时，我们还是会讲解的。</p>
<p><span class="Apple-style-span" style="font-size: small;"><br /></span></p>
<h3 style="font-size: 12pt;">1.4.1 一个寻找质数的程序</h3>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;/*&nbsp; Dumb program that generates prime numbers. */&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;#include &lt;stdio.h&gt;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;#include &lt;stdlib.h&gt;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;main(){&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int this_number, divisor, not_prime;&nbsp;</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this_number = 3;&nbsp;</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(this_number &lt; 10000){&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;divisor = this_number / 2;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;not_prime = 0;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(divisor &gt; 1){&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(this_number % divisor == 0){&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;not_prime = 1;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;divisor = 0;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;else&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;divisor = divisor-1;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(not_prime == 0)&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&#8221;%d is a prime number\n&#8221;, this_number);&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this_number = this_number + 1;&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;exit(EXIT_SUCCESS);&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;}</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;<em>Example 1.2</em></span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">这里有什么有趣的东西？也许有几样新东西。这个程序的运行方式是很笨的：为了看一个数是否是质数，它就把这个数用从2到这个数的一半的所有数来除－－如果其中有一个能够整除，那么这个数就不是质数。这里有之前没有见过的两个操作符，一个是求余操作符%，另一个是等式操作符，也就是连起来的两个等号==。后者无疑是C语言中产生错误最多的单一因素。</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">像这样测试相等与否的问题在于，如果只放一个等号，它也是合法的语句。连等号==比较两个量是否相等，而这是在如下的程序片段中通常需要用到的：</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;if (a==b)</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;while (c==d)</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">也许有点让人意外的是，赋值操作符=在这些地方也是合法的，不过它的作用就是把右边表达式的值赋给左边的东西。如果你习惯了那些用C语言的赋值操作符做相等比较的编程语言，那么这个问题就更加严重了。这是完全没有办法的事，所以你只能入乡随俗了。（确实，现代的编译器会在它们发现&ldquo;可疑&rdquo;的赋值符的时候给出警告，不过如果你是故意这样写的，那也未知非祸。）</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">这里我们也第一次看到 if 语句。和 while 语句一样，if 语句测试一个表达式是否为真。你也许已经注意到了，它也和 while 语句一样，用来控制 if 语句的表达式是放在括号里的。必须总是如此：所有的流程条件控制语句都必须在其关键字后有一个放在括号里的表达式。关于 if 语句的正式描述是这样的：</span></span></div>
<p><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;if(<em>表达式</em>)&nbsp;</span></span></p>
</div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<em>语句</em>&nbsp;</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;if(<em>表达式</em>)&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<em>语句</em>&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;else&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<em>语句</em></span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">这显示了 if 语句有两种形式。当然，它的效果就是，如果表达式的部分为真，那么紧随其后的语句就被执行，则否该语句不执行。如果有一个 else 部分，那么跟着 else 的那个语句仅在表达式为假时被执行。</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">关于 if 语句，有一个很有名的问题。在下面的代码中，语句-2是会被执行还是不会被执行？</span></span></span></span></div>
<p><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;if(1 &gt; 0)</span></span></p>
</div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(1 &lt; 0)&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;语句-1&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;else&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;语句-2</span></span></p>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">答案是<strong>会</strong>被执行。这里你得忽略缩进（因为它让人误入歧途）。根据上面对于 if 语句的描述，这里的 else 既可以属于第一个 if 也可以属于第二个 if。因此，为了避免歧义，还需要另一条规则。这条规则很简单，就是一个 else 总是从属于在它前面最近的一个没有 else 搭配的 if 。在上例中，如果想让程序按照缩进的格式所隐含的方式运行，我们就必须使用一个复合语句：</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;if(1 &gt; 0) {</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(1 &lt; 0)&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;语句-1&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;}</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp;else&nbsp;</span></span></div>
<div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: #ffffff;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;语句-2</span></span></div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">在这里，C语言的处理方式至少和其它大多数编程语言一样的。事实上，很多程序员熟悉存在着这种问题的编程语言，而他们根本从来没有意识到这个问题的存在－－他们只是认为这种消除歧义的规则是&ldquo;显而易见&rdquo;的。我们希望每个人都会这样认为吧。</div>
<p>&nbsp;</p>
<h3 style="font-size: 12pt;">1.4.2 除法操作符集</h3>
<p>除法操作符集包括除法操作符&ldquo;/&rdquo;和求余操作符&ldquo;%&rdquo;。除法操作符进行的是一般的除法，但当操作数为整数时，结果会被向0舍入取整。比如，5/2的结果是2，5/3得1。求余操作符则可以用来得到整数除法中被舍弃的余数。C语言标准中规定了商和余数的符号如何由除数和被除数决定，具体规定请参见第二章。</p>
</div>
<p>&nbsp;</p>
<h3 style="font-size: 12pt;">1.4.3 输入的例子</h3>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">一些程序能够打印出多多少少有意思的列表和表格，而能够进行输入的程序也同样是很有用的。函数库中最简单的一个函数，也就是我们现在要讲到的这个函数，就是getchar函数。它每次从程序的输入中读取一个字符，然后返回一个整数值。返回的值是这个字符的一种编码形式，而这个编码可以用来输出同样的字符。这个编码也可以被用来和某个字符常量或是输入的其它字符相比较。不过，唯一有意义的比较，是看两个字符是否相等。一般来说，比较两个字符哪个大哪个小，是不可移植的。虽然在大多数系统中字符 &lsquo;a&rsquo; 是小于字符 &lsquo;b&rsquo; 的，但这不能保证在任何情况下都成立。C语言标准唯一的保证就是字符 &#8216;0&#8242; 到字符 &#8216;9&#8242; 是连续的。请看下例。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;#include &lt;stdio.h&gt;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;#include &lt;stdlib.h&gt;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;main(){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int ch;&nbsp;</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ch = getchar();&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(ch != &#8216;a&#8217;){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(ch != &#8216;\n&#8217;)&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&#8221;ch was %c, value %d\n&#8221;, ch, ch);&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ch = getchar();&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;exit(EXIT_SUCCESS);&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;}</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;<em>Example 1.3</em></div>
<p>这个例子中有两个要注意的地方。第一点，就是在读入的每一行结束的时候，都会看到一个用 &#8216;\n&#8217; 表示的字符（字符常量）。这和输出时用printf来产生一个新的行用的是同一个字符。在C语言中，输入输出的模型并不把数据看成一行一行的，而是一个字符一个字符的。如果你想把数据当成是一行一行的，那么你可以用这个 &#8216;\n&#8217; 字符来标记一行的结尾。当用 %d 来打印的时候，打印的是同一个变量，但显示的将是你的程序用来表示这个字符所用的整数值。</p>
<div style="margin-top: 0px; margin-bottom: 0px;">如果你试着运行一下这个程序，你就会发现有些系统并不是一个字符一个字符地把数据送到你的程序，而是会让你一次输入一整行。在这之后，这一整行就成为程序可用的输入数据，每次输入一个字符。初学者常常会被弄糊涂。程序开始运行时，他们敲进去一些数据，但却没有任何输出。这种现象和C语言本身没有关系，而是取决于具体的计算机和操作系统。</div>
<p>&nbsp;</p>
<h3 style="font-size: 12pt;">1.4.4 简单数组</h3>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">C语言中数组的使用，通常对于初学者是个难题。数组的声明，尤其是对于一维数组的声明，其实并不困难。但总是会让人糊涂的，是数组的下标总是从0开始。声明一个包含五个整数的数组，需要用到类似下面的声明语句：</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;int something[5];</div>
<p>如你所见，C语言中声明数组用的是方括号。数组的下标总是从0向上走，C语言不支持其它的下标范围。在上例中，有效的数组元素就是从 something[0] 到 something[4]。这里需要特别注意的是，something[5] 并<strong>不</strong>是一个有效的数组元素。</p>
<p>下面这个程序从输入中读取一些字符，并按这些字符的数值表达方式排序，最后输出结果。请自己分析这个程序的算法，因为下面我们不会着重讲解它的算法。</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;#include &lt;stdio.h&gt;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;#include &lt;stdlib.h&gt;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;#define ARSIZE 10&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;main(){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int ch_arr[ARSIZE], count1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int count2, stop, lastchar;&nbsp;</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;lastchar = 0;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;stop = 0;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/*</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;* 把字符读入数组，直至一行结束或数组已满</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(stop != 1){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ch_arr[lastchar] = getchar();&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(ch_arr[lastchar] == &#8216;\n&#8217;)&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;stop = 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;else&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;lastchar = lastchar + 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(lastchar == ARSIZE)&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;stop = 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;lastchar = lastchar-1;&nbsp;</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/*</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;* 这是传统的冒泡排序法&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;*/&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;count1 = 0;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(count1 &lt; lastchar){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;count2 = count1 + 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(count2 &lt;= lastchar){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(ch_arr[count1] &gt; ch_arr[count2]){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/* swap */&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int temp;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;temp = ch_arr[count1];&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ch_arr[count1] = ch_arr[count2];&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ch_arr[count2] = temp;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;count2 = count2 + 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;count1 = count1 + 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;count1 = 0;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(count1 &lt;= lastchar){&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&#8221;%c\n&#8221;, ch_arr[count1]);&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;count1 = count1 + 1;&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;exit(EXIT_SUCCESS);&nbsp;</div>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;}</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">&nbsp;&nbsp; &nbsp;<em>Example 1.4</em></div>
<p>你可能已经注意到了，在程序中我们一直都在使用一个定义的常数 ARSIZE，而不是直接用数组的实际大小。这是因为，如果我们想要改变这个程序可以排序的最大字符个数，我们只需要修改这个常数定义的这一行，然后重新编译。程序中还对数组是否已经放满进行了检查，这看起来不显眼，但对程序的安全至关重要。如果你仔细看看，就会发现，当第 ARSIZE-1 个数组元素被放入的时候，程序就停下来了。这是因为，对于一个有N个元素的数组，我们只能使用从第0个到第N-1个元素（所以总数是N个）。</p>
<div style="margin-top: 0px; margin-bottom: 0px;">和其它编程语言不同的是，在C语言中，如果你跑出了数组的界限，你很可能不会得到任何警告。当数组越界的情况发生时，这个程序就会出现所谓的未定义行为，通常在将来的某个时候导致很奇怪的错误。大多数有经验的程序员要么会以严格的测试来保证所使用的算法中数组越界的情况不会发生，要么在存取每一个数组元素之前都做一次明确的测试。数组越界是C语言程序运行时出错的常见原因。切记，切记。</div>
<p>&nbsp;</p>
<h3 style="font-size: 12pt;">小结</h3>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">数组下标总是从0开始，别无选择。</div>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-bottom: 0px;">一个有 n 个元素的数组，它的元素下标是从 0 到 n-1。第 n 个元素是不存在的。试图存取第 n 个元素是个很大的错误。<br /><br class="Apple-interchange-newline" /></div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/7436/feed/</wfw:commentRss>
		</item>
		<item>
		<title>关于Integrity of Science的翻译</title>
		<link>http://xysblogs.org/eng/archives/7394</link>
		<comments>http://xysblogs.org/eng/archives/7394#comments</comments>
		<pubDate>Fri, 14 May 2010 02:43:50 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>翻译</category>

		<category>杂谈</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/7394</guid>
		<description><![CDATA[这两天看到很多关于如何翻译Integrity of Science的不同看法。当然，这里首先要解决的问题是这个短语在英文中的实际意义。假设我们可以接受Susan Haack在The Integrity of Science: What It Means, Why It Matters一文中的阐述，那么它主要有三个层面上的意义。一个是科学作为一种知识体的层面，一个是科学家个人的层面，一个是科学作为一种体系、制度的层面。
方舟子认为因该译为&#8220;科学的完整性&#8221;。但中文的&#8220;完整&#8221;似乎只能体现出第一个层面的意思。我认为一个更好的译法是&#8220;科学的健全&#8221;。理由如下：
1、&#8220;全&#8221;本身包括了&#8220;完整&#8221;的意思，也就涵盖了science在知识体这个层面上的意思。
2、&#8220;健全&#8221;本身有soundness的意思。
3、Integrity of Science其中一层意思是在science qua  institution的层面上看。这里institution一般可译为制度、系统、体系，而&#8220;健全的制度／系统／体系&#8220;本身是常用的汉语。
4、 &#8220;健全&#8221;和integrity一样，既可以用于物（制度／系统／体系），也可以用于人。用于人时虽然多指身体，但也常常引申到精神。在两种情况下都通常用来形容好的品质。
5、用 &#8220;健全&#8221;的一个好处是可以去掉那个多余的&#8220;性&#8221;，做为汉语更加自然。
]]></description>
			<content:encoded><![CDATA[<p>这两天看到很多关于如何翻译Integrity of Science的不同看法。当然，这里首先要解决的问题是这个短语在英文中的实际意义。假设我们可以接受Susan Haack在The Integrity of Science: What It Means, Why It Matters一文中的阐述，那么它主要有三个层面上的意义。一个是科学作为一种知识体的层面，一个是科学家个人的层面，一个是科学作为一种体系、制度的层面。</p>
<p>方舟子认为因该译为&ldquo;科学的完整性&rdquo;。但中文的&ldquo;完整&rdquo;似乎只能体现出第一个层面的意思。我认为一个更好的译法是&ldquo;科学的健全&rdquo;。理由如下：</p>
<p>1、&ldquo;全&rdquo;本身包括了&ldquo;完整&rdquo;的意思，也就涵盖了science在知识体这个层面上的意思。</p>
<p>2、&ldquo;健全&rdquo;本身有soundness的意思。</p>
<p>3、Integrity of Science其中一层意思是在science qua  institution的层面上看。这里institution一般可译为制度、系统、体系，而&ldquo;健全的制度／系统／体系&ldquo;本身是常用的汉语。</p>
<p>4、 &ldquo;健全&rdquo;和integrity一样，既可以用于物（制度／系统／体系），也可以用于人。用于人时虽然多指身体，但也常常引申到精神。在两种情况下都通常用来形容好的品质。</p>
<p>5、用 &ldquo;健全&rdquo;的一个好处是可以去掉那个多余的&ldquo;性&rdquo;，做为汉语更加自然。</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/7394/feed/</wfw:commentRss>
		</item>
		<item>
		<title>为什么被救的人是趴着的</title>
		<link>http://xysblogs.org/eng/archives/7336</link>
		<comments>http://xysblogs.org/eng/archives/7336#comments</comments>
		<pubDate>Wed, 28 Apr 2010 04:26:25 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>未分类</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/7336</guid>
		<description><![CDATA[前几天新到里有&#8220;科学侦探&#8220;质疑，&#8220;为什么被救者在担架上要采取趴着的姿势？不知道这是哪门子的救护理论?&#8220;
这个趴着的姿势叫做Recovery Position。进行过急救处理后，必需要摆成这种姿势才能保证气道通畅。这一点任何上过急救课程的人都应该知道。
可参见：http://en.wikipedia.org/wiki/Recovery_position
]]></description>
			<content:encoded><![CDATA[<p>前几天新到里有&ldquo;科学侦探&ldquo;质疑，&ldquo;为什么被救者在担架上要采取趴着的姿势？不知道这是哪门子的救护理论?&ldquo;</p>
<p>这个趴着的姿势叫做Recovery Position。进行过急救处理后，必需要摆成这种姿势才能保证气道通畅。这一点任何上过急救课程的人都应该知道。</p>
<p>可参见：<a href="http://en.wikipedia.org/wiki/Recovery_position" target="_blank">http://en.wikipedia.org/wiki/Recovery_position</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/7336/feed/</wfw:commentRss>
		</item>
		<item>
		<title>闲话武术</title>
		<link>http://xysblogs.org/eng/archives/6687</link>
		<comments>http://xysblogs.org/eng/archives/6687#comments</comments>
		<pubDate>Tue, 22 Dec 2009 06:32:53 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>杂谈</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/6687</guid>
		<description><![CDATA[所谓&#8220;武&#8221;，从止从戈。从字面上看，一般人都会以为止戈就是停止争战的意思。不过恰恰相反，这里的&#8220;止戈&#8221;，是举戈行进的形象，准备战斗的意思。所谓&#8220;术&#8221;，就是技艺、方法的意思。所以合起来，&#8220;武术&#8221;，含蓄地说，就是战斗的方法，直接一点，就是冷兵器时代的杀人术。对敌人的身体有效地实施伤害，这是传统武术的本质。明白了这一点，才能对传统武术有一个正确的认识，中国和外国的都一样。这和现代的体育竞技武术、表演武术、健身武术等等有着很大的区别。

说到中国武术，很多人就会想到少林拳、太极拳之类。其实，通常所说&#8220;拳法&#8221;，或者说徒手搏击的技术，在中国古代大概是摆不上台面的。我所知道最早的关于武术的描写，是&#8220;越女剑&#8221;的故事。金庸先生固然妙笔生花，《吴越春秋》中的文言读起来已让人拍案叫绝。越女论道：&#8220;凡手战之道，内实精神，外示安逸，见之似好妇，夺之似惧虎，布形气候，与神俱往，杳之若日，偏为滕兔，追形逐影，光若仿佛，呼吸结束，不及法禁，纵横顺逆，直复不闻，斯逆者，一人当百，百人当万。&#8221;这是讲的剑法，不是拳法。不过其中道理，却是一致的。中原逐鹿的历史，到了越女的时代，已有千年。杀人的技术，古往今来并无不同。

明代的大将戚继光，带领着戚家军长年征战，深通兵法武艺。他写了一本书，叫做《纪效新书》，记录作战的方法。其中有一章讲的是拳法，放在了全书最末的位置。书中说，&#8220;拳法似无预于大战之技，然活动手足，惯勤肢体，此为初学入艺之门也。&#8221;作为带兵打仗的将领，戚继光十分清楚拳法的有限用途，充其量也就是强身健体。这也很容易理解，用兵器杀人容易。用拳头打虎是英雄，用刀箭杀老虎就是普通猎户了。现代战场上，也是一样。什么硬功，什么徒手碎砖之类，古人都看不上眼，今人更不必念念不忘。

明白了武术是杀人术，就能明白传统武术和现代竞技武术的区别。后者有规则，前者没有。后者的目标是得分取胜，前者则是生死存亡。很多自由搏击的爱好者，也许大多是叶公，都不太明白规则的重要，动不动就以MMA（Mixed Martial Arts）比赛里没有见到中国武术为理由妄自菲薄。其实大可不必。MMA规则虽然少，但都是一些很重要的限制，其目的是保护运动员不受严重伤害。很明显，这和传统武术的本质是背道而驰的。在MMA比赛中胜出，不见得就比对手更懂得武术。

我们可以看看YouTube上可以看到的两场经典比赛。比赛双方一边是柔道高手吉田秀彦（Hidehiko Yoshida），一方是巴西格雷西柔术高手罗伊斯格雷西（Royce Gracie）。第一场中，双方约定的规则和柔道比赛接近。比如，双方不得拳打脚踢，只能摔、拿，而且双方必须穿着柔道服。这场比赛中吉田秀彦占有明显优势。最后吉田秀彦将胸口压在格雷西头上，使得裁判认定格雷西因窒息而失去知觉而终止了比赛。在第二场比赛中，双方约定的规则更接近UFC的规则，允许拳打脚踢，而且不必穿着柔道服。双方都戴着拳套，吉田秀彦仍然身着道服，而格雷西则赤着上身。开场不久，吉田秀彦被踢中档部，使比赛一度中断。比赛重新开始后不久，格雷西开始占了绝对上风，吉田秀彦只能趴在地上，抱成一团，毫无反击之力。但由于规定的10分钟内格雷西未能让吉田认输或失去知觉，最后只能以和局做罢。


在这两场比赛中，可以看出几件很有意思的事。首先，在第一场比赛中，吉田秀彦之所以能让对方窒息，很大程度上是由于自己身上厚重的柔道服可以盖住对方的口鼻。如果没有上衣，这个动作就有相当的难度。如果没有规则限制，还得担心对手是否会用牙齿。第二，由于现代柔道比赛中取消了当身技（即拳打脚踢），吉田秀彦明显对自己的要害部位疏于保护而在第二场比赛开始就受伤。如果没有规则保护，吉田已经输了。第三，在第二场中可以看到吉田秀彦多次抓住对方的裤脚不放。这是由于柔道技术中很多都依靠抓衣服来控制对手。在正常的柔道比赛中，我们可以经常看到对方互相抓住对方的衣领、袖子、腰带等处。在这场比赛中格雷西没有上衣，所以吉田秀彦只能抓裤脚了。格雷西没穿上衣是聪明的，但不知道他是否后悔没有干脆只穿短裤。最后，当吉田秀彦处于下风时，摆出一个乌龟式，双手抱头，缩成一团。这时，如果没有规则限制，对方可以用脚踩踏其后脑、后腰，或用手肘向下重击后脑或脊柱，这样吉田不死也得受重伤。只可惜这些都是规则所禁止的，所以格雷西基本上是干瞪眼，只能骑在对方身上用拳打击对方头部侧面和肋部，虽然占尽上风却无法赢得比赛。

虽然这两场比赛只是个例，但是如果不带偏见的话，还可应该看得出，无论是柔道、巴西柔术、MMA，还是其它什么比赛，规则就是一切，规则决定技术。为什么在美国UFC比赛中巴西柔术横行？理由其实很简单，就是UFC规则上偏向格雷西家族的巴西柔术。UFC规则虽然少，也有31种犯规动作。有人可能以为既然是MMA，那么其它竞技武术比赛中可以用的招这里都可以用。这就大错特错。比如说，UFC禁止用肘尖向下打击的动作，这在泰拳里是很常见的。UFC也禁止把对手举起来之后头向下砸，这在职业摔角中是允许的。UFC还禁止抓短裤和拳套，而抓衣服在柔道、摔跤比赛中都是允许的。

至于和没有规则的传统武术相比，UFC的限制就更多了。有的人不理解，说难道传统武术练的都是插眼踢档？从某种意义上说，还真是这样。因为武术就是杀人术、伤人术。最有效的伤害对方的方式，自然就是最好的技术。古人有歌决说：&#8220;上打咽喉下打阴，左右两肋并中心，上鼻下臁并封眼，脑后一击要人魂&#8221;。一共八个要害之处，其中五个在我所知的所有竞技比赛中都是禁招。现在能够大范围公开教学的武术，都是我称为&#8220;表演武术&#8221;或&#8220;健身武术&#8221;的东西，自然把很多危险的招式去掉或改变了。尽管如此，这些表演武术和健身武术还是很难摆脱传统武术的本质。

二十四式简化太极拳，应该算得上是普及最广、习者最众的健身武术了。起式之后的第一式是野马分鬃，就是先双手在身前作抱球状，右手上左手下，然后左脚向左开步，重心向左移的同时身体向左转，同时右手向下移至胯旁，左手向上挥出大概齐胸高。既没有插眼，也没有踢档，但是还是很危险。且看其用法的一种：敌右拳向我头部或胸部打来，我起右手格挡，小臂外侧与敌右手外侧相接。我随即向右转身，右手顺势控制住敌右手腕部，同时上左步，左手置于右手下、胸腹前（这是抱球）。这时我左腿、左胯在敌后方。我右手顺敌势向下拉扯敌右手，左手由敌右肋下向敌头面穿出，同时迅速向左转身将对方摔出。这招若使得好了，对方必然后脑着地，非死即伤。

这招不光太极拳有，其它很多流派的拳术都有，算得上是很常见了。但在UFC里面就不好用。为什么呢？当我用右手拉扯敌右手时，很难不抓到对方拳套，犯规。左手向上穿出时，隐含着攻击对方咽喉，又是犯规。把对方摔出时如让对方后脑着地，是犯规。如果不让对方后脑着地，地上是软的，没效果，如果没有后继招式，用了也白用。但对方倒地之后又不能踩踏，要继续进攻，只能做地面缠斗，于是善于地面缠斗巴西柔术就出场了。

古代的杀人术，到了现代应该怎么办？这是很多人都考虑过的问题。对于柔道创始人嘉纳治五郎来说，解决的方法，是把武术变成体育，把搏斗变成竞技。现代泰拳、跆拳道，以及中国的散打，走的都是这条路。而另一种方法，是把武术变成体操表演。中国的各种所谓武术比赛，大都是走的这条路。也有人把武术变成健身操，比如二十四式太极拳，各种武术健身操，甚至瑜伽，都是走的这条路。还有一种思路，就是把杀人术变成防身自卫术，叶问传授的咏春拳，走的就是这条路。当然，依照传统的教法和练法来传授传统武术的人也不在少数。

无论如何，传统武术在现代社会作用有限，对于大多数人只是强身健体，少数人可能借此自卫防身、或是制服凶徒。竞技武术和表演武术有其特有的价值，也将会存在下去。认为某某武术不如某某武术，只是井底之见罢了。

==== 参考资料 ====


纪效新书
http://zh.wikisource.org/wiki/%E7%B4%80%E6%95%88%E6%96%B0%E6%9B%B8



吉田秀彦对罗伊斯格雷西第一战：
http://www.youtube.com/watch?v=vql9nuYgZ8s

吉田秀彦对罗伊斯格雷西第二战：
http://www.youtube.com/watch?v=rGFsgmMaQ4I
http://www.youtube.com/watch?v=oEZowJURuJQ


UFC规则中的禁招
http://en.wikipedia.org/wiki/Ultimate_Fighting_Championship#Fouls


]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: mceinline;">所谓&ldquo;武&rdquo;，从止从戈。从字面上看，一般人都会以为止戈就是停止争战的意思。不过恰恰相反，这里的&ldquo;止戈&rdquo;，是举</span><span style="font-family: mceinline;">戈行进</span><span style="font-family: mceinline;">的形象，准备战斗的意思。所谓&ldquo;术&rdquo;，就是技艺、方法的意思。所以合起来，&ldquo;武术&rdquo;，含蓄地说，就是战斗的方法，直接一点，就是冷兵器时代的杀人术。对敌人的身体有效地实施伤害，这是传统武术的本质。明白了这一点，才能对传统武术有一个正确的认识，中国和外国的都一样。这和现代的体育竞技武术、表演武术、健身武术等等有着很大的区别。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">说到中国武术，很多人就会想到少林拳、太极拳之类。其实，通常所说&ldquo;拳法&rdquo;，或者说徒手搏击的技术，在中国古代大概是摆不上台面的。我所知道最早的关于武术的描写，是&ldquo;越女剑&rdquo;的故事。金庸先生固然妙笔生花，《吴越春秋》中的文言读起来已让人拍案叫绝。越女论道：&ldquo;凡手战之道，内实精神，外示安逸，见之似好妇，夺之似惧虎，布形气候，与神俱往，杳之若日，偏为滕兔，追形逐影，光若仿佛，呼吸结束，不及法禁，纵横顺逆，直复不闻，斯逆者，一人当百，百人当万。&rdquo;这是讲的剑法，不是拳法。不过其中道理，却是一致的。中原逐鹿的历史，到了越女的时代，已有千年。杀人的技术，古往今来并无不同。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">明代的大将戚继光，带领着戚家军长年征战，深通兵法武艺。他写了一本书，叫做《纪效新书》，记录作战的方法。其中有一章讲的是拳法，放在了全书最末的位置。书中说，&ldquo;拳法似无预于大战之技，然活动手足，惯勤肢体，此为初学入艺之门也。&rdquo;作为带兵打仗的将领，戚继光十分清楚拳法的有限用途，充其量也就是强身健体。这也很容易理解，用兵器杀人容易。用拳头打虎是英雄，用刀箭杀老虎就是普通猎户了。现代战场上，也是一样。什么硬功，什么徒手碎砖之类，古人都看不上眼，今人更不必念念不忘。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">明白了武术是杀人术，就能明白传统武术和现代竞技武术的区别。后者有规则，前者没有。后者的目标是得分取胜，前者则是生死存亡。很多自由搏击的爱好者，也许大多是叶公，都不太明白规则的重要，动不动就以MMA（Mixed Martial Arts）比赛里没有见到中国武术为理由妄自菲薄。其实大可不必。MMA规则虽然少，但都是一些很重要的限制，其目的是保护运动员不受严重伤害。很明显，这和传统武术的本质是背道而驰的。在MMA比赛中胜出，不见得就比对手更懂得武术。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">我们可以看看YouTube上可以看到的两场经典比赛。比赛双方一边是柔道高手吉田秀彦（Hidehiko Yoshida），一方是巴西格雷西柔术高手罗伊斯格雷西（Royce Gracie）。第一场中，双方约定的规则和柔道比赛接近。比如，双方不得拳打脚踢，只能摔、拿，而且双方必须穿着柔道服。这场比赛中吉田秀彦占有明显优势。最后吉田秀彦将胸口压在格雷西头上，使得裁判认定格雷西因窒息而失去知觉而终止了比赛。在第二场比赛中，双方约定的规则更接近UFC的规则，允许拳打脚踢，而且不必穿着柔道服。双方都戴着拳套，吉田秀彦仍然身着道服，而格雷西则赤着上身。开场不久，吉田秀彦被踢中档部，使比赛一度中断。比赛重新开始后不久，格雷西开始占了绝对上风，吉田秀彦只能趴在地上，抱成一团，毫无反击之力。但由于规定的10分钟内格雷西未能让吉田认输或失去知觉，最后只能以和局做罢。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<div>
<p><span style="font-family: mceinline;">在这两场比赛中，可以看出几件很有意思的事。首先，在第一场比赛中，吉田秀彦之所以能让对方窒息，很大程度上是由于自己身上厚重的柔道服可以盖住对方的口鼻。如果没有上衣，这个动作就有相当的难度。如果没有规则限制，还得担心对手是否会用牙齿。第二，由于现代柔道比赛中取消了当身技（即拳打脚踢），吉田秀彦明显对自己的要害部位疏于保护而在第二场比赛开始就受伤。如果没有规则保护，吉田已经输了。第三，在第二场中可以看到吉田秀彦多次抓住对方的裤脚不放。这是由于柔道技术中很多都依靠抓衣服来控制对手。在正常的柔道比赛中，我们可以经常看到对方互相抓住对方的衣领、袖子、腰带等处。在这场比赛中格雷西没有上衣，所以吉田秀彦只能抓裤脚了。格雷西没穿上衣是聪明的，但不知道他是否后悔没有干脆只穿短裤。最后，当吉田秀彦处于下风时，摆出一个乌龟式，双手抱头，缩成一团。这时，如果没有规则限制，对方可以用脚踩踏其后脑、后腰，或用手肘向下重击后脑或脊柱，这样吉田不死也得受重伤。只可惜这些都是规则所禁止的，所以格雷西基本上是干瞪眼，只能骑在对方身上用拳打击对方头部侧面和肋部，虽然占尽上风却无法赢得比赛。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">虽然这两场比赛只是个例，但是如果不带偏见的话，还可应该看得出，无论是柔道、巴西柔术、MMA，还是其它什么比赛，规则就是一切，规则决定技术。为什么在美国UFC比赛中巴西柔术横行？理由其实很简单，就是UFC规则上偏向格雷西家族的巴西柔术。UFC规则虽然少，也有31种犯规动作。有人可能以为既然是MMA，那么其它竞技武术比赛中可以用的招这里都可以用。这就大错特错。比如说，UFC禁止用肘尖向下打击的动作，这在泰拳里是很常见的。UFC也禁止把对手举起来之后头向下砸，这在职业摔角中是允许的。UFC还禁止抓短裤和拳套，而抓衣服在柔道、摔跤比赛中都是允许的。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">至于和没有规则的传统武术相比，UFC的限制就更多了。有的人不理解，说难道传统武术练的都是插眼踢档？从某种意义上说，还真是这样。因为武术就是杀人术、伤人术。最有效的伤害对方的方式，自然就是最好的技术。古人有歌决说：&ldquo;上打咽喉下打阴，左右两肋并中心，上鼻下臁并封眼，脑后一击要人魂&rdquo;。一共八个要害之处，其中五个在我所知的所有竞技比赛中都是禁招。现在能够大范围公开教学的武术，都是我称为&ldquo;表演武术&rdquo;或&ldquo;健身武术&rdquo;的东西，自然把很多危险的招式去掉或改变了。尽管如此，这些表演武术和健身武术还是很难摆脱传统武术的本质。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">二十四式简化太极拳，应该算得上是普及最广、习者最众的健身武术了。起式之后的第一式是野马分鬃，就是先双手在身前作抱球状，右手上左手下，然后左脚向左开步，重心向左移的同时身体向左转，同时右手向下移至胯旁，左手向上挥出大概齐胸高。既没有插眼，也没有踢档，但是还是很危险。且看其用法的一种：敌右拳向我头部或胸部打来，我起右手格挡，小臂外侧与敌右手外侧相接。我随即向右转身，右手顺势控制住敌右手腕部，同时上左步，左手置于右手下、胸腹前（这是抱球）。这时我左腿、左胯在敌后方。我右手顺敌势向下拉扯敌右手，左手由敌右肋下向敌头面穿出，同时迅速向左转身将对方摔出。这招若使得好了，对方必然后脑着地，非死即伤。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">这招不光太极拳有，其它很多流派的拳术都有，算得上是很常见了。但在UFC里面就不好用。为什么呢？当我用右手拉扯敌右手时，很难不抓到对方拳套，犯规。左手向上穿出时，隐含着攻击对方咽喉，又是犯规。把对方摔出时如让对方后脑着地，是犯规。如果不让对方后脑着地，地上是软的，没效果，如果没有后继招式，用了也白用。但对方倒地之后又不能踩踏，要继续进攻，只能做地面缠斗，于是善于地面缠斗巴西柔术就出场了。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">古代的杀人术，到了现代应该怎么办？这是很多人都考虑过的问题。对于柔道创始人嘉纳治五郎来说，解决的方法，是把武术变成体育，把搏斗变成竞技。现代泰拳、跆拳道，以及中国的散打，走的都是这条路。而另一种方法，是把武术变成体操表演。中国的各种所谓武术比赛，大都是走的这条路。也有人把武术变成健身操，比如二十四式太极拳，各种武术健身操，甚至瑜伽，都是走的这条路。还有一种思路，就是把杀人术变成防身自卫术，叶问传授的咏春拳，走的就是这条路。当然，依照传统的教法和练法来传授传统武术的人也不在少数。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">无论如何，传统武术在现代社会作用有限，对于大多数人只是强身健体，少数人可能借此自卫防身、或是制服凶徒。竞技武术和表演武术有其特有的价值，也将会存在下去。认为某某武术不如某某武术，只是井底之见罢了。</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<p><span style="font-family: mceinline;">==== 参考资料 ====</span></p>
<p><span style="font-family: mceinline;"><br /></span></p>
<div>
<p><span style="font-family: mceinline;">纪效新书</span></p>
<p><a href="http://zh.wikisource.org/wiki/%E7%B4%80%E6%95%88%E6%96%B0%E6%9B%B8" target="_blank"><span style="color: #000000;"><span style="font-family: mceinline;">http://zh.wikisource.org/wiki/%E7%B4%80%E6%95%88%E6%96%B0%E6%9B%B8</span></span></a></p>
<p><span style="color: #000000;"><span style="font-family: mceinline;"><br /></span></span></p>
</div>
<div>
<p><span style="font-family: mceinline;">吉田秀彦对罗伊斯格雷西第一战：</span></p>
<p><a href="http://www.youtube.com/watch?v=vql9nuYgZ8s" target="_blank"><span style="color: #000000;"><span style="font-family: mceinline;">http://www.youtube.com/watch?v=vql9nuYgZ8s</span></span></a></p>
<p><span style="color: #000000;"><span style="font-family: mceinline;"><br /></span></span></p>
<p><span style="font-family: mceinline;">吉田秀彦对罗伊斯格雷西第二战：</span></p>
<p><a href="http://www.youtube.com/watch?v=rGFsgmMaQ4I" target="_blank"><span style="color: #000000;"><span style="font-family: mceinline;">http://www.youtube.com/watch?v=rGFsgmMaQ4I</span></span></a></p>
<p><a href="http://www.youtube.com/watch?v=oEZowJURuJQ" target="_blank"><span style="color: #000000;"><span style="font-family: mceinline;">http://www.youtube.com/watch?v=oEZowJURuJQ</span></span></a></p>
<p><span style="color: #000000;"><span style="font-family: mceinline;"><br /></span></span></p>
</div>
<p><span style="font-family: mceinline;">UFC规则中的禁招</span></p>
<p><a href="http://en.wikipedia.org/wiki/Ultimate_Fighting_Championship#Fouls" target="_blank"><span style="color: #000000;"><span style="font-family: mceinline;">http://en.wikipedia.org/wiki/Ultimate_Fighting_Championship#Fouls</span></span></a></p>
<p><span style="color: #000000;"><br /></span></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/6687/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The C Book － 第一章 C语言概述 (4)</title>
		<link>http://xysblogs.org/eng/archives/6156</link>
		<comments>http://xysblogs.org/eng/archives/6156#comments</comments>
		<pubDate>Mon, 12 Oct 2009 02:54:30 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>编程</category>

		<category>翻译</category>

		<category>The_C_Book</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/6156</guid>
		<description><![CDATA[1.3.5. 字符串
在C语言中，字符串就是一系列放在一对双引号之间的字符：
&#8220;就像这样&#8221;
由于一个字符串就是一个单独的元素，就像同标志符一样，所以一个字符串只能写在一行上－－尽管字符内部可以包含空格或制表符。
&#8220;这是一个 有效的 字符串&#8221;&#8220;这里有一个换行符所以是无效的字符串&#8221;
有两种方法可以写出一个很长的字符串。在C语言中，无论在什么地方，反斜杠加换行符这样的序列会完全消失不见，所以我们可以利用这一点。
&#8220;这样原本是不可以的 \但对于编译器来说这个换行符不存在&#8221;
另一个方法，就是利用字符串连接的功能。也就是说，两个相邻的字符串会被当成一个字符串。
&#8220;所有这些&#8221; &#8220;都会成为&#8221;&#8220;一个字符串&#8221;
现在回头看看这个例子。这个序列中的 \n 是一个所谓换码序列，在这里，这个序列代表了换行符。printf 函数把这个字符串的内容打印到程序的输出文件中，所以我们看到输出的是 hello，然后再是新的一行。
有的人所使用的编程环境使用了比美国的ASCII字符集更&#8220;宽&#8221;的字符，比如中国大陆使用的GB2312（译注1.3）。为了对这些程序员提供支持，C语言标准允许在字符串和注释中使用多字节字符。C语言标准规定了C语言所用的96个字符（参见第二章）。如果你的系统可以支持扩展字符集，你只能在字符串、字符常量、注释以及头文件的文件名中使用这些扩展字符。对于扩展字符集如何支持是取决于编译系统的，因此你得去查看你的系统说明文档。
1.3.6. main 函数
在例1.1中实际上有两个函数，即 show_message 和 main 函数。尽管 main 函数比 show_message 函数长那么一点，但很明显它俩长得一样：它们都有名字，然后是小括号()，然后是一个复合语句开头的左花括号&#8220;{&#8221;。没错，这之后还有好些东西，不过在最后你可以找到一个右花括号&#8220;}&#8221;和前面的左花括号相对应。
这个函数就实际多了，因为在函数体里有好几个语句，而不是只有一个。你也许已经注意到了，这个函数没有被声明为 void。这当然是有原因的：这个函数返回一个值。现在不用理会这个函数的参数。这些会在第十章中讲到。
关于 main 函数，最重要的一点就是，这是第一个被调用的函数。在主机环境中，当程序开始运行时，你的C语言系统会神奇地安排调用一个叫做 main 的函数（这也就是这个函数叫做 main 的原因）。这个函数结束运行时，整个程序也就结束了。很显然这是一个重要的函数。同样重要的，就是 main 函数下复合语句里面的内容。如前所述，一个复合语句中可以有好几个语句。那么就让我们一一道来。
1.3.7. 声明
第一个语句是这样的：
int count;
它不做任何事，只不过在程序中引入了一个变量。这个语句声明了一样东西，名字叫做 count，其类型为&#8220;整数&#8221;。在C语言中，用来声明整数的关键词碰巧被缩写成了&#8220;int&#8221;。C语言对于这些关键词有种特别的处理方式，有些被完整地拼写出来，有些则像 int 一样被缩写了。至少 int 还有或多或少不言自明的含义，到了后面讲 static 的时候好戏才真正登场呢。
由于有了这个声明，编译器就知道了，这里有一件东西要用来存放整数，而且它的名字是 count。在C语言中，所有的变量都必须先声明过后再能使用，而不存在像FORTRAN里那样的隐性声明。在复合语句中，所有的声明必须都放在最前面。这些声明必须在所有&#8220;正常&#8221;的语句之前，这就使得它们比较特别。
（喜欢钻牛角尖的人：如果你非得要问的话，这里对 count 这样变量的声明同时也是对它的定义。在后面我们才会看到两者的实际区别。）
&#160;
1.3.8 赋值语句
顺着例子往下看，我们可以找到一个赋值语句，与声明很相似。在这里，那个 count 变量第一次被赋值。在这里，被赋与的值是一个常数，其数值为0。在这个赋值语句之前，count 这个变量的值是没有定义、不可预知的。你也许会觉得奇怪，这个赋值符号（准确地说是赋值运算符）是一个等于号＝。这在现代编程语言中是不时髦的（译注1.4），不过这只是白玉微瑕。
到现在为止，我们已经声明了一个变量，并把数值0赋给了它。接下来呢？
1.3.9 while语句
接下来是while语句。这是C语言的循环控制语句之一。好好看看它的形式吧。while语句的正式描述是这样的：
&#160;&#160;&#160; while(expression) &#160;&#160;&#160;&#160;&#160;&#160;&#160; statement
我们的while语句是这样的吗？正是如此。下面的这个表达式
&#160;&#160;&#160; count &#60; 10
是一个关系表达式。这是一个有效的表达式。而这个表达式之后跟着一个复合语句，这就形成了一个有效的语句。这样就满足了构成while语句的条件。
这个语句做的事情对于任何写过程序的人来说都是很明显的。只要 count &#60; 10 [...]]]></description>
			<content:encoded><![CDATA[<h3>1.3.5. 字符串</h3>
<p>在C语言中，字符串就是一系列放在一对双引号之间的字符：</p>
<p>&#8220;就像这样&#8221;</p>
<p>由于一个字符串就是一个单独的元素，就像同标志符一样，所以一个字符串只能写在一行上－－尽管字符内部可以包含空格或制表符。</p>
<p>&#8220;这是一个 有效的 字符串&#8221;<br />&#8220;这里有一个换行符<br />所以是无效的字符串&#8221;</p>
<p>有两种方法可以写出一个很长的字符串。在C语言中，无论在什么地方，反斜杠加换行符这样的序列会完全消失不见，所以我们可以利用这一点。</p>
<p>&#8220;这样原本是不可以的 \<br />但对于编译器来说这个换行符不存在&#8221;</p>
<p>另一个方法，就是利用字符串连接的功能。也就是说，两个相邻的字符串会被当成一个字符串。</p>
<p>&#8220;所有这些&#8221; &#8220;都会成为&#8221;<br />&#8220;一个字符串&#8221;</p>
<p>现在回头看看这个例子。这个序列中的 \n 是一个所谓换码序列，在这里，这个序列代表了换行符。printf 函数把这个字符串的内容打印到程序的输出文件中，所以我们看到输出的是 hello，然后再是新的一行。</p>
<p>有的人所使用的编程环境使用了比美国的ASCII字符集更&ldquo;宽&rdquo;的字符，比如中国大陆使用的GB2312（译注1.3）。为了对这些程序员提供支持，C语言标准允许在字符串和注释中使用多字节字符。C语言标准规定了C语言所用的96个字符（参见第二章）。如果你的系统可以支持扩展字符集，你只能在字符串、字符常量、注释以及头文件的文件名中使用这些扩展字符。对于扩展字符集如何支持是取决于编译系统的，因此你得去查看你的系统说明文档。</p>
<h3>1.3.6. main 函数</h3>
<p>在例1.1中实际上有两个函数，即 show_message 和 main 函数。尽管 main 函数比 show_message 函数长那么一点，但很明显它俩长得一样：它们都有名字，然后是小括号()，然后是一个复合语句开头的左花括号&ldquo;{&rdquo;。没错，这之后还有好些东西，不过在最后你可以找到一个右花括号&ldquo;}&rdquo;和前面的左花括号相对应。</p>
<p>这个函数就实际多了，因为在函数体里有好几个语句，而不是只有一个。你也许已经注意到了，这个函数没有被声明为 void。这当然是有原因的：这个函数返回一个值。现在不用理会这个函数的参数。这些会在第十章中讲到。</p>
<p>关于 main 函数，最重要的一点就是，这是第一个被调用的函数。在主机环境中，当程序开始运行时，你的C语言系统会神奇地安排调用一个叫做 main 的函数（这也就是这个函数叫做 main 的原因）。这个函数结束运行时，整个程序也就结束了。很显然这是一个重要的函数。同样重要的，就是 main 函数下复合语句里面的内容。如前所述，一个复合语句中可以有好几个语句。那么就让我们一一道来。</p>
<h3>1.3.7. 声明</h3>
<p>第一个语句是这样的：</p>
<p>int count;</p>
<p>它不做任何事，只不过在程序中引入了一个变量。这个语句声明了一样东西，名字叫做 count，其类型为&ldquo;整数&rdquo;。在C语言中，用来声明整数的关键词碰巧被缩写成了&ldquo;int&rdquo;。C语言对于这些关键词有种特别的处理方式，有些被完整地拼写出来，有些则像 int 一样被缩写了。至少 int 还有或多或少不言自明的含义，到了后面讲 static 的时候好戏才真正登场呢。</p>
<p>由于有了这个声明，编译器就知道了，这里有一件东西要用来存放整数，而且它的名字是 count。在C语言中，所有的变量都必须先声明过后再能使用，而不存在像FORTRAN里那样的隐性声明。在复合语句中，所有的声明必须都放在最前面。这些声明必须在所有&ldquo;正常&rdquo;的语句之前，这就使得它们比较特别。</p>
<p>（喜欢钻牛角尖的人：如果你非得要问的话，这里对 count 这样变量的声明同时也是对它的定义。在后面我们才会看到两者的实际区别。）</p>
<p>&nbsp;</p>
<h3>1.3.8 赋值语句</h3>
<p>顺着例子往下看，我们可以找到一个赋值语句，与声明很相似。在这里，那个 count 变量第一次被赋值。在这里，被赋与的值是一个常数，其数值为0。在这个赋值语句之前，count 这个变量的值是没有定义、不可预知的。你也许会觉得奇怪，这个赋值符号（准确地说是赋值运算符）是一个等于号＝。这在现代编程语言中是不时髦的（译注1.4），不过这只是白玉微瑕。</p>
<p>到现在为止，我们已经声明了一个变量，并把数值0赋给了它。接下来呢？</p>
<h3>1.3.9 while语句</h3>
<p>接下来是while语句。这是C语言的循环控制语句之一。好好看看它的形式吧。while语句的正式描述是这样的：</p>
<p>&nbsp;&nbsp;&nbsp; while(expression) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; statement</p>
<p>我们的while语句是这样的吗？正是如此。下面的这个表达式</p>
<p>&nbsp;&nbsp;&nbsp; count &lt; 10</p>
<p>是一个关系表达式。这是一个有效的表达式。而这个表达式之后跟着一个复合语句，这就形成了一个有效的语句。这样就满足了构成while语句的条件。</p>
<p>这个语句做的事情对于任何写过程序的人来说都是很明显的。只要 count &lt; 10 这个条件成立，循环体就会被执行，然后又再进行比较。如果想让这个程序能够停下来，那么这个循环体就必需能够最终让这个比较表达式成为&ldquo;假&rdquo;。无疑它能够做到这点。</p>
<p>循环体里只有两个语句。第一个是函数调用语句，调用了show_message这个函数。之所以这是一个函数调用，是因为首先出现了函数名称，然后跟是一对括号（），其包含了函数的参数列表。如果函数不带函数，那么你就不给它参数就行了。如果函数带参数，这些参数就得像下面这样放在括号里：</p>
<p>&nbsp;&nbsp;&nbsp; /* 调用带参数的函数 */ <br />&nbsp;&nbsp;&nbsp; function_name(first_arg, second_arg, third_arg);</p>
<p>调用printf则是另一种形式。这在第四章中有更详细的讲解。</p>
<p>循环体的最后一个语句也是赋值语句。它的作用是把 count 变量加一，最终就能满足程序停止的条件。</p>
<h3>1.3.10 返回（return）语句</h3>
<p>最后我们要讨论的一个语句就是这个返回（return）语句。它看上去就像是一个函数调用语句，但其实它的书写规则是这样的：</p>
<p>&nbsp;&nbsp;&nbsp; return expression;</p>
<p>这里的 expression（表达式） 不是必须的。这个例子采用了一种通常的美观写法，把这个表达式放在了括号里。这其实对程序没有任何影响。</p>
<p>这个返回语句使得当前函数把一个数值返回给调用这个函数的地方。如果这里没有写表达式，那么返回的就可能是任何数值－－这几乎肯定是错的，除非函数本身返回类型是void（空）。和 show_message 函数不同的是，main 函数没有声明为任何类型。那么 main 函数返回什么类型的值呢？答案是 int （整型）。在C语言中，有很多地方可以有默认声明：函数的默认返回类型是 int，所以常常可以看到 main 函数没有返回类型。在这种情况下就相当于把 main 函数声明为：</p>
<p>&nbsp;&nbsp;&nbsp; int main(){</p>
<p>最后的结果是一样的（译注1.5）。</p>
<p>对于变量，则不能用这种方式得到一个默认类型，因为变量类型都必须是明确指定的。</p>
<p>那么，main 函数返回数值是什么意思呢？返回的数值去了哪里呢？在旧版C里，这个返回值回到了操作系统，或是任何其它开始运行这个程序的地方。在类似UNIX的环境下，数值0通常表示某种意义上的&ldquo;成功&rdquo;，其它所有数值（通常是－1）表示&ldquo;失败&rdquo;。标准C把惯例变成了规定，明确指出0代表程序的正确结束。这并不意味着返回到主机系统就是数值0，而是说返回的数值应该是在该系统中代表的&ldquo;成功&rdquo;的数值。由于在这点上通常有一些模糊，你也许会比较喜欢用在 &lt;stdlib.h&gt; 头文件中预定的 EXIT_SUCCESS（成功退出）和 EXIT_FAILURE（失败退出）这两个值来代替。从 main 函数中返回，实际上和调用 exit 库函数并用返回值作参数是一样的。区别在于，exit 库函数可以程序的任何地方调用，而程序就会在那个地方做一些整理工作后停下来。如果你想用 exit 库函数，就必须包含 &lt;stdlib.h&gt; 这个头文件。从现在起，我们将使用 exit，而不是从 main 函数中返回。</p>
<h4>小结</h4>
<p>main 函数返回的是一个 int 值。</p>
<p>从 main 函数返回和调用 exit 函数是一样的，只不过 exit 可以在程序的任何地方调用。</p>
<p>返回 0 或者 EXIT_SUCCESS 代表成功，而其它任何值都代表失败。</p>
<p>&nbsp;</p>
<h3>1.3.11 目前的进展</h3>
<p>这里的范例程序尽管短小，还是让我们了解到了几个重要的程序特性，包括：</p>
<ul>
<li>程序结构</li>
<li>注释文件包含</li>
<li>函数定义</li>
<li>复合语句</li>
<li>函数调用</li>
<li>变量声明</li>
<li>算术运算</li>
<li>循环</li>
</ul>
<p>当然，所有这些都不是很严谨的讲解。</p>
<p>&nbsp;</p>
<hr />
<p>&nbsp;</p>
<p>译注：</p>
<p>1.1、原文为 implementation defined。这里implementation的意思是具体的C语言编译器、连接程序、装入程序等等。这里译为&ldquo;编译系统&rdquo;。</p>
<p>1.2、在C标准中，严格意义上来讲预处理指令和声明都不是语句（statement），因此这里的&ldquo;语句&rdquo;一词加上了引号，表明是使用了&ldquo;语句&rdquo;一词的非正式用法。下文中的&ldquo;语句&rdquo;一词也都是这种用法。</p>
<p>1.3、原文用了日语编码shift-JIS为例。在这里考虑到读者可能更加熟悉中文编码，特换为GB2312。</p>
<p>1.4、由于C语言的流行，事实上现在非常多&ldquo;时髦&rdquo;的编程语言都沿用了C当中这种用等于号做赋值符号的做法。</p>
<p>1.5、事实上，写程序时最好把main的类型声明明确地写出来。在最新的C标准（C99）要求编译器在 main 返回类型省略时给出警告。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/6156/feed/</wfw:commentRss>
		</item>
		<item>
		<title>读谭师傅的书（15）</title>
		<link>http://xysblogs.org/eng/archives/4893</link>
		<comments>http://xysblogs.org/eng/archives/4893#comments</comments>
		<pubDate>Wed, 27 May 2009 05:31:41 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>读书</category>

		<category>评论</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/4893</guid>
		<description><![CDATA[接着上次的学习。之前在读谭师傅的书时，有的地方跳过去了。现在重新回过头来看看第四章，《最简单的C程序设计－－顺序程序设计》。
第4.1节是《C语句概述》。我们来看看谭师傅的图4.1。

&#160;
&#160;
&#160;
&#160;
在这里我们可以很清楚的看到，这里少了点东西：函数声明。如果一个文件有函数声明，但没有该函数的函数体，则按这个图，这个文件不是C程序。再严格一点，这里还少了注释、typedef的位置。
谭师傅在讲解的时候说，&#8220;一个C程序可以由若干个函数和预处理命令以及全局变量声明部分组成&#8221;。这问题就更大了。如果我有一个 struct foo { int bar; } ，可能还可以勉强算是&#8220;数据声明&#8221;，但决不是全局变量的声明。静态变量的声明也没有包括在里面。
谭师傅接下来把C 语句分为5类，分别是（1）控制语句、（2）函数调用语句、（3）表达式语句、（4）空语句，以及（5）复合语句。这种分类方法和通常使用的分类方法（即 C标准中使用的分类方法）不同，很可能会造成初学者的误解。例如，谭师傅说，if()&#8230;else&#8230;这样语句的小括号里的内容是一个&#8220;判别条件&#8221;。 这个判别条件是个什么东西？它是不是一个语句？谭师傅没有讲。其实，它就是一个表达式，而且对它的返回值有一定要求（必须是scalar type）。按谭师傅的说法，for()&#8230; 的小括号里也是一个&#8220;判定条件&#8221;。这个判定条件是什么东西？它是三个用分号隔开的表达式（或按最新的标准草案，可以是一个声明加两个用分号隔开的表达式）。另外，函数调用也是表达式（这点谭师傅自己也提到了）。空语句其实也是表达式语句，理解了这点才能知道为什么可以写出 for(;;)&#8230; 这样的语句。我不明白谭师傅在搞出这么一个不伦不类的&#8220;分类&#8221;的时候有没有好好读过K&#38;R或者C标准。
第4.3节讲的C语言的输入输出。谭师傅讲了什么是头文件：&#8220;文件后缀中&#8216;h&#8217;是head的缩写，#include命令都是放在程序的开头，因此这类文件都被称为&#8216;头文件&#8217;。&#8221; 这里有点小问题，h应当是header而不是head的缩写。

谭师傅还说，在包含stdio.h的时候，既可以用 #include &#60;stdio.h&#62;，也可以用 #include &#8220;stdio.h&#8221; 的形式，但却没有讲两者的区别。这是初学者比较容易搞混的地方，不该放过。事实上，对于编译系统提供的头文件，用第一种形式比较好。
第4.4节给了几个例子。我们又一次看到谭师傅把字符常量的类型当成了char，把getchar()的返回类型也当成了char。而实际上这两者都是 int。
第4.5节在（12）里已经学习过了，这里就不多说了。
]]></description>
			<content:encoded><![CDATA[<p>接着<a href="/eng/archives/4637">上次</a>的学习。之前在读谭师傅的书时，有的地方跳过去了。现在重新回过头来看看第四章，《最简单的C程序设计－－顺序程序设计》。</p>
<p>第4.1节是《C语句概述》。我们来看看谭师傅的图4.1。</p>
<div id="k0oh" style="text-align: left;"><img id="image4892" src="/wp-content/blogs/41/uploads//figure4-1.png" alt="figure4-1" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>在这里我们可以很清楚的看到，这里少了点东西：函数声明。如果一个文件有函数声明，但没有该函数的函数体，则按这个图，这个文件不是C程序。再严格一点，这里还少了注释、typedef的位置。</p>
<p>谭师傅在讲解的时候说，&ldquo;一个C程序可以由若干个函数和预处理命令以及全局变量声明部分组成&rdquo;。这问题就更大了。如果我有一个 struct foo { int bar; } ，可能还可以勉强算是&ldquo;数据声明&rdquo;，但决不是全局变量的声明。静态变量的声明也没有包括在里面。</p>
<p>谭师傅接下来把C 语句分为5类，分别是（1）控制语句、（2）函数调用语句、（3）表达式语句、（4）空语句，以及（5）复合语句。这种分类方法和通常使用的分类方法（即 C标准中使用的分类方法）不同，很可能会造成初学者的误解。例如，谭师傅说，if()&#8230;else&#8230;这样语句的小括号里的内容是一个&ldquo;判别条件&rdquo;。 这个判别条件是个什么东西？它是不是一个语句？谭师傅没有讲。其实，它就是一个表达式，而且对它的返回值有一定要求（必须是scalar type）。按谭师傅的说法，for()&#8230; 的小括号里也是一个&ldquo;判定条件&rdquo;。这个判定条件是什么东西？它是三个用分号隔开的表达式（或按最新的标准草案，可以是一个声明加两个用分号隔开的表达式）。另外，函数调用也是表达式（这点谭师傅自己也提到了）。空语句其实也是表达式语句，理解了这点才能知道为什么可以写出 for(;;)&#8230; 这样的语句。我不明白谭师傅在搞出这么一个不伦不类的&ldquo;分类&rdquo;的时候有没有好好读过K&amp;R或者C标准。</p>
<p>第4.3节讲的C语言的输入输出。谭师傅讲了什么是头文件：&ldquo;文件后缀中&lsquo;h&rsquo;是head的缩写，#include命令都是放在程序的开头，因此这类文件都被称为&lsquo;头文件&rsquo;。&rdquo; 这里有点小问题，h应当是header而不是head的缩写。</p>
</div>
<p>谭师傅还说，在包含stdio.h的时候，既可以用 #include &lt;stdio.h&gt;，也可以用 #include &#8220;stdio.h&#8221; 的形式，但却没有讲两者的区别。这是初学者比较容易搞混的地方，不该放过。事实上，对于编译系统提供的头文件，用第一种形式比较好。</p>
<p>第4.4节给了几个例子。我们又一次看到谭师傅把字符常量的类型当成了char，把getchar()的返回类型也当成了char。而实际上这两者都是 int。</p>
<p>第4.5节在（12）里已经学习过了，这里就不多说了。</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/4893/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The C Book － 第一章 C语言概述 (3)</title>
		<link>http://xysblogs.org/eng/archives/4866</link>
		<comments>http://xysblogs.org/eng/archives/4866#comments</comments>
		<pubDate>Fri, 22 May 2009 09:29:59 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>编程</category>

		<category>翻译</category>

		<category>The_C_Book</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/4866</guid>
		<description><![CDATA[1.3.4 函数的声明和定义
1.3.4.1 声明
在 &#60;stdio.h&#62; 文件被包含之后，就是一个函数声明。这个声明告诉编译器，show_message 是一个函数，不带任何参数，也不返回任何值。这就是新的C标准所做的改动之一，所谓函数原型。我们在第四章里还要再详细讲解。尽管不是在所有情况下都需要预先声明函数－－如果没有声明的话C就会使用一些旧的默认规则－－在新标准下，你最好还是要对函数预先声明。声明和定义的区别在于，前者只是描述函数的类型以及它所带的参数，而后者则给出了函数体。这些术语在后面会变得更为重要。
由 于我们在使用 show_message 之前就预先对它进行了声明，这样编译器就可以检查它是否被正确使用。这个函数声明描述了关于函数的三个重要信息：名称、类型以及参数的个数和类型。在这 里，void show_message( 这一部分表明它是一个函数，并且返回一个类型为 void 的值。这个类型我们待会就要讲到。这个 void 的第二个用途，就是用在声明函数参数列表里，(void)，表示函数不带任何参数。
1.3.4.2 定义
在程序的最后，就是函数的定义了。尽管只有三行，它也是一个完整的函数。
在 C语言里，函数所做的事是其它语言中需要用两部分来做的。大部分编程语言都用函数来返回某种值，典型的例子就是三角函数sin和cos，或者平方根函数。 C语言在这方面也是一样的。其它的一些类似的事情是由一些看上去很像函数的东西来做的，只不过不返回值。FORTRAN语言用子程序（subroutine），Pascal 和 Algo 语言则称之为过程（procedure）。而C语言只是用函数来做这两种事情，并在函数定义中规定函数返回值的类型。在这个例子中，show_message 函数不返回值，所以我们把它的类型设为 void （空）。
在 这里 void 的用法，既可能无比直观，也可能暗藏玄机。这得取决于你看问题的角度。我们其实可以在这里岔开一笔，别开生面（但毫无结果）地从哲学的高度讨论一下 void 究竟是不是个值。不过还是就此打住了。不管你喜欢哪一种回答，很明显你不能拿 void 来做任何事，这也就是它的意义之所在－－&#8220;这个函数返回值也好，不返回也罢，我不想拿返回的东西做任何事&#8221;。
这个函数的类型是 void，它的名称是 show_message。函数名后紧跟着的小括号 () 用来让编译器知道，这里我们讲的是函数而不是别的什么东西。如果函数带参数，那么这些参数就会出现在小括号之间。这个函数不带参数，所以我们特地在小括号 中间放了一个 void 来表明这一点。
如果一样东西的本质是空的、要放弃的或是被拒绝的，那么 void 在这种情况下是很有用的。
这个函数的函数体是一个复合语句，也就是一系列被花括号 {} 括起来的语句。括号里面其实只有一个语句，但这里的括号还是必要的。一般来说，C语言允许你把一个复合语句放到任何可以放单个简单语句的地方，而花括号的作用就是把几个连着的语句组合起来，让它们实际上成为一个语句。
值得一问的是，如果这里花括号的作用仅仅是把几个语句合成一个，而这个函数体里本来就只有一个语句，那么这里的花括号是不是一定必要呢？奇怪的是，答案为是－－这里的花括号的确是必要的。在C语言里，仅有的一种场合必须用复合语句而不能用单个语句，那就是在定义函数时候。自然，最简单的函数就是什么也不做的空函数：
void do_nothing(void){}
在 show_message 函数里的那个语句，调用了库函数 printf。这个 printf 是用来排版和打印数据用的。这个例子显示了它最简单的用法之一。printf 函数带一个或多个参数，而这些参数的值则在调用函数时被传送到函数中。在这里这个参数是一个字符串。这个字符串的内容由 printf 函数来解释，并依此来控制如何打印其它参数的值。这个字符串参数有点像 FORTRAN 语言里的 FORMAT [...]]]></description>
			<content:encoded><![CDATA[<h3><span style="font-family: Arial;"><a name="chapter1.3.4"></a>1.3.4 函数的声明和定义</span></h3>
<h4>1.3.4.1 声明</h4>
<p>在 &lt;stdio.h&gt; 文件被包含之后，就是一个函数声明。这个声明告诉编译器，show_message 是一个函数，不带任何参数，也不返回任何值。这就是新的C标准所做的改动之一，所谓<em>函数原型</em>。我们在第四章里还要再详细讲解。尽管不是在所有情况下都需要预先声明函数－－如果没有声明的话C就会使用一些旧的默认规则－－在新标准下，你最好还是<strong>要</strong>对函数预先声明。声明和定义的区别在于，前者只是描述函数的类型以及它所带的参数，而后者则给出了函数体。这些术语在后面会变得更为重要。</p>
<p>由 于我们在使用 show_message 之前就预先对它进行了声明，这样编译器就可以检查它是否被正确使用。这个函数声明描述了关于函数的三个重要信息：名称、类型以及参数的个数和类型。在这 里，void show_message( 这一部分表明它是一个函数，并且返回一个类型为 void 的值。这个类型我们待会就要讲到。这个 void 的第二个用途，就是用在声明函数参数列表里，(void)，表示函数<strong>不</strong>带任何参数。</p>
<h4>1.3.4.2 定义</h4>
<p>在程序的最后，就是函数的定义了。尽管只有三行，它也是一个完整的函数。</p>
<p>在 C语言里，函数所做的事是其它语言中需要用两部分来做的。大部分编程语言都用函数来返回某种值，典型的例子就是三角函数sin和cos，或者平方根函数。 C语言在这方面也是一样的。其它的一些类似的事情是由一些看上去很像函数的东西来做的，只不过不返回值。FORTRAN语言用<em>子程序</em>（subroutine），Pascal 和 Algo 语言则称之为<em>过程</em>（procedure）。而C语言只是用函数来做这两种事情，并在函数定义中规定函数返回值的<strong>类型</strong>。在这个例子中，show_message 函数不返回值，所以我们把它的类型设为 void （空）。</p>
<p>在 这里 void 的用法，既可能无比直观，也可能暗藏玄机。这得取决于你看问题的角度。我们其实可以在这里岔开一笔，别开生面（但毫无结果）地从哲学的高度讨论一下 void 究竟是不是个值。不过还是就此打住了。不管你喜欢哪一种回答，很明显你不能拿 void 来做任何事，这也就是它的意义之所在－－&ldquo;这个函数返回值也好，不返回也罢，我不想拿返回的东西做任何事&rdquo;。</p>
<p>这个函数的类型是 void，它的名称是 show_message。函数名后紧跟着的小括号 () 用来让编译器知道，这里我们讲的是函数而不是别的什么东西。如果函数带参数，那么这些参数就会出现在小括号之间。这个函数不带参数，所以我们特地在小括号 中间放了一个 void 来表明这一点。</p>
<p>如果一样东西的本质是空的、要放弃的或是被拒绝的，那么 void 在这种情况下是很有用的。</p>
<p>这个函数的函数体是一个<em>复合语句</em>，也就是一系列被花括号 {} 括起来的语句。括号里面其实只有一个语句，但这里的括号还是必要的。一般来说，C语言允许你把一个复合语句放到任何可以放单个简单语句的地方，而花括号的作用就是把几个连着的语句组合起来，让它们实际上成为一个语句。</p>
<p>值得一问的是，如果这里花括号的作用仅仅是把几个语句合成一个，而这个函数体里本来就只有一个语句，那么这里的花括号是不是一定必要呢？奇怪的是，答案为是－－这里的花括号<strong>的确</strong>是必要的。在C语言里，仅有的一种场合<strong>必须</strong>用复合语句而不能用单个语句，那就是在定义函数时候。自然，最简单的函数就是什么也不做的空函数：</p>
<pre style="margin-left: 40px;">void do_nothing(void){}</pre>
<p>在 show_message 函数里的那个语句，调用了库函数 printf。这个 printf 是用来排版和打印数据用的。这个例子显示了它最简单的用法之一。printf 函数带一个或多个参数，而这些参数的值则在调用函数时被传送到函数中。在这里这个参数是一个<em>字符串</em>。这个字符串的内容由 printf 函数来解释，并依此来控制如何打印其它参数的值。这个字符串参数有点像 FORTRAN 语言里的 FORMAT 语句，不过还没有到可以闻一知二的程度。</p>
<h4>小结</h4>
<p><em>声明</em>的作用，是描述函数的名称、返回值类型以及参数类型（如果有参数的话）。</p>
<p>函数的<em>定义</em>也是对函数的声明，但同时也给出了函数体。</p>
<p>如果函数不返回值，那么应该把它的返回值类型声明为 void。例如，void func(/* 参数列表 */);</p>
<p>如果函数不带参数，那么应该把它的参数列表声明为 void。例如，void func(void);</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/4866/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The C Book － 第一章 C语言概述 (2)</title>
		<link>http://xysblogs.org/eng/archives/4822</link>
		<comments>http://xysblogs.org/eng/archives/4822#comments</comments>
		<pubDate>Mon, 18 May 2009 03:01:18 +0000</pubDate>
		<dc:creator>eng</dc:creator>
		
		<category>编程</category>

		<category>翻译</category>

		<category>The_C_Book</category>

		<guid isPermaLink="false">http://xysblogs.org/eng/archives/4822</guid>
		<description><![CDATA[第1.3节 例1.1的讲解
1.3.1 里面有什么
即使是这么小的一个程序例子，也包括了不少关于C的内容。不说别的，它首先就包括了两个函数，一个&#8220;#include&#8221;语句，以及一些注释。由于注释是最容易的掌握的，我们就先来看看注释。
1.3.2 排版布局和注释
C语言程序的排版对于编译器来说并不十分重要。但为了让程序易读易懂，你可以利用排版的自由来放入额外的信息。这点是很重要的。C语言可以让你在程序里几乎任何地方放入空格、制表符或换行符而不影响程序的意义。这三种字符对于编译器来说都是一样的，统一称为空白符，因为这些字符仅仅只是改变打印的位置而不会在输出设备上有任何&#8220;可见&#8221;的打印效果。空白符几乎可以放在程序的任何地方，除了标志符、字符串以及字符常量以外。所谓标志符，意思就是函数或其它物件的名称。对于字符串和字符常量，我们以后还会讲到，但现在不必理会它们的含义。
除了特殊情况以外，空白符只是用来把两个可能混淆在一起的东西隔开。在前面的例子中，void show_message 中间就必须要有一个空格来隔开，而 show_message( 可以在小括号 ( 之前放一个空格，也可以不放，这完全是风格问题。
C语言中的注释从 /* 这样两个字符开始。这两个字符之间不能有空格。从那里开始，直到 */ 这两个字符为止，这中间的所有东西都会被吞掉，被一个空格取而代之。在旧版C里，规则有所不同。以前的规则是注释可以出现在空格可以出现的任何地方，而新的规则是注释本身就是空格。这个规则变化并不大，到了第七章，当我们讲到预处理器时才会变得明显。对注释结尾如此规定，其后果之一就是你不能把一个注释放到另一个注释里面，因为第一次出现的 */ 这样两个字符就标志着注释结束了。这有点令人讨厌，不过习惯就好了。
如果注释占了多于一行，通常我们会在每一行前面加上一个星号 *，使它更为醒目，就像例子里显示的那样。
1.3.3 预处理器语句
这个例子里的第一个语句，是一条预处理器指令。在从前，一个C语言编译器分为两个阶段：一个预处理器，然后是真正的编译器。预处理器是一个宏处理器，用来对程序做简单的文本处理，然后其结果才送到编译器进行编译。预处理器很快被认为是编译器的重要组成部分，所以现在它已经被定义为C语言不可或缺的一部分了。
预处理器只知道一行一行的文字，所以对于分行是敏感的。这与C语言其它部分不同。虽然有可能写出一个多行的预处理器指令，这种指令是不常见的，也容易让人看不懂。凡是第一个可见字符为井号＃的程序行，都是预处理器指令。
在例1.1中，&#8220;#include&#8221; 指令使得含有该指令的那一行被另一个文件的内容完全取代。在这里，包括在左右尖括号（&#60;&#62;）之间的，就是那个文件的名字。这是一个很常见的技巧，用来把一个标准头文件里的内容放到你的程序中，而不用费力去把这些内容再重新输入一遍。这个叫做 &#60;stdio.h&#62; 的文件是一个很重要的文件。如果没有它里面所含的信息，就不能用标准函数库做输入或输出。所以，如果你要使用标准输入输出函数，就必须包含这个 &#60;stdio.h&#62; 文件。而旧版的C对此则没有严格要求。
1.3.3.1. Define 语句
预处理器的另一个能力，也是被广泛应用的一个能力，就是它的 #define 语句。它是这样用的：
#define 标志符    替换文本
这个意思就是说，凡是程序中&#8220;标志符&#8221;出现的地方，它都会被后面的替换文本所取代。这里的标志符总是大写字母。这是为了方便读者理解程序的惯用写法。而后面的替换文本可以是任何文本－－要记住预处理器是不懂C的，它只懂文本。这个语句最常见的用法，就是为常数起名字：
#define PI 3.141592#define SECS_PER_MIN 60#define MINS_PER_HOUR 60#define HOURS_PER_DAY 24
然后像这样使用这些常数的名字：
circumf = 2*PI*radius;if(timer &#62;= SECS_PER_MIN){mins = mins+1;timer = timer - SECS_PER_MIN;}
预处理器给出的结果，就好像你写了下面这样的程序一样：
circumf = 2*3.141592*radius;if(timer &#62;= 60){mins = [...]]]></description>
			<content:encoded><![CDATA[<h2><a name="chapter1.3"></a>第1.3节 例1.1的讲解<br /></h2>
<h3><a name="chapter1.3.1"></a>1.3.1 里面有什么<br /></h3>
<p>即使是这么小的一个程序例子，也包括了不少关于C的内容。不说别的，它首先就包括了两个函数，一个&ldquo;#include&rdquo;语句，以及一些注释。由于注释是最容易的掌握的，我们就先来看看注释。</p>
<h3><a name="chapter1.3.2"></a>1.3.2 排版布局和注释<br /></h3>
<p>C语言程序的排版对于编译器来说并不十分重要。但为了让程序易读易懂，你可以利用排版的自由来放入额外的信息。这点是很重要的。C语言可以让你在程序里几乎任何地方放入空格、制表符或换行符而不影响程序的意义。这三种字符对于编译器来说都是一样的，统一称为空白符，因为这些字符仅仅只是改变打印的位置而不会在输出设备上有任何&ldquo;可见&rdquo;的打印效果。空白符几乎可以放在程序的任何地方，除了标志符、字符串以及字符常量以外。所谓标志符，意思就是函数或其它物件的名称。对于字符串和字符常量，我们以后还会讲到，但现在不必理会它们的含义。</p>
<p>除了特殊情况以外，空白符只是用来把两个可能混淆在一起的东西隔开。在前面的例子中，void show_message 中间就必须要有一个空格来隔开，而 <span style="font-family: courier new,courier;">show_message</span>( 可以在小括号 ( 之前放一个空格，也可以不放，这完全是风格问题。</p>
<p>C语言中的注释从 /* 这样两个字符开始。这两个字符之间不能有空格。从那里开始，直到 */ 这两个字符为止，这中间的所有东西都会被吞掉，被一个空格取而代之。在旧版C里，规则有所不同。以前的规则是注释可以出现在空格可以出现的任何地方，而新的规则是注释本身就是空格。这个规则变化并不大，到了第七章，当我们讲到预处理器时才会变得明显。对注释结尾如此规定，其后果之一就是你不能把一个注释放到另一个注释里面，因为<em>第一次</em>出现的 <span style="font-family: Courier New;">*/</span> 这样两个字符就标志着注释结束了。这有点令人讨厌，不过习惯就好了。</p>
<p>如果注释占了多于一行，通常我们会在每一行前面加上一个星号 *，使它更为醒目，就像例子里显示的那样。</p>
<h3><a name="chapter1.3.3"></a>1.3.3 预处理器语句<br /></h3>
<p>这个例子里的第一个语句，是一条预处理器指令。在从前，一个C语言编译器分为两个阶段：一个预处理器，然后是真正的编译器。预处理器是一个宏处理器，用来对程序做简单的文本处理，然后其结果才送到编译器进行编译。预处理器很快被认为是编译器的重要组成部分，所以现在它已经被定义为C语言不可或缺的一部分了。</p>
<p>预处理器只知道一行一行的文字，所以对于分行是敏感的。这与C语言其它部分不同。虽然有可能写出一个多行的预处理器指令，这种指令是不常见的，也容易让人看不懂。凡是第一个可见字符为井号＃的程序行，都是预处理器指令。</p>
<p>在例1.1中，&ldquo;<span style="font-family: courier new,courier;">#include</span>&rdquo; 指令使得含有该指令的那一行被另一个文件的内容完全取代。在这里，包括在左右尖括号（&lt;&gt;）之间的，就是那个文件的名字。这是一个很常见的技巧，用来把一个标准头文件里的内容放到你的程序中，而不用费力去把这些内容再重新输入一遍。这个叫做 <span style="font-family: courier new,courier;">&lt;stdio.h&gt;</span> 的文件是一个很重要的文件。如果没有它里面所含的信息，就不能用标准函数库做输入或输出。所以，如果你要使用标准输入输出函数，就必须包含这个 <span style="font-family: courier new,courier;">&lt;stdio.h&gt;</span> 文件。而旧版的C对此则没有严格要求。</p>
<h4>1.3.3.1. Define 语句<br /></h4>
<p>预处理器的另一个能力，也是被广泛应用的一个能力，就是它的 #define 语句。它是这样用的：</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">#define</span> 标志符    替换文本</p>
<p>这个意思就是说，凡是程序中&ldquo;标志符&rdquo;出现的地方，它都会被后面的替换文本所取代。这里的标志符总是大写字母。这是为了方便读者理解程序的惯用写法。而后面的替换文本可以是任何文本－－要记住预处理器是不懂C的，它只懂文本。这个语句最常见的用法，就是为常数起名字：</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">#define PI 3.141592<br />#define SECS_PER_MIN 60<br />#define MINS_PER_HOUR 60<br />#define HOURS_PER_DAY 24</span></p>
<p>然后像这样使用这些常数的名字：</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">circumf = 2*PI*radius;<br />if(timer &gt;= SECS_PER_MIN){<br />mins = mins+1;<br />timer = timer - SECS_PER_MIN;<br />}</span></p>
<p>预处理器给出的结果，就好像你写了下面这样的程序一样：</p>
<p style="padding-left: 30px;"><span style="font-family: courier new,courier;">circumf = 2*3.141592*radius;<br />if(timer &gt;= 60){<br />mins = mins+1;<br />timer = timer - 60;<br />}</span></p>
<h4>小结</h4>
<p>预处理器语句是一行一行进行处理的，而C语言其它部分则不是。</p>
<p><span style="font-family: courier new,courier;">#include</span> 语句是用来读入某一特定文件的内容的，通常被用来使用库函数。</p>
<p><span style="font-family: courier new,courier;">#define</span> 语句通常被用来给常数起名字。习惯做法是把这样的名字全部用大写字母表示。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://xysblogs.org/eng/archives/4822/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
