7

我有以下代码:

void main()
{
  int k, x, y, z;
  printf("\nExperiment 1:");
  x = 0, y = 0, z = 0;
  k = x++ || y++ && z++;
  printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k);
  printf("\nExperiment 2:");
  x = 1, y = 0, z = 0;
  k = x++ || y++ && z++;
  printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k);
}

输出:

实验 1:x = 1,y = 1,z = 0 和 k = 0

实验 2:x = 2,y = 0,z = 0 和 k = 1

我的理解是:要使表达式为真,'||'的左侧或右侧 必须非零。它从左边开始。如果 left 不为零,则不会进一步评估。如果为零,则从右侧开始。在右边我们有'&&'。因此,我们再次从 && 的左侧开始,如果它为零,则表达式不能为真并且不会继续。否则它评估'&&'的右侧

我的假设是运算符 && 具有更高的优先级。因此,它的两个参数都应该被评估,然后应该对它应用 &&,然后评估 || 的两个参数。

编译器是否在优化自己?我使用了禁用优化的 Visual Studio TC 编译器。

4

2 回答 2

9

我认为这在 C11 中涵盖§6.5.14 Logical OR operator(我的重点)

不像按位 | 运算符,|| 运算符保证从左到右的评估;如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点。如果第一个操作数比较不等于 0,则不计算第二个操作数。

于 2013-05-17T12:06:56.150 回答
4

所以表达式

k = x++ || y++ && z++;

被解释为(由于优先规则):

k = x++ || (y++ && z++);

在实验 1 中,我们有x = y = z = 0;.

在实验 2 中,我们有x = 1, y = z = 0;.

因此,右侧表达式在评估后停止y++,因为它的值为 0,因此布尔值不能变为真。

于 2013-05-17T12:08:22.460 回答