-
Notifications
You must be signed in to change notification settings - Fork 25
/
ch06s03.html
20 lines (20 loc) · 8.95 KB
/
ch06s03.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>3. for语句</title><link rel="stylesheet" href="styles.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><link rel="start" href="index.html" title="Linux C编程一站式学习" /><link rel="up" href="ch06.html" title="第 6 章 循环语句" /><link rel="prev" href="ch06s02.html" title="2. do/while语句" /><link rel="next" href="ch06s04.html" title="4. break和continue语句" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. for语句</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch06s02.html">上一页</a> </td><th width="60%" align="center">第 6 章 循环语句</th><td width="20%" align="right"> <a accesskey="n" href="ch06s04.html">下一页</a></td></tr></table><hr /></div><div class="sect1" lang="zh-cn" xml:lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="id2726720"></a>3. for语句</h2></div></div></div><p>前两节我们在<code class="literal">while</code>和<code class="literal">do/while</code>循环中使用循环变量,其实使用循环变量最见的是<code class="literal">for</code>循环这种形式。<code class="literal">for</code>语句的语法是:</p><div class="literallayout"><p>for (控制表达式1; 控制表达式2; 控制表达式3) 语句</p></div><p>如果不考虑循环体中包含<code class="literal">continue</code>语句的情况(稍后介绍<code class="literal">continue</code>语句),这个<code class="literal">for</code>循环等价于下面的<code class="literal">while</code>循环:</p><pre class="programlisting">控制表达式1;
while (控制表达式2) {
语句
控制表达式3;
}</pre><p>从这种等价形式来看,控制表达式1和3都可以为空,但控制表达式2是必不可少的,例如<code class="literal">for (;1;) {...}</code>等价于<code class="literal">while (1) {...}</code>死循环。C语言规定,如果控制表达式2为空,则认为控制表达式2的值为真,因此死循环也可以写成<code class="literal">for (;;) {...}</code>。</p><p>上一节<code class="literal">do/while</code>循环的例子可以改写成<code class="literal">for</code>循环:</p><pre class="programlisting">int factorial(int n)
{
int result = 1;
int i;
for(i = 1; i <= n; ++i)
result = result * i;
return result;
}</pre><p>其中<code class="literal">++i</code>这个表达式相当于<code class="literal">i = i + 1</code><sup>[<a id="id2726856" href="#ftn.id2726856" class="footnote">9</a>]</sup>,++称为前缀自增运算符(Prefix Increment Operator)<a id="id2726869" class="indexterm"></a>,类似地,--称为前缀自减运算符(Prefix Decrement Operator)<a id="id2726877" class="indexterm"></a><sup>[<a id="id2726883" href="#ftn.id2726883" class="footnote">10</a>]</sup>,<code class="literal">--i</code>相当于<code class="literal">i = i - 1</code>。如果把<code class="literal">++i</code>这个表达式看作一个函数调用,除了传入一个参数返回一个值(等于参数值加1)之外,还产生一个Side Effect,就是把变量<code class="literal">i</code>的值增加了1。</p><p><code class="literal">++</code>和<code class="literal">--</code>运算符也可以用在变量后面,例如<code class="literal">i++</code>和<code class="literal">i--</code>,为了和前缀运算符区别,这两个运算符称为后缀自增运算符(Postfix Increment Operator)<a id="id2726952" class="indexterm"></a>和后缀自减运算符(Postfix Decrement Operator)<a id="id2726960" class="indexterm"></a>。如果把<code class="literal">i++</code>这个表达式看作一个函数调用,传入一个参数返回一个值,返回值就等于参数值(而不是参数值加1),此外也产生一个Side Effect,就是把变量<code class="literal">i</code>的值增加了1,它和<code class="literal">++i</code>的区别就在于返回值不同。同理,<code class="literal">--i</code>返回减1之后的值,而<code class="literal">i--</code>返回减1之前的值,但这两个表达式都产生同样的Side Effect,就是把变量<code class="literal">i</code>的值减了1。</p><p>使用++、--运算符会使程序更加简洁,但也会影响程序的可读性,<a class="xref" href="bi01.html#bibli.kr" title="The C Programming Language">[<abbr class="abbrev">K&R</abbr>]</a>中的示例代码大量运用++、--和其它表达式的组合使得代码非常简洁。为了让初学者循序渐进,在接下来的几章中++、--运算符总是单独组成一个表达式而不跟其它表达式组合,从<a class="xref" href="ch11.html#sortsearch">第 11 章 <i>排序与查找</i></a>开始将采用<a class="xref" href="bi01.html#bibli.kr" title="The C Programming Language">[<abbr class="abbrev">K&R</abbr>]</a>的简洁风格。</p><p>我们看一个有意思的问题:<code class="literal">a+++++b</code>这个表达式如何理解?应该理解成<code class="literal">a++ ++ +b</code>还是<code class="literal">a++ + ++b</code>,还是<code class="literal">a + ++ ++b</code>呢?应该按第一种方式理解。编译的过程分为词法解析和语法解析两个阶段,在词法解析阶段,编译器总是从前到后找最长的合法Token。把这个表达式从前到后解析,变量名<code class="literal">a</code>是一个Token,<code class="literal">a</code>后面有两个以上的+号,在C语言中一个+号是合法的Token(可以是加法运算符或正号),两个+号也是合法的Token(可以是自增运算符),根据最长匹配原则,编译器绝不会止步于一个+号,而一定会把两个+号当作一个Token。再往后解析仍然有两个以上的+号,所以又是一个++运算符。再往后解析只剩一个+号了,是加法运算符。再往后解析是变量名<code class="literal">b</code>。词法解析之后进入下一阶段语法解析,<code class="literal">a</code>是一个表达式,表达式++还是表达式,表达式再++还是表达式,表达式再+b还是表达式,语法上没有问题。最后编译器会做一些基本的语义分析,这时就有问题了,++运算符要求操作数能做左值,<code class="literal">a</code>能做左值所以<code class="literal">a++</code>没问题,但表达式<code class="literal">a++</code>的值只能做右值,不能再++了,所以最终编译器会报错。</p><p>C99规定了一种新的<code class="literal">for</code>循环语法,在控制表达式1的位置可以有变量定义。例如上例的循环变量<code class="literal">i</code>可以只在<code class="literal">for</code>循环中定义:</p><pre class="programlisting">int factorial(int n)
{
int result = 1;
for(int i = 1; i <= n; i++)
result = result * i;
return result;
}</pre><p>如果这样定义,那么变量<code class="literal">i</code>只是<code class="literal">for</code>循环中的局部变量而不是整个函数的局部变量,相当于<a class="xref" href="ch04s01.html#cond.if">第 1 节 “if语句”</a>讲过的语句块中的局部变量,在循环结束后就不能再使用<code class="literal">i</code>这个变量了。这个程序用<code class="literal">gcc</code>编译要加上选项<code class="literal">-std=c99</code>。这种语法也是从C++借鉴的,考虑到兼容性不建议使用这种写法。</p><div class="footnotes"><br /><hr width="100" align="left" /><div class="footnote"><p><sup>[<a id="ftn.id2726856" href="#id2726856" class="para">9</a>] </sup>这两种写法在语义上稍有区别,详见<a class="xref" href="ch16s02.html#op.compound">第 2.1 节 “复合赋值运算符”</a>。</p></div><div class="footnote"><p><sup>[<a id="ftn.id2726883" href="#id2726883" class="para">10</a>] </sup>increment和decrement这两个词很有意思,大多数字典都说它们是名词,但经常被当成动词用,在计算机术语中,它们当动词用应该理解为increase by one和decrease by one。现代英语中很多原本是名词的都被当成动词用,字典都跟不上时代了,再比如transition也是如此。</p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch06s02.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="ch06.html">上一级</a></td><td width="40%" align="right"> <a accesskey="n" href="ch06s04.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">2. do/while语句 </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> 4. break和continue语句</td></tr></table></div></body></html>