Is \(a+(b+c)\) same as \((a+b)+c\)?

Not necessary!

In any reasonably complex expression, there arises a choice as to the order in which to evaluate the parts of the expression: 

(1+1)+(3+3)may be evaluated in the order 

  • (1+1)+(3+3)(2)+(3+3)(2)+(6)(8), or in the order 
  • (1+1)+(3+3)(1+1)+(6)(2)+(6)(8).

Formally, a conforming C compiler may evaluate expressions in any order between sequence points (this allows the compiler to do some optimization). Sequence points are defined by:

  • Statement ends at semicolons.
  • The sequencing operator: a comma. However, commas that delimit function arguments are not sequence points.
  • The short-circuit operators: logical and (&&, which can be read and then) and logical or (||, which can be read or else).
  • The ternary operator (?:): This operator evaluates its first sub-expression first, and then its second or third (never both of them) based on the value of the first.
  • Entry to and exit from a function call (but not between evaluations of the arguments).

Expressions before a sequence point are always evaluated before those after a sequence point. In the case of short-circuit evaluation, the second expression may not be evaluated depending on the result of the first expression. For example, in the expression (a() || b()), if the first argument evaluates to nonzero (true), the result of the entire expression cannot be anything else than true, so b() is not evaluated. Similarly, in the expression (a() && b()), if the first argument evaluates to zero (false), the result of the entire expression cannot be anything else than false, so b() is not evaluated.

The arguments to a function call may be evaluated in any order, as long as they are all evaluated by the time the function is entered. The following expression, for example, has undefined behavior:

 printf("%s %s\n", argv[i = 0], argv[++i]);

Undefined behavior

An aspect of the C standard (not unique to C) is that the behavior of certain code is said to be "undefined". In practice, this means that the program produced from this code can do anything, from working as the programmer intended, to crashing every time it is run.

For example, the following code produces undefined behavior, because the variable b is modified more than once with no intervening sequence point:

#include <stdio.h>
 
int main(void)
{
    int  a, b;
    int c;
    
    c = 1; 
    a = c++ + ++c;
    
    c = 1;
    b = ++c + c++;

    printf("%d\t%d\n", a, b);

    c = 1;
    printf("%d\t%d\t%d\n", c++ + ++c,  c++ + ++c, ++c + c++);
    return 0;
}

Because there is no sequence point between the modifications of c in "++c + c++", it is possible to perform the evaluation steps in more than one order, resulting in an ambiguous statement.

Different systems will have different results:

Running on Codepad.org: http://codepad.org/ALAyZC2u

Running on ideone.com: https://ideone.com/KHxT2b

This can be fixed by rewriting the code to insert a sequence point in order to enforce an unambiguous behavior, for example:

a = c++;
a += c++;

You have no rights to post comments