6.4 退出循环 🚀
6.4.1 break 语句 🚀
当这些语句出现嵌套时,break语句只能跳出一层嵌套。
6.4.2 continue 语句 🚀
用break语句会使程序控制跳出循环,而continue语句会把程序控制留在循环内。break语句和continue语句的另外一个区别是:break语句可以用于switch语句和循环(while、do和for),而continue语句只能用于循环。
6.4.3 goto 语句 🚀
break语句和continue语句都是跳转语句:它们把控制从程序中的一个位置转移到另一个位置。这两者都是受限制的:break语句的目标是包含该语句的循环结束之后的那一点,而continue语句的目标是循环结束之前的那一点。goto语句则可以跳转到函数中任何有标号的语句处。(C99增加了一条限制:goto语句不可以用于绕过变长数组( 8.3节)的声明。)
注意,return语句后面没有break语句。紧跟在return语句后的break语句永远不会执行,
许多编译器还将显示警告消息。
6.5 空语句 🚀
语句可以为空,也就是除了末尾处的分号以外什么符号也没有。
空语句主要有一个好处:编写空循环体的循环。
把普通循环转化成带空循环体的循环不会带来很大的好处:新循环往往更简洁,但通常不会提高效率。但是在一些情况下,带空循环体的循环比其他循环更高效。例如,这些带空循环体的循环更便于读取字符( 7.3节)数据。
如果不小心在if、while或for语句的圆括号后放置分号会创建空语句,从而造成if、
while或for语句提前结束。
1. if语句中,如果在圆括号后边放置分号,无论控制表达式的值是什么,if语句执行的动作显然 都是一样的:
这种写法的循环会在i达到0值时停止,所以它应该和原始版本一样好。(p.70)
答: 新写法确实更加简洁,许多C程序员也都这样写循环。 但是,它也有缺点。
首先,新循环不像原始版本那样容易阅读。新循环可以清楚地显示出在i达到0值时循环终止,但是不能清楚地表示是向上计数还是向下计数。而在原始的循环中,根据控制表达式i > 0可以推断出这一信息。
其次,如果循环开始执行时i碰巧为负值,那么新循环的行为会不同于原始版本。原始循环会立刻终止,而新循环则不会。
问:6.3节提到,大多数 for循环可以利用标准模式转换成 while循环。能给出一个反例吗?(p.74)
答:当for循环体中含有continue语句时,6.3节给出的while模式将不再有效。思考下面这个来自6.4节的示例:
但是,这个循环并不等价于原始循环。当i等于0时,原始循环并没有对n进行自增操作,但是新循环却做了。
问:哪个无限循环格式更可取,while(1)还是for(;;)?(p.75)
答:C程序员传统上喜欢for(;;)的高效性;因为早期的编译器经常强制程序在每次执行while循环体时测试条件1。但是, 对于现代编译器来说,在性能上两种无限循环应该没有差别。
问:听说程序员应该永不使用continue语句。这种说法对吗?
答:continue语句的确很少使用。尽管如此,continue语句有时还是非常方便的。假设我们编写的循 环要读入一些输入数据并测试其有效性,如果有效则以某种方法进行处理。如果有许多有效性测试,或者如果它们都很复杂,那么continue语句就非常有用了。循环将类似于下面这样:
问:goto语句有什么不好?(p.79)
答:goto语句不是天生的魔鬼,只是通常它有更好的替代方式。使用过多goto语句的程序会迅速退化成“垃圾代码”,因为控制可以随意地跳来跳去。垃圾代码是非常难于理解和修改的。
由于goto语句既可以往前跳又可以往后跳,所以使得程序难于阅读。(break语句和 continue语句只是往前跳。)含有goto语句的程序经常要求阅读者来回跳转以理解代码的控制流。goto语句使程序难于修改,因为它可能会使某段代码用于多种不同的目的。例如,对于前面有标号的语句,既可以在执行完其前一条语句后到达,也可以通过多条goto语句中的一条到达。
问:除了说明循环体为空外,空语句还有其他用途吗?(p.82)
答: 非常少。空语句可以放在任何允许放语句的地方,所以有许多潜在的用途。 但在实际中,空语句只有一种别的用途,而且极少使用。
假设需要在复合语句的末尾放置标号。标号不能独立存在,它后面必须有语句。在标号后放置空语句就可以解决这个问题: