跳转到内容

1. if 语句

目前我们写的简单函数中可以有多条语句,但这些语句总是从前到后顺序执行的。除了顺序执行之外,有时候我们需要检查一个条件,然后根据检查的结果执行不同的后续代码,在 C 语言中可以用分支语句(Selection Statement)实现,比如:

c
if (x != 0) {
    printf("x is nonzero.\n");
}

其中 x != 0 表示“x 不等于 0”的条件,这个表达式称为控制表达式(Controlling Expression)如果条件成立,则 {} 中的语句被执行,否则 {} 中的语句不执行,直接跳到 } 后面。 if 和控制表达式改变了程序的控制流程(Control Flow),不再是从前到后顺序执行,而是根据不同的条件执行不同的语句,这种控制流程称为分支(Branch)。上例中的 != 号表示“不等于”,像这样的运算符有:

表 4.1. 关系运算符和相等性运算符

运算符含义
==等于
!=不等于
>大于
<小于
>=大于或等于
<=小于或等于

注意以下几点:

  1. 这里的 == 表示数学中的相等关系,相当于数学中的 = 号,初学者常犯的错误是在控制表达式中把 == 写成 =,在 C 语言中 = 号是赋值运算符,两者的含义完全不同。
  2. 如果表达式所表示的比较关系成立则值为真(True),否则为假(False),在 C 语言中分别用 int 型的 1 和 0 表示。如果变量 x 的值是 -1,那么 x>0 这个表达式的值为 0, x>-2 这个表达式的值为 1。
  3. 在数学中 a<b<c 表示 b 既大于 a 又小于 c ,但作为 C 语言表达式却不是这样。以上几种运算符都是左结合的,请读者想一下这个表达式应如何求值。
  4. 这些运算符的两个操作数应该是相同类型的,两边都是整型或者都是浮点型可以做比较,但两个字符串不能做比较,在 第 1.5 节“比较字符串” 我们会介绍比较字符串的方法。
  5. ==!= 称为相等性运算符(Equality Operator),其余四个称为关系运算符(Relational Operator),相等性运算符的优先级低于关系运算符。

总结一下, if (x != 0) { ... } 这个语句的计算顺序是:首先求 x != 0 这个表达式的值,如果值为 0,就跳过 {} 中的语句直接执行后面的语句,如果值为 1,就先执行 {} 中的语句,然后再执行后面的语句。事实上控制表达式取任何非 0 值都表示真值,例如 if (x) { ... }if (x != 0) { ... } 是等价的,如果 x 的值是 2,则 x != 0 的值是 1,但对于 if 来说不管是 2 还是 1 都表示真值。

if 语句相关的语法规则如下:

plaintext
语句 → if (控制表达式) 语句
语句 → { 语句列表 }
语句 → ;

在 C 语言中,任何允许出现语句的地方既可以是由 ; 号结尾的一条语句,也可以是由 {} 括起来的若干条语句或声明组成的语句块(Statement Block),语句块和上一章介绍的函数体的语法相同。注意语句块的 } 后面不需要加 ; 号。如果}后面加了 ; 号,则这个 ; 号本身又是一条新的语句了,在 C 语言中一个单独的 ; 号表示一条空语句(Null Statement)。上例的语句块中只有一条语句,其实没必要写成语句块,可以简单地写成:

c
if (x != 0)
    printf("x is nonzero.\n");

语句块中也可以定义局部变量,例如:

c
void foo(void) {
    int i = 0;
    {
        int i = 1;
        int j = 2;
        printf("i=%d, j=%d\n", i, j);
    }
    printf("i=%d\n", i); /* cannot access j here */
}

和函数的局部变量同样道理,每次进入语句块时为变量 j 分配存储空间,每次退出语句块时释放变量 j 的存储空间。语句块也构成一个作用域,和 例 3.6“作用域”的分析类似,如果整个源文件是一张大纸, foo 函数是盖在上面的一张小纸,则函数中的语句块是盖在小纸上面的一张更小的纸。语句块中的变量 i 和函数的局部变量 i 是两个不同的变量,因此两次打印的 i 值是不同的;语句块中的变量 j 在退出语句块之后就没有了,因此最后一行的 printf 不能打印变量 j ,否则编译器会报错。语句块可以用在任何允许出现语句的地方,不一定非得用在 if 语句中,单独使用语句块通常是为了定义一些比函数的局部变量更“局部”的变量。

习题

  1. 以下程序段编译能通过,执行也不出错,但是执行结果不正确(根据 第 3 节“程序的调试” 的定义,这是一个语义错误),请分析一下哪里错了。还有,既然错了为什么编译能通过呢?

    c
    int x = -1;
    if (x > 0);
    printf("x is positive.\n");