-1

我写了以下代码:

int main(){

int i=-1,j=-1,k=0,l=2,m;
m = i++ && j++ && k++ || l++;
printf("%d %d %d %d %d",i,j,k,l,m);

i=-1,j=-1,k=0,l=2,m;
m = ++i && ++j && ++k || ++l;
printf("\n%d %d %d %d %d",i,j,k,l,m);
    return(0);
}

我得到了以下结果:

    0 0 1 3 1

    0 -1 0 3 1

据我所知,后缀和前缀运算符在分号之后解决,即。原始值在表达式中使用,然后变量自行解析。在这种情况下

     i++ && j++ 

应该等于

      ++i && ++j 

两者都应该等同于

     i && j;
     i = i+1;
     j = j+1;

因此两个表达式的结果必须相同。但事实并非如此。请任何人都可以帮助我解决我在哪里有错误的概念。

4

2 回答 2

3

i++ && j++绝对等于++i && ++j.

以两者都为零的情况为例 - 第一个结果是:

0 && j++

产生 0 结果(并且由于短路, j 甚至不会增加)。

在第二种情况下,你会得到

1 && 1

产生 1 结果。

考虑到这一点,让我们看一下您的示例(为便于阅读而添加的空格、分号和换行符):

  1. 第一:

    int i = -1;
    int j = -1;
    int k =  0;
    int l =  2;
    int m = i++ && j++ && k++ || l++;
    

    让我们首先将括号完全括起来,以便于处理:

    int m = ((i++ && j++) && k++) || l++;
    

    那么,会发生什么?首先,i++. i递增(并变为0),但因为它是后递增,所以表达式的结果是-1. 这给出了:

    int m = ((-1 && j++) && k++) || l++;
    

    由于其左侧&&非零,因此评估右侧。 j++递增j0,但同样,后递增意味着表达式的值为-1

    int m = ((-1 && -1) && k++) || l++;
    

    解决&&

    int m = (1 && k++) || l++;
    

    接下来,剩下的右侧&&k递增,变为1,但表达式产生0

    int m = (1 && 0) || l++;
    

    解决这个问题&&

    int m = 0 || l++;
    

    最后,因为左侧||为 0,所以评估右侧。 l递增,成为3,但作为后递增,产生2

    int m = 0 || 3;
    

    最后:

    int m = 1;
    

    一路走来,我们最终得到:

    i = 0;
    j = 0;
    k = 1;
    l = 3;
    

    解释你的第一个打印输出。

  2. 接下来,让我们看第二个示例(更简洁;如果您需要更多详细信息,请告诉我):

    int i = -1, j = -1, k = 0, l = 2, m;
    m = ((++i && ++j) && ++k) || ++l;   // parenthesized for readability
           ^                            // i is pre-incremented
    m = (( 0  && ++j) && ++k) || ++l;
               ^                        // first && operator short-circuits
    m = (0 && ++k) || ++l;
            ^                           // second && operator short-circuits
    m = 0 || ++l;
              ^                         // l is pre-incremented
    m = 0 || 3;
           ^                            // evaluate || operator
    m = 1;
    

    结果是:

    i =  0
    j = -1
    k =  0
    l =  3
    m =  1
    

    和你看到的打印出来的完全一样。

于 2013-06-07T19:54:36.963 回答
1

问题是您的条件运算符:

m=i++&&j++&&k++||l++;

程序将开始检查条件语句 (i++ && j++),它等于 (-1 && -1),结果为真,因此它继续语句 (true && k++),这意味着 (true && 0) 为假。然后它将检查 OR 条件 (false || l++),这意味着 (false || 2)。每次处理条件时,值都会通过 ++ 运算符递增。

然而,第二个说法...

m=++i&&++j&&++k||++l;

程序启动条件 (++i && ++j),它等于 (0 && ++j)。因此,它立即将第一个条件 ++i 视为错误,并立即将块的其余部分 (m=++i&&++j&&++k) 视为错误,而不是像以前那样处理 ++j 或 ++k不需要,以确定该块将失败。然后它继续到为真的 OR 条件 (false || ++l) 或 (false || 3),m=1。

最后,第二条语句只处理 ++i 和 ++l,而其他语句保持不变。

我会对所谓的“短路”进行一些研究,因为它是描述为什么会发生这种情况的术语。

于 2013-06-07T20:03:30.153 回答