C现代方法笔记(chapter5&6)
第5章 选择语句
5.1 逻辑表达式
包括
if
语句在内的某些C语句必须测试表达式的值是“真”还是“假”。例如,if
语句可能需要检测表达式i < j
,若取得真值则说明i
小于j
。在许多编程语言中,类似i < j
这样的表达式都具有特殊的“布尔”类型或“逻辑”类型。这样的类型只有两个值,即假和真。而在C语言中,i < j
这样的比较运算会产生整数:0(假)
或1(真)
。先记住这一点,下面来看看用于构建逻辑表达式的运算符。
5.1.1 关系运算符
C语言的关系运算符(relational operator)跟数学上的<
、>
、≤
和≥
运算符相对应,只不过用在C语言的表达式中时产生的结果是0(假)
或1(真)
。例如,表达式10 < 11
的值为1
,而表达式11 < 10
的值为0。
关系运算符可以用于比较整数和浮点数,也允许比较混合类型的操作数。
从优先级上来看,关系运算符的优先级低于算术运算符。
请注意,表达式
i < j < k
在C语言中是合法的,但是由于<
运算符是左结合的,因此表达式等价于(i < k) < k
,要判断j
在i
和k
之间,正确的写法应该是i < j && j < k
。
5.1.2 判等运算符
- 等于(
==
) - 不等于(
!=
)
和关系运算符一样,判等运算符也是左结合的,并且产生0(假)
或1(真)
作为结果。然而,判等运算符的优先级低于关系运算符。
5.1.3 逻辑运算符
- 逻辑非(
!
) - 逻辑与(
&&
) - 逻辑或(
||
)
逻辑运算符所产生的结果是0
或1
。逻辑运算符将任何非零值操作数作为真值来处理,同时将任何零值操作数作为假值来处理。
运算符
&&
和运算符||
都对操作数进行“短路”计算。也就是说,这些运算符首先计算出左操作数的值,然后计算右操作数。如果表达式的值可以仅由左操作数的值推导出来,那么将不计算右操作数的值。运算符
!
的优先级和一元正负号的优先级相同,运算符&&
和运算符||
的优先级低于关系运算符和判等运算符。例如,表达式i < j && k == m
等价于表达式(i < j) && (k == m)
。运算符!
是右结合的,而运算符&&
和运算符||
都是左结合的。
5.2 if语句
if
语句允许程序通过测试表达式的值从两种选项中选择一种。
if
语句的最简单格式如下:
if (表达式) 语句
其中,表达式两边的圆括号是必需的,它们是if
语句的组成部分。
执行if
语句时,先计算圆括号内表达式的值。如果表达式的值非零(C语言把非零值解释为真值),那么接着执行圆括号后边的语句。
5.2.1 复合语句
复合语句由一对花括号,以及花括号内的声明和语句混合而成。可以有多个声明和多条语句,也可以都没有。在后一种情况下,复合语句只有一对花括号,它什么也不做。典型地,通过在一组语句周围放置花括号,可以强制编译器将其作为一条语句来处理。
下面是在if语句内部使用复合语句的形式:
if (line_num == MAX_LINES) {
line_num = 0;
page_num++;
}
复合语句也常出现在循环和其他需要多条语句(但C语言的语法要求一条语句)的地方。
5.2.2 else子句
if
语句可以有else
子句:
if (表达式) 语句 else 语句
如果圆括号内的表达式的值为0
,那么就执行else
后边的语句。
当在if
语句中嵌套if
语句时,记得要为语句增加花括号(即使有时并不是必需的),就像在表达式中使用圆括号一样,这两种方法都可以使程序更加容易阅读,同时可以避免出现编译器不能像程序员一样去理解程序的问题。
5.2.3 级联式if语句(else if)
编程时常常需要判定一系列的条件,一旦其中某一个条件为真就立刻停止。“级联式”
if
语句常常是编写这类系列判定的最好方法。
if (表达式)
语句
else if (表达式)
语句
else if (表达式)
语句
else
语句
当然,最后两行(else
语句)不是总出现的。这种缩进级联式if
语句的方
法避免了判定数量过多时过度缩进的问题。此外,这样也向读者证明了这组语句只是一连串的判定。
请记住,级联式
if
语句不是新的语句类型,它仅仅是普通的if
语句,只是碰巧有另外一条if
语句作为else
子句(而且这条if
语句又有另外一条if
语句作为它自己的else
子句,以此类推)。
5.2.4 “悬空else”的问题
当
if
语句嵌套时,千万要当心著名的“悬空else
”的问题。思考下面这个例子:
if (y != 0)
if (x != 0)
result = x / y;
else
printf("Error: y is equal to 0\n");
上面的else
子句究竟属于哪一个if
语句呢?缩进格式暗示它属于最外层的if
语句。然而,C语言遵循的规则是else
子句应该属于离它最近的且还未和其他else
匹配的if
语句。在此例中,else
子句实际上属于最内层的if
语句,因此正确的缩进格式应该如下所示:
if (y != 0)
if (x != 0)
result = x / y;
else
printf("Error: y is equal to 0\n");
为了使else
子句属于外层的if
语句,可以把内层的if
语句用花括号括起来:
if (y != 0) {
if (x != 0)
result = x / y;
} else
printf("Error: y is equal to 0\n");
这个示例表明了花括号的作用。如果把花括号用在本节第一个示例的if
语句上,那么就不会有这样的问题了。
5.2.5 条件表达式
C语言的
if
语句允许程序根据条件的值来执行两个操作中的一个。C语言还提供了一种特殊的运算符,这种运算符允许表达式依据条件的值产生两个值中的一个。
条件运算符(conditional operator)由符号?
和符号:
组成,两个符号必须按如下格式一起使用:
表达式1? 表达式2 : 表达式3
-
上面的表达式可以是任何类型的表达式,按上述方式组合成的表达式称为条件表达式。条件运算符是C运算符中唯一一个要求3个操作数的运算符。因此,它通常被称为三元运算符。
-
条件表达式
表达式1?表达式2:表达式3
读作“如果表达式1
成立,那么表达式2
,否则表达式3
”。 -
条件表达式也普遍用于某些类型的宏定义中。
5.2.6 C89中的布尔值
C89标准中也没有定义布尔类型,但是有几种解决方法。
- 一种解决方法是先声明一个
int
型变量,然后将其赋值为0
或1
:
int flag;
flag = 0;
....
flag = 1;
- 为了使程序更易于理解,C89的程序员通常使用
TRUE
和FALSE
这样的名字定义宏:
#define TRUE 1
#define FALSE 0
flag = FALSE;
...
flag = TRUE;
为了发扬这一思想,甚至可以定义一个可用作类型的宏:
#define BOOL int
BOOL flag;
在后面的章节中,我们将介绍一些更好的方法,可以使用类型定义( 7.5节)和枚举( 16.5 节)在C89中设置布尔类型。
5.2.7 C99中的布尔值
C99提供了
_Bool
型,因此在C语言的这一版本中,布尔变量可以声明为_Bool flag;
_Bool
是整数类型(更准确地说是无符号整型),因此_Bool
变量实际上就是整型变量;但是和一般的整型不同,_Bool
只能赋值为0
或1
。一般来说,往_Bool
变量中存储非零值会导致变量赋值为1
:
flag = 5; /* flag is assigned 1 */
除了_Bool
类型的定义,C99还提供了一个新的头<stdbool.h>
,这使得操作布尔值更加容易。该头提供了bool
宏,用来代表_Bool
。
#include <stdbool.h>
....
bool flag;
flag = false;
....
flag = true;
<stdbool.h>
头使用起来非常方便,因此在后面的程序中需要使用布尔变量时都用到了这个头。
5.3 switch语句
C语言提供了switch
语句作为级联式if
语句的替代。
if (grade == 4)
printf("Excellent");
else if (grade == 3)
printf("Good");
else if (grade == 2)
printf("Average");
else if (grade == 1)
printf("Poor");
else if (grade == 0)
printf("Failing");
else
printf("Illegal grade");
/
switch (grade) {
case 4: printf("Excellent");
break;
case 3: printf("Good");
break;
case 2: printf("Average");
break;
case 1: printf("Poor");
break;
case 0: printf("Failing");
break;
default: printf("Illegal grade");
break;
}
执行上述
switch
语句时,变量grade
的值与4
、3
、2
、1
和0
进行比较。例如,如果值和4
相匹配,那么显示信息Excellent
,然后break
语句( 6.4 节)把控制传递给switch
后边的语句。如果grade
的值和列出的任何选项都不匹配,那么执行default
分支的语句,显示消息Illegal grade
。
switch
语句往往比级联式if
语句更容易阅读。此外,switch
语句往往比if
语句执行速度快,特别是在有许多情况要判定的时候。
switch
语句十分复杂,下面逐一看一下它的组成部分。
-
控制表达式。
switch
后边必须跟着由圆括号括起来的整型表达式。C语言把字符(7.3节)当成整数来处理,因此在switch
语句中可以对字符进行判定。但是,这不适用于浮点数和字符串。 -
分支标号。每个分支的开头都有一个标号,格式如下:
case 常量表达式:
常量表达式(constant expression)很像普通的表达式,只是不能包含变量和函数调用。因此,
5
是常量表达式,5 + 10
也是常量表达式,但n + 10
不是常量表达式(除非n
是表示常量的宏)。分支标号中常量表达式的值必须是整数(字符也可以)。 -
语句。每个分支标号的后边可以跟任意数量的语句,并且不需要用花括号把这些语句括起来。(好好享受这一点,这可是C语言中少数几个不需要花括号的地方。)每组语句的最后一条通常是
break
语句。
C语言不允许有重复的分支标号,但对分支的顺序没有要求,特别是default
分支不一定要放置在最后。
case
后边只可以跟随一个常量表达式。但是,多个分支标号可以放置在同一组语句的前面:
switch (grade) {
case 4: case 3: case 2: case l:
printf("Passing");
break;
case 0: printf("Failing");
break;
default: printf("Illegal grade");
break;
}
switch
语句不要求一定有default
分支。如果default
不存在,而且控制表达式的值和任何一个分支标号都不匹配的话,控制会直接传给switch
语句后面的语句。
5.3.1 break语句的作用
需要break
语句是由于switch
语句实际上是一种“基于计算的跳转”。对控制表达式求值时,控制会跳转到与switch
表达式的值相匹配的分支标号处。分支标号只是一个说明switch
内部位置的标记。在执行完分支中的最后一条语句后,程序控制“向下跳转”到下一个分支的第一条语句上,忽略下一个分支的分支标号。如果没有break
语句(或者其他某种跳转语句),控制将从一个分支继续流向下一个分支。思考下面的switch
语句:
switch (grade) {
case 4: printf("Excellent");
case 3: printf("Good");
case 2: printf("Average");
case 1: printf("Poor");
case 0: printf("Fai1ing");
default: printf("Illegal grade");
}
/*
如果grade的值为3,那么显示的消息是
GoodAveragePoorFailingIllegal grade
*/
问与答
问1:当我用
=
代替==
时,我所用的编译器没有发出警告。是否有办法可以强制编译器注意这类问题?
答:幸运的是,许多编译器可以检测出if
条件中=
运算符的可疑使用。例如,GCC会在选中-Wparentheses
选项或-Wall
(所有情况都警告)选项时执行这样的检查。GCC允许程序员通过在if
条件外面增加一对圆括号的方式来禁用该警告:
if ((i = j)) ...
问2:如果
i
是int
型变量,f
是float
型变量,那么条件表达式(i > 0 ? i: f)
是哪一种类型的值?
答:如问题所述,当int
型和float
型的值混合在一个条件表达式中时,表达式的类型为float
型。如果i > 0
为真,那么变量i
转换为float
型后的值就是表达式的值。
问3:为什么
_Bool
这个名字就不会影响已有的程序呢?
答:C89标准指出,以下划线开头,后跟一个大写字母的名字是保留字,程序员不应该使用。
第6章 循环
循环(loop)是重复执行其他语句(循环体)的一种语句。在C 语言中,每个循环都有一个控制表达式(controlling expression)。每次执行循环体(循环重复一次)时都要对控制表达式求值。如果表达式为真(即值不为零),那么继续执行循环。
C语言提供了3种重复语句,即while
语句、do
语句和for
语句。while
循环在循环体执行之前测试控制表达式,do
循环在循环体执行之后测试控制表达式,for
语句则非常适合那些递增或递减计数变量的循环。
本章最后两节致力于讨论与循环相关的C语言特性。break
语句用来跳出循环并把程序控制传递到循环后的下一条语句,continue
语句用来跳过本次循环的剩余部分,而goto
语句则可以跳到函数内的任何语句上。
6.1 while语句
在C语言所有设置循环的方法中,
while
语句是最简单也是最基本的。while
语句的格式如下所示:
while (表达式) 语句
圆括号内的表达式是控制表达式,圆括号后边的语句是循环体。
执行while
语句时,首先计算控制表达式的值。如果值不为零(即真值),那么执行循环体,接着再次判定表达式。这个过程(先判定控制表达式,再执行循环体)持续进行,直到控制表达式的值变为零才停止。
请注意,虽然循环体必须是单独的一条语句,但这只是个技术问题;如果需要多条语句,那么只要用一对花括号构造成一条复合语句就可以了,比如:
while (i > 0) {
printf("flsdjfklsdjlkfjklsdj");
i--;
}
6.1.1 无限循环
如果控制表达式的值始终非零(为真),while
语句将无法终止。事实上,C程序员有时故意用非零常量作为控制表达式来构造无限循环:
[惯用法] while (1) ...
除非循环体中含有跳出循环控制的语句(break
、goto
、return
)或者调用了导致程序终止的函数,否则上述形式的while
语句将永远执行下去。
小知识:如何把输出整齐地排成两列?窍门是使用类似
%10d
这样的转换说明代替%d
,并利用了printf
函数在指定宽度内输出右对齐的特性。
下面是一个利用循环进行数列求和的例子:
/* Sums a series of numbers */
#include <stdio.h>
int main(void)
{
int n, sum = 0;
printf("This program sums a series of integers.\n");
printf("Enter integers (0 to terminate): ");
scanf("%d", &n);
while (n != 0) {
sum += n;
scanf("%d", &n);
}
printf("The sum is: %d\n", sum);
return 0;
}
/*
This program sums a series of integers.
Enter integers (0 to terminate): 8 23 71 5 0
The sum is: 107
*/
注意,条件n != 0
在数被读入后立即进行判断,这样可以尽快终止循环。此外,程序中用到了两个完全一样的scanf
函数调用,在使用while
循环时往往很难避免这种现象。
6.2 do语句
do
语句和while
语句关系紧密。事实上,do
语句本质上就是while
语句,只不过其控制表达式是在每次执行完循环体之后进行判定的。do
语句的格式如下所示:
do 语句 while (表达式)
和处理while
语句一样,do
语句的循环体也必须是一条语句(当然可以用复合语句),并且控制表达式的外面也必须有圆括号。
执行do
语句时,先执行循环体,再计算控制表达式的值。如果表达式的值是非零的,那么再次执行循环体,然后再次计算表达式的值。在循环体执行后,若控制表达式的值变为0,则终止do
语句的执行。
do
语句和while
语句往往难以区别。两种语句的区别是,do
语句的循环体至少要执行一次,而while
语句在控制表达式初始值为0
时会完全跳过循环体。
下面是一个利用do循环计算整数的位数的例子:
/* Calculates the number of digits in an integer */
#include <stdio.h>
int main(void)
{
int digits = 0, n;
printf("Enter a nonnegative integer: ");
scanf("%d", &n);
do {
n /= 10;
digits++;
} while (n > 0);
printf("The number has %d digit(s).\n", digits);
return 0;
}
/*
Enter a nonnegative integer: 60
The number has 2 digit(s).
*/
6.3 for语句
for
语句是C语言循环中最后一种循环,也是功能最强大的一种循环。不要因为for
语句表面上的复杂性而灰心;实际上,它是编写许多循环的最佳方法。for
语句非常适合应用在使用“计数”变量的循环中,当然它也可以灵活地用于许多其他类型的循环中。格式如下:
for (声明或者表达式1;表达式2;表达式3) 语句
其中表达式1、表达式2 和表达式3全都是表达式。下面是一个例子:
for (i = 10; i > 0; i--)
printf("T minus %d and counting\n",i);
/*
在执行for语句时,变量i先初始化为10,接着判定i是否大于0。因为判定的结果为真,所以打印信息T minus 10 and counting,然后变量i进行自减操作。随后再次对条件i > 0进行判定。循环体总共执行10次,在这一过程中变量i从10变化到1。
*/
for
语句和while
语句关系紧密。事实上,除了一些极少数的情况以外,for
循环总可以用等价的while
循环替换:
表达式1;
while (表达式2) {
语句
表达式3;
}
6.3.1 for语句的惯用法
对于“向上加”(变量自增)或“向下减”(变量自减)的循环来说,
for
语句通常是最好的选择。对于向上加或向下减共n
次的情况,for语句经常会采用下列形式中的一种。
- 从
0
向上加到n-1
:for ( i = 0; i < n; i++) ...
- 从
1
向上加到n
:for ( i = 1; i <= n; i++) ...
- 从
n-1
向下减到0
:for ( i = n-1; i >= 0; i--) ...
- 从
n
向下减到1
:for ( i = n; i > 0; i--) ...
模仿上面的书写格式有助于避免C语言初学者常犯的下列错误:
- 在控制表达式中把
>
写成<
(或者相反)。注意,“向上加”的循环使用运算符<
或运算符<=
,而“向下减”的循环则依赖于运算符>
或运算符>=
。 - 在控制表达式中把
<
、<=
、>
或>=
写成==
。控制表达式的值在循环开始时应该为真,以后会变为假以便能终止循环。类似i == n
这样的判定没什么意义,因为它的初始值不为真。 - 编写的控制表达式中把
i < n
写成i <= n
,这会犯“循环次数差一”错误。
6.3.2 在for语句中省略表达式
通常for
语句用三个表达式控制循环,但是有一些for
循环可能不需要这么多,因此C语言允许省略任意或全部的表达式。
注意,保留第一个表达式和第二个表达式之间的分号。即使省略掉某些表达式,控制表达式也必须始终有两个分号。
某些程序员用下列
for
语句建立无限循环:for (;;) ...
6.3.3 C99中的for语句
在C99中,for
语句的第一个表达式可以替换为一个声明,这一特性使得程序员可以声明一个用于循环的变量:
for (int i = 0; i < n; i++)
变量
i
不需要在该语句前进行声明。事实上,如果变量i
在之前已经进行了声明,这个语句将创建一个新的i
且该值仅用于循环内。
for
语句声明的变量不可以在循环外访问(在循环外不可见)。顺便提一下,for
语句可以声明多个变量,只要它们类型相同。
for (int i = 0, j = 0; i < n; i++)
....
6.3.4 逗号运算符
有些时候,我们可能喜欢编写有两个(或更多个)初始表达式的
for
语句,或者希望在每次循环时一次对几个变量进行自增操作。使用逗号表达式(comma expression)作为for
语句中第一个或第三个表达式可以实现这些想法。逗号表达式的格式如下所示:
表达式1, 表达式2
这里的表达式1
和表达式2
是两个任意的表达式。逗号表达式的计算要通过两步来实现:
- 第一步,计算
表达式1
并且扔掉计算出的值; - 第二步,计算
表达式2
,把这个值作为整个表达式的值。对表达式1
的计算应该始终会有副作用;如果没有,那么表达式1
就没有了存在的意义。
i = 1, j = 2, k = i + j
/*
因为逗号表达式的左操作数在右操作数之前求值,所以赋值运算i = 1、j = 2 和k = i + j是从左向右进行的。
*/
提供逗号运算符是为了在C语言要求只能有一个表达式的情况下,可以使用两个或多个表达式。换句话说,逗号运算符允许将两个表达式“粘贴”在一起构成一个表达式。(注意它与复合语句的相似之处,后者允许我们把一组语句当作一条语句来使用。)
需要把多个表达式粘在一起的情况不是很多。正如后面的某一章将介绍的那样,某些宏定义( 14.3 节)可以从逗号运算符中受益。除此之外,
for
语句是唯一可以发现逗号运算符的地方。
6.4 退出循环
然而,有些时候也需要在循环中间设置退出点,甚至可能需要对循环设置多个退出点。break
语句可以用于有上述这些需求的循环中。
continue
语句会跳过某次迭代的部分内容,但是不会跳出整个循环。goto
语句允许程序从一条语句跳转到另一条语句。因为已经有了break
和continue
这样有效的语句,所以很少使用goto
语句。
6.4.1 break语句
break
语句把程序控制从switch
语句中转移出来,还可以用于跳出while
、do
或for
循环。
值得注意的是,
break
语句把程序控制从包含该语句的最内层while
、do
、for
或switch
语句中转移出来。因此,当这些语句出现嵌套时,break
语句只能跳出一层嵌套。
while (...) {
switch (...) {
...
break;
...
}
}
/*
break语句可以把程序控制从switch语句中转移出来,
但是不能跳出while循环。
*/
6.4.2 continue语句
break
语句刚好把程序控制转移到循环体末尾之后,而continue
语句刚好把程序控制转移到循环体末尾之前。break
语句会使程序控制跳出循环,而continue
语句会把程序控制留在循环内。break
语句和continue
语句的另外一个区别是,break
语句可以用于switch
语句和循环(while
、do
和for
),而continue
语句只能用于循环。
6.4.3 goto语句
goto
语句在早期编程语言中很常见,但在日常C语言编程中已经很少用到它了。
break
、continue
、return
语句(本质上都是受限制的goto
语句)和exit
函数( 9.5 节)足以应付在其他编程语言中需要goto
语句的大多数情况。
goto
语句则可以跳转到函数中任何有标号的语句处。[C99增加了一条限制:goto
语句不可以用于绕过变长数组( 8.3 节)的声明。]
-
标号只是放置在语句开始处的标识符:
标识符 : 语句
- 一条语句可以有多个标号。goto语句自身的格式如下:
goto 标识符
执行语句goto L;
,控制会转移到标号L
后面的语句上,而且该语句必须和goto
语句在同一个函数中。
while (...) {
switch (...) {
...
goto loop_done; /* break won’t work here */
...
}
}
loop_done: ...
//goto语句对于嵌套循环的退出也是很有用的。
6.5 空语句
语句可以为空,也就是除了末尾处的分号以外什么符号也没有。下面是一个示例:
i = 0; ; j = 1;
这行含有三条语句:一条语句是给i
赋值,一条是空语句,还有一条是给j
赋值。
空语句主要有一个好处:编写空循环体的循环。(注意空语句单独放置在一行。)
for (d = 2; d < n && n % d != 0; d++)
/* empty loop body */;
C程序员习惯性地把空语句单独放置在一行。否则,有些人阅读程序时可能会搞不清for
语句后边的语句是否是其循环体。
请注意!如果不小心在
if
、while
或for
语句的圆括号后放置分号,则会创建空语句,从而造成if
、while
或for
语句提前结束。
问与答
问1:
while (i > 0) printf("T minus %d and counting\n", i--); 为什么不删除“> 0”判定来进一步缩短循环呢? while (i) printf("T minus %d and counting\n", i--); 这种写法的循环会在i 达到0 值时停止,所以它应该和原始版本一样好。
答:新写法确实更加简洁,许多C程序员也这样写循环。但是,它也有缺点。
首先,新循环不像原始版本那样容易阅读。新循环可以清楚地显示出在i
达到0
值时循环终止,但是不能清楚地表示是向上计数还是向下计数。而在原始的循环中,根据控制表达式i > 0
可以推断出这一信息。
其次,如果循环开始执行时i
碰巧为负值,那么新循环的行为会不同于原始版本。原始循环会立刻终止,而新循环则不会。
问2:6.3节提到,大多数
for
循环可以利用标准模式转换成while
循环。能给出一个反例吗?
答:当for
循环体中含有continue
语句时,6.3节给出的while
模式将不再有效。
问3:哪个无限循环格式更可取,
while(1)
还是for(;;)
?
答:C程序员传统上喜欢for(;;)
的高效性。这是因为早期的编译器经常强制程序在每次执行while
循环体时测试条件1
。但是,对于现代编译器来说,在性能上两种无限循环应该没有差别。
问4:听说程序员应该永不使用
continue
语句。这种说法对吗?
答:continue
语句的确很少使用。尽管如此,continue
语句有时还是非常方便的。假设我们编写的循环要读入一些输入数据并测试其有效性,如果有效则以某种方法进行处理。如果有许多有效性测试,或者如果它们都很复杂,那么continue
语句就非常有用了。循环将类似于下面这样:
for(; ;) {
读入数据;
if(数据的第一条测试失败)
continue;
if(数据的第二条测试失败)
continue; . . .
if(数据的最后一条测试失败)
continue;
处理数据;
}
问5:
goto
语句有什么不好?
答:goto
语句不是天生的魔鬼,只是通常它有更好的替代方式。使用过多goto
语句的程序会迅速退化成“垃圾代码”,因为控制可以随意地跳来跳去。垃圾代码是非常难于理解和修改的。
-
因为
goto
语句既可以往前跳又可以往后跳,所以使得程序难于阅读。(break
语句和continue
语句只是往前跳。)含有goto
语句的程序经常要求阅读者来回跳转以理解代码的控制流。 -
goto
语句使程序难于修改,因为它可能会使某段代码用于多种不同的目的。例如,对于前面有标号的语句,既可以在执行完其前一条语句后到达,也可以通过多条goto
语句中的一条到达。
问6:除了说明循环体为空外,空语句还有其他用途吗?
答:非常少。空语句可以放在任何允许放语句的地方,所以有许多潜在的用途。但在实际中,空语句只有一种别的用途,而且极少使用。
问7:除了把空语句单独放置在一行以外,是否还有其他方法可以凸显出空循环体?
答:一些程序员使用虚设的continue
语句:
for (d = 2; d < n && n % d != 0; d++)
continue;
还有一些人使用空的复合语句:文章来源:https://www.toymoban.com/news/detail-726951.html
for (d = 2; d < n && n % d != 0; d++)
{}
写在最后
本文是作者阅读《C语言程序设计:现代方法(第2版·修订版)》时所做笔记,日后会持续更新后续章节笔记。欢迎各位大佬批评指正,希望对诸位有所帮助,Thank you very much!文章来源地址https://www.toymoban.com/news/detail-726951.html
到了这里,关于C现代方法(第5&6章)笔记——选择语句、循环的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!