Why does a=(b++) have the same behavior as a=b++?

前端 未结 10 2047
借酒劲吻你
借酒劲吻你 2020-12-06 16:14

I am writing a small test app in C with GCC 4.8.4 pre-installed on my Ubuntu 14.04. And I got confused for the fact that the expression a=(b++); behaves in the

相关标签:
10条回答
  • 2020-12-06 16:52

    The parentheses will not change the post-increment behaviour itself.

    a1=(b1++); //b1=10

    It equals to,

     uint8_t mid_value = b1++; //10
     a1 = (mid_value); //10
    
    0 讨论(0)
  • 2020-12-06 16:53

    However, I expected the parentheses to have b1 incremented before its value is assigned to a1.

    You aren't assigning b1 to a1: you're assigning the result of the postincrement expression.

    Consider the following program, which prints the value of b when executing assignment:

    #include <iostream>
    using namespace std;
    
    int b;
    
    struct verbose
    {
        int x;
    
        void operator=(int y) {
            cout << "b is " << b << " when operator= is executed" << endl;  
            x = y;
        }
    };
    
    int main() {
        // your code goes here
        verbose a;
        b = 10;
        a = b++;
        cout << "a is " << a.x << endl;
        return 0;
    }
    

    I suspect this is undefined behavior, but nonetheless when using ideone.com I get the output shown below

    b is 11 when operator= is executed
    a is 10
    
    0 讨论(0)
  • 2020-12-06 16:54

    Quoting from the C99:6.5.2.4:

    The result of the postfix ++ operator is the value of the operand. After the result is obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate type is added to it.) See the discussions of additive operators and compound assignment for information on constraints, types, and conversions and the effects of operations on pointers. The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.

    You can look up the C99: annex C to understand what the valid sequence points are.

    In your question, just adding a parentheses doesn't change the sequence points, only the ; character does that.

    Or in other words, you can view it like there's a temporary copy of b and the side-effect is original b incremented. But, until a sequence point is reached, all evaluation is done on the temporary copy of b. The temporary copy of b is then discarded, the side effect i.e. increment operation is committed to the storage,when a sequence point is reached.

    0 讨论(0)
  • 2020-12-06 16:54

    OK, in a nutshell: b++ is a unary expression, and parentheses around it won't ever take influence on precedence of arithmetic operations, because the ++ increment operator has one of the highest (if not the highest) precedence in C. Whilst in a * (b + c), the (b + c) is a binary expression (not to be confused with binary numbering system!) because of a variable b and its addend c. So it can easily be remembered like this: parentheses put around binary, ternary, quaternary...+INF expressions will almost always have influence on precedence(*); parentheses around unary ones NEVER will - because these are "strong enough" to "withstand" grouping by parentheses.

    (*)As usual, there are some exceptions to the rule, if only a handful: e. g. -> (to access members of pointers on structures) has a very strong binding despite being a binary operator. However, C beginners are very likely to take quite awhile until they can write a -> in their code, as they will need an advanced understanding of both pointers and structures.

    0 讨论(0)
  • 2020-12-06 16:58

    However, I expected the parentheses to have b1 incremented before its value is assigned to a1

    You should not have expected that: placing parentheses around an increment expression does not alter the application of its side effects.

    Side effects (in this case, it means writing 11 into b1) get applied some time after retrieving the current value of b1. This could happen before or after the full assignment expression is evaluated completely. That is why a post-increment will remain a post-increment, with or without parentheses around it. If you wanted a pre-increment, place ++ before the variable:

    a1 = ++b1;
    
    0 讨论(0)
  • 2020-12-06 17:02

    Your expectations are completely unfounded.

    Parentheses have no direct effect on the order of execution. They don't introduce sequence points into the expression and thus they don't force any side-effects to materialize earlier than they would've materialized without parentheses.

    Moreover, by definition, post-increment expression b++ evaluates to the original value of b. This requirement will remain in place regardless of how many pair of parentheses you add around b++. Even if parentheses somehow "forced" an instant increment, the language would still require (((b++))) to evaluate to the old value of b, meaning that a would still be guaranteed to receive the non-incremented value of b.

    Parentheses only affects the syntactic grouping between operators and their operands. For example, in your original expression a = b++ one might immediately ask whether the ++ apples to b alone or to the result of a = b. In your case, by adding the parentheses you simply explicitly forced the ++ operator to apply to (to group with) b operand. However, according to the language syntax (and the operator precedence and associativity derived from it), ++ already applies to b, i.e. unary ++ has higher precedence than binary =. Your parentheses did not change anything, it only reiterated the grouping that was already there implicitly. Hence no change in the behavior.

    0 讨论(0)
提交回复
热议问题