what is the difference between i = i + j
; and i += j
; in C?
Are they equivalent? Is there any side effect of i
?
I was trying to check the assignment mechanism in C using the GCC compiler.
what is the difference between i = i + j
; and i += j
; in C?
Are they equivalent? Is there any side effect of i
?
I was trying to check the assignment mechanism in C using the GCC compiler.
They're almost the same. The only difference is that i
is only evaluated once in the +=
case versus twice in the other case.
i = i + j
is equivalent to i += j
but not same.
In some cases(rare) i += j
differs from i = i + j
because i
itself has a side effect.
Also one more problem is operator precedence i.e
i = i * j + k;
is not same as
i *= j + k;
There is almost no difference, but if i
is a complex expression, it is only computed once. Suppose you had:
int ia[] = {1, 2, 3, 4, 5};
int *pi = &(ia[0]); // Yes, I know. I could just have written pi = ia;
*pi++ += 10;
// ia now is {11, 2, 3, 4, 5}.
// pi now points to ia[1].
// Note this would be undefined behavior:
*pi++ = *pi++ + 10;
The two statements i = i + j
and i += j
, are functionally same, in first case you are using the general assignment operation, while the second one uses the combinatorial assignment operator
. +=
is additive assignment operator
(addition followed by assignment).
The use of combinatorial assignment operators generates smaller source code
that is less susceptible to maintenance errors
and also possibly a smaller object code
where it would also run faster. Compilation is also likely to be a little faster
.
Syntactic sugar baby.
Any differences are just going to come down to compiler implementation.
In both cases i
(the variable or expression being assigned) must be an lvalue. In most simple cases this will yield code that is identical in both cases so long as i
is not declared volatile
.
However there are a few cases where a lvalue can be an expression involving operators, and this may cause evaluation of i
twice. The most plausible example of an lvalue expression that might be used in that way is perhaps simple dereferencing of a pointer (*p
):
*p = *p + j ;
*p += j ;
may generate different code, but it is trivially optimised so I would expect not even without optimisation enabled. Again p
cannot be volatile
, otherwise the expressions are semantically different.
A less plausible scenario is to use a conditional operator expression as an lvalue. For example the following adds j
to b
or c
depending on a
:
(a ? b : c) += j ;
(a ? b : c) = (a ? b : c) + j ;
These might generate different code - the compiler might reasonably not spot that idiom and apply an optimisation. If the expression a
has side effects - for example were the expression getchar() == '\n'
or a
is volatile
(regardless of b
or c
), then they are not equivalent since the second would evaluate to:
c = b + j
for the input "Y\n"
, b = b + j
for input "\n\n"
,c = c + j
for input "YN"
.These points are of course mostly irrelevant - if you write code like that and it does things you did not expect, sympathy may be in short supply!