如何解决后缀和前缀运算符表达式?

时间:2013-06-07 19:51:40

标签: c logical-operators postfix-operator prefix-operator

我写了以下代码:

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

因为我知道postfix和前缀运算符在分号后解析,即。原始值在表达式中使用,然后变量自行解析。 在那种情况下

     i++ && j++ 

应该等于

      ++i && ++j 

两者都应该等同于

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

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

2 个答案:

答案 0 :(得分: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++j增加到0,但同样,后增量表示表达式的值为-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
    

    你看到的正好是打印出来的。

答案 1 :(得分:1)

问题在于您的条件运算符:

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

程序将开始检查条件语句(i ++&& j ++),它等同于(-1&& -1),这是真的,因此它继续声明(true&& k ++) )这意味着(真&& 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,而其他语句没有被触及。

我会对一些叫做“短路”的事情进行一些研究,因为这个术语描述了为什么会发生这种情况。