C 运算符优先级,a++ && b++ || 中的逻辑与一元++c
C operator precedence, logical vs unary in a++ && b++ || ++c
在下面的代码中,
int a = 1, b = 2, c = 3, d;
d = a++ && b++ || c++;
printf("%d\n", c);
输出将是 3,我得到它或评估第一个条件,将其视为 1,然后不关心另一个条件,但在 c 中,一元运算符的优先级高于逻辑运算符,就像在数学中一样
2 * 3 + 3 * 4
我们会先计算乘积再求和来计算上面的表达式,为什么 c 不这样做呢?先求所有的一元运算符,再求逻辑的东西?
请注意优先级与求值顺序不是同一个概念。 &&
和 ||
的特殊行为表明 right-hand 端根本不会被评估,如果它不是必须的。优先级告诉你一些关于如果它被评估将如何被评估的事情。
换句话说,优先级有助于描述如何解析表达式。但并没有直接说如何评价。 Precedence 告诉我们,解析您询问的表达式的方法是:
||
/ \
/ \
&& c++
/ \
/ \
a++ b++
但是当我们去评估这个解析树时,&&
和 ||
的 short-circuiting 行为告诉我们,如果 left-hand 端决定结果,我们根本不会站在 right-hand 一边评估任何东西。在这种情况下,由于 a++ && b++
为真,||
运算符知道其结果将为 1,因此它根本不会导致 c++
部分被计算。
这也是为什么像
这样的条件表达式
if(p != NULL && *p != '[=11=]')
和
if(n == 0 || sum / n == 0)
很安全。第一个不会崩溃,不会尝试访问 *p
,在 p
为 NULL 的情况下。如果 n
为 0,则第二个不会除以 0。
很容易对计算的优先级和顺序产生错误的印象。当我们有一个像
这样的表达式时
1 + 2 * 3
我们总是说 "the higher precedence of *
over +
means that the multiplication happens first" 这样的话。但是如果我们像这样抛出一些函数调用会怎样:
f() + g() * h()
这三个函数中的哪一个会先被调用?事实证明我们不知道。优先级并没有告诉我们这一点。编译器可以安排先调用 f()
,即使它的结果是最后需要的。另见 .
在下面的代码中,
int a = 1, b = 2, c = 3, d;
d = a++ && b++ || c++;
printf("%d\n", c);
输出将是 3,我得到它或评估第一个条件,将其视为 1,然后不关心另一个条件,但在 c 中,一元运算符的优先级高于逻辑运算符,就像在数学中一样
2 * 3 + 3 * 4
我们会先计算乘积再求和来计算上面的表达式,为什么 c 不这样做呢?先求所有的一元运算符,再求逻辑的东西?
请注意优先级与求值顺序不是同一个概念。 &&
和 ||
的特殊行为表明 right-hand 端根本不会被评估,如果它不是必须的。优先级告诉你一些关于如果它被评估将如何被评估的事情。
换句话说,优先级有助于描述如何解析表达式。但并没有直接说如何评价。 Precedence 告诉我们,解析您询问的表达式的方法是:
||
/ \
/ \
&& c++
/ \
/ \
a++ b++
但是当我们去评估这个解析树时,&&
和 ||
的 short-circuiting 行为告诉我们,如果 left-hand 端决定结果,我们根本不会站在 right-hand 一边评估任何东西。在这种情况下,由于 a++ && b++
为真,||
运算符知道其结果将为 1,因此它根本不会导致 c++
部分被计算。
这也是为什么像
这样的条件表达式if(p != NULL && *p != '[=11=]')
和
if(n == 0 || sum / n == 0)
很安全。第一个不会崩溃,不会尝试访问 *p
,在 p
为 NULL 的情况下。如果 n
为 0,则第二个不会除以 0。
很容易对计算的优先级和顺序产生错误的印象。当我们有一个像
这样的表达式时1 + 2 * 3
我们总是说 "the higher precedence of *
over +
means that the multiplication happens first" 这样的话。但是如果我们像这样抛出一些函数调用会怎样:
f() + g() * h()
这三个函数中的哪一个会先被调用?事实证明我们不知道。优先级并没有告诉我们这一点。编译器可以安排先调用 f()
,即使它的结果是最后需要的。另见