Team LiB
Previous Section Next Section

5.2. Relational and Logical Operators

5.2. 关系操作符和逻辑操作符

The relational and logical operators take operands of arithmetic or pointer type and return values of type bool.

关系操作符和逻辑操作符(表 5.2)使用算术或指针类型的操作数,并返回 bool 类型的值。

Table 5.2. Relational and Logical Operators
表 5.2. 关系操作符和逻辑操作符

Each of these operators yields bool

下列操作符都产生 bool

Operator

操作符

Function

功能

Use

用法

!

logical NOT(逻辑非)

!expr

<

less than(小于)

expr < expr

<=

less than or equal(小于等于)

expr <= expr

>

greater than(大于)

expr > expr

>=

greater than or equal(大于等于)

expr >= expr

==

equality(相等)

expr == expr

!=

inequality(不等)

expr != expr

&&

logical AND(逻辑与)

expr && expr

||

logical OR(逻辑或)

expr || expr


Logical AND and OR Operators

逻辑与、逻辑或操作符

The logical operators treat their operands as conditions (Section 1.4.1, p. 12). The operand is evaluated; if the result is zero the condition is false, otherwise it is true. The overall result of the AND operator is TRue if and only if both its operands evaluate to TRue. The logical OR (||) operator evaluates to true if either of its operands evaluates to true. Given the forms

逻辑操作符将其操作数视为条件表达式(第 1.4.1 节):首先对操作数求值;若结果为 0,则条件为假(false),否则为真(true)。仅当逻辑与(&&)操作符的两个操作数都为 true,其结果才得 true 。对于逻辑或(||)操作符,只要两个操作数之一为 true,它的值就为 true。给定以下形式:

     expr1 && expr2 // logical AND
     expr1 || expr2 // logical OR

expr2 is evaluated if and only if expr1 does not by itself determine the result. In other words, we're guaranteed that expr2 will be evaluated if and only if

仅当由 expr1 不能确定表达式的值时,才会求解 expr2。也就是说,当且仅当下列情况出现时,必须确保 expr2 是可以计算的:

  • In a logical AND expression, expr1 evaluates to TRue. If expr1 is false, then the expression will be false regardless of the value of expr2. When expr1 is true, it is possible for the expression to be true if expr2 is also TRue.

    在逻辑与表达式中,expr1 的计算结果为 true。如果 expr1 的值为 false,则无论 expr2 的值是什么,逻辑与表达式的值都为 false 。当 expr1 的值为 true 时,只有 expr2 的值也是 true ,逻辑与表达式的值才为 true

  • In a logical OR expression, expr1 evaluates to false; if expr1 is false, then the expression depends on whether expr2 is true.

    在逻辑或表达式中,expr1 的计算结果为 false。如果 expr1 的值为 false,则逻辑或表达式的值取决于 expr2 的值是否为 true

The logical AND and OR operators always evaluate their left operand before the right. The right operand is evaluated only if the left operand does not determine the result. This evaluation strategy is often referred to as "short-circuit evaluation."

逻辑与和逻辑或操作符总是先计算其左操作数,然后再计算其右操作数。只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数。我们常常称这种求值策略为“短路求值(short-circuit evaluation)”。



A valuable use of the logical AND operator is to have expr1 evaluate to false in the presence of a boundary condition that would make the evaluation of expr2 dangerous. As an example, we might have a string that contains the characters in a sentence and we might want to make the first word in the sentence all uppercase. We could do so as follows:

对于逻辑与操作符,一个很有价值的用法是:如果某边界条件使 expr2 的计算变得危险,则应在该条件出现之前,先让 expr1 的计算结果为 false。例如,编写程序使用一个 string 类型的对象存储一个句子,然后将该句子的第一个单词的各字符全部变成大写,可如下实现:

     string s("Expressions in C++ are composed...");
     string::iterator it = s.begin();
     // convert first word in s to uppercase
     while (it != s.end() && !isspace(*it)) {
         *it = toupper(*it); // toupper covered in section 3.2.4 (p. 88)
         ++it;
     }

In this case, we combine our two tests in the condition in the while. First we test whether it has reached the end of the string. If not, it refers to a character in s. Only if that test succeeds is the right-hand operand evaluated. We're guaranteed that it refers to an actual character before we test to see whether the character is a space or not. The loop ends either when a space is encountered or, if there are no spaces in s, when we reach the end of s.

在这个例子中,while 循环判断了两个条件。首先检查 it 是否已经到达 string 类型对象的结尾,如果不是,则 it 指向 s 中的一个字符。只有当该检验条件成立时,系统才会计算逻辑与操作符的右操作数,即在保证it确实指向一个真正的字符之后,才检查该字符是否为空格。如果遇到空格,或者 s 中没有空格而已经到达 s 的结尾时,循环结束。

Logical NOT Operator

逻辑非操作符

The logical NOT operator (!) treats its operand as a condition. It yields a result that has the opposite truth value from its operand. If the operand evaluates as nonzero, then ! returns false. For example, we might determine that a vector has elements by applying the logical NOT operator to the value returned by empty:

逻辑非操作符(!)将其操作数视为条件表达式,产生与其操作数值相反的条件值。如果其操作数为非零值,则做 ! 操作后的结果为 false。例如,可如下在 vector 类型对象的 empty 成员函数上使用逻辑非操作符,根据函数返回值判断该对象是否为空:

     // assign value of first element in vec to x if there is one
     int x = 0;
     if (!vec.empty())
         x = *vec.begin();

The subexpression

如果调用 empty 函数返回 false,则子表达式

     !vec.empty()

evaluates to true if the call to empty returns false.

的值为 true

The Relational Operators Do Not Chain Together

不应该串接使用关系操作符

The relational operators (<, <=, >, <=) are left associative. The fact that they are left associative is rarely of any use because the relational operators return bool results. If we do chain these operators together, the result is likely to be surprising:

关系操作符(<、<=、>、<=)具有左结合特性。事实上,由于关系操作符返回bool类型的结果,因此很少使用其左结合特性。如果把多个关系操作符串接起来使用,结果往往出乎预料:

     // oops! this condition does not determine if the 3 values are unequal
     if (i < j < k) { /* ... */ }

As written, this expression will evaluate as true if k is greater than one! The reason is that the left operand of the second less-than operator is the TRue/ false result of the firstthat is, the condition compares k to the integer values of 0 or 1. To accomplish the test we intended, we must rewrite the expression as follows:

这种写法只要 k 大于 1,上述表达式的值就为 true。这是因为第二个小于操作符的左操作数是第一个小于操作符的结果:truefalse。也就是,该条件将 k 与整数 0 或 1 做比较。为了实现我们想要的条件检验,应重写上述表达式如下:

     if (i < j && j < k) { /* ... */ }

Equality Tests and the bool Literals

相等测试与 bool 字面值

As we'll see in Section 5.12.2 (p. 180) a bool can be converted to any arithmetic typethe bool value false converts to zero and true converts to one.

正如第 5.12.2 节将介绍的,bool 类型可转换为任何算术类型——boolfalse 用 0 表示,而 true 则为 1。

Because bool converts to one, is almost never right to write an equality test that tests against the bool literal true:

由于 true 转换为 1,因此要检测某值是否与 bool 字面值 true 相等,其等效判断条件通常很难正确编写:

     if (val == true) { /* ... */ }

Either val is itself a bool or it is a type to which a bool can be converted. If val is a bool, then this test is equivalent to writing

val 本身是 bool 类型,或者 val 具有可转换为 bool 类型的数据类型。如果 valbool 类型,则该判断条件等效于:

     if (val) { /* ... */ }

which is shorter and more direct (although admittedly when first learning the language this kind of abbreviation can be perplexing).

这样的代码更短而且更直接(尽管对初学者来说,这样的缩写可能会令人费解)。

More importantly, if val is not a bool, then comparing val with true is equivalent to writing

更重要的是,如果 val 不是 bool 值,valtrue 的比较等效于:

     if (val == 1) { /* ... */ }

which is very different from

这与下面的条件判断完全不同:

     // condition succeeds if val is any nonzero value
     if (val) { /* ... */ }

in which any nonzero value in val is true. If we write the comparison explicitly, then we are saying that the condition will succeed only for the specific value 1.

此时,只要 val 为任意非零值,条件判断都得 true。如果显式地书写条件比较,则只有当 val 等于指定的 1 值时,条件才成立。

Exercises Section 5.2

Exercise 5.5:

Explain when operands are evaluated in the logical AND operator, logical OR operator, and equality operator.

解释逻辑与操作符、逻辑或操作符以及相等操作符的操作数在什么时候计算。

Exercise 5.6:

Explain the behavior of the following while condition:

解释下列 while 循环条件的行为:

     char *cp = "Hello World";
     while (cp && *cp)
Exercise 5.7:

Write the condition for a while loop that would read ints from the standard input and stop when the value read is equal to 42.

编写 while 循环条件从标准输入设备读入整型(int)数据,当读入值为 42 时循环结束。

Exercise 5.8:

Write an expression that tests four values, a, b, c, and d, and ensures that a is greater than b, which is greater than c, which is greater than d.

编写表达式判断四个值 a、b、cd 是否满足 a 大于 b、b 大于 c 而且 c 大于 d 的条件。

Team LiB
Previous Section Next Section