++ & -- Operators in C

Increment (++) and Decrement (--) Operators in C


Though we are familiar with these operators, specially their uses in for loops are widely known, but at many occasions you may find it puzzling in some way. Some increment/decrement operations are fully dependent on how the compiler handles it. I shall give some examples below which may seem confusing. But before that, here I want to say a couple of lines about these 2 operatos.

Both increment and decrement operators take same precedence or priority in the precedence table. Both  ++ and -- are unary operators, that means they can be used only with one variable. For example,if you say a++b; it will be a wrong statement.

Placing   ++ or  -- before or after a variable makes different senses. Remeber the following lines.

a++;     Means,Do the job with value in a,then increment it by 1.
++a;     Means,Increment a by 1,then do the job with the new value in a.

Suppose you are given with following kind of expression.

example 1:
main()

 int a=5,b; b= a++  +  a++; printf(“\n b=%d”,b);
}

The output will be b=10 in Turbo C where the sum is calculated taking variable a’s current value i.e 5. So, 5 is added to 5 giving the resulting output to 10 which is stored in variable b. After the sum operation, finally variable a is incremented twice to come to 7.

The above example may give different result in different C compiler. For example, in PHP, the above increment statements would have evaluated as shown below.

$a = 5;
$b = $a++ + $a++; 

Here, for the summation, 5 is taken as first operand [value of $a] and then $a is incremented to 6 .. hence the 2nd operand is 6 producing the final output 5+6 = 11. $a is incremented again to 7.

example 2:
main()
{
 int x=3,w,y,z;
 w = x++ +10;
 /* do the job with current value 3, then increment it*/
 y=x-- -111;
 /* do the job of subtraction, then decrement */
 /* x is again 3 */
 z=x++ + ++x; 
 printf(“\n x=%d,w=%d,y=%d,z=%d”,x,w,y,z);

}
Here is output of the program: x=5,w=13,y=-107,z=8 in Turbo C.
In the  statement z=x++ + ++x; x is incremented once due to prefix notation (++x) which causes x to become 4, then the sum is done giving 4 + 4 = 8 which is assigned to z. Next, post-fix notation increments the x again to 5.

One similar example goes here..

example 3:
main()
{
 int z, x = 5, y = -10, a = 4, b = 2; 
 z =  x++ + ++y * b / a;
 printf(“\n z=%d”,z);
}

output: z = 1
explanation:    
z = 5 + (-9) * 2/4;      =>      z= 5 + (-18)/4;     =>   z=5+ (-4) ;  =>   z=1;
In the division between –18 and 4, result will be always a integer as both are so. So actual result –4.5 will be taken as –4.

example 4:
main()
{
int x=2,w=2,y=3,z=9;
w+=z+=y+=x+=++x*x++ + ++z;
printf(“\n w=%d,x=%d,y=%d,z=%d”,w,x,y,z);
}
Here is the output in Turbo C : w=38, x=23, y=26, z=36. Same output is given in PHP.

Explanation:
The most complex statement [line 4] can be re-written as shown below:

$x += ++$x*$x++ + ++$z;
$w += $z+= $y+= $x;

Which can be again broken into following lines :

temp = ++x * x++ + ++z; //[ $temp is used as temporary variable ]
x = x + temp;
y = y + x;
z = z + y;
w = w + z;
1. temp = (++x)*(x++)+ (++z); => temp = 3 * 3 + 10 => (x gets new value 4, temp becomes 19, z becomes 10)
2. x = x + temp; => x = 4 + 19 => x = 23 
3. y += x;  => y = 3 + 23 = 26 
4. z += y;  => z = 10 + 26 = 36 
5. w += z;  => w = 2 + 36 = 38


example 5:
main()
{
int a=12,b,c,d,e,f,g,h;         
b=a++;                              
c=a--;                                
d=a+b;     /* a is 12 */
e=(a++)+b; /* e becomes 24 */          
f=++e+c;   /* e is incremented to 25 */                           
g=++f;
h=f++;
printf("\n a=%d,b=%d,c=%d,d=%d,e=%d,f=%d,g=%d,h=%d",a,b,c,d,e,f,g,h);
}
Output : a=13, b=12, c=13, d=24, e=25, f=40, g=39, h=39

Example 6:
main()
{

int i=12;
i=i++ + i++ + i++;   
/* same as i=(i++)+(i++)+(i++);do the job of summation,then increment thrice */
printf("\n i=%d",i); // result 36
i=(--i)-(--i);   
/* decrement twice first, then do the subtraction, result 0*/
printf("\n i=%d",i);                 

i=i++;     /* i becomes 1 */
/* do assignment,then increment */

++i=i++;          
/* illegal statement,it means (i=i+1)=(i=i+1); which has no significance at all */                 

i=(i-2)++;        
/* invalid statement.it means i=(10)++; 10++ isn't possible at all. */

i=i++ + i--;      
/* do the sum,then increment & decrement. i's value ultimately doesn't get changed*/                   

i=++(++i);      
/* Erroneous, it’s same as i=++(constant Integer); which isn’t possible*/

printf("\n %d",i);
}

Explanation:
The statements above are already explained. One thing I need to say is, complier searches for longer operators first in statements like :
i = --i---i;
which will be accepted as i = --i-- -i; which is a invalid statement. Compiler searches for a operator taking longer token from the string “---“ and comes up with “--” first, then “-”. That’s why the problem arises.

More examples are given below.

Example:7 
main()
{
 int a=2,b;
 b=a++ +  ++a +  ++a;   
 /* first increment 'a' twice, then do the sum with that*/
 printf("\n a=%d,b=%d",a,b);
}

Explanation : It will be a=5,b=12. The expression has two ++a, so before doing the sum, it increments “a” twice to get 4, then the sum becomes

(4+4+4)=12,so 12 is assigned to b. “a” is again incremented (a++) to get a value of 5. So, “a” is now 5 and “b” is 12.

As I have already discussed that this type of complicated operations will result as per compiler implementation. For example in PHP, the output is “a=5, b=11”. If you run the above code in codepad.org’s code console, it would give “a=5, b=10”

Example:8
main()
{
 int a=2,b,c,d,e;
 b=a++ *a++ *a++;
 /* first do the multiplication ,then increment thrice */
 c=++a*++a*++a;
 /* increment a thrice, then multiply */
 d=c+++c;           
 /* same as d = c++  +  c;  Do summation first, then increment */
 e=(++d?d++:d--)+d--;  /* one confusing portion,explained below*/
 printf("\n a=%d,b=%d,c=%d,d=%d,e=%d",a,b,c,d,e);
}

Explanation:
After b=a++*a++*a++;  => b = 8(2*2*2)   => a=2+1+1+1 = 5 (thrice increment)
After c=++a*++a*++a;  => a=5+1+1+1=8 (increased thrice),  c=8*8*8 = 512
After d=c+++c; =>  d=c+c=1024, c is incremented to 513
The toughest part is  e=(++d?d++: d--)+d--; First d is incremented (Blue coloured part) to 1025, conditional operator checks whether 1025 is true or false.1025 is a true value, hence control Goes to green part, and then happens one very interesting thing. The green part d++ says that you do the job with its current value, then increment d. So you take d (current value is 1025) for the job of summation and increment it to 1026.Now control comes to the pink part d-- . Here it says that you do the job (summation) first, then decrement it. But remember that now d=1026 as result of a statement having conditional operator. So, do sum of 1025 & 1026 resulting to 2051,then you decrement d (current value 1026) to 1025. So e gets a value of 2051.
Ultimate output: a=8,b=8,c=513,d=1025,e=2051 in Turbo C. Though CodePad.org says it is “a=8,b=8,c=393,d=785,e=1571”

Example:9
main()
{
 int a,b;
 a=1;
 printf(" a=%d", a++ * a++ * a++);
 printf("\n a=%d",a);
}

What will be the answer? The answer would be 6,4. The explanation just contradicts what we have learned so far because C only guarantees the evaluation of expression like "a++ * a++ * a++" before sending it to a function. It does not guarantee the order in which such expressions will be evaluated. Thus, the concept of  “do the job then increase” won’t do here. a++ * a++ * a++ = 1 ( increase a to 2) * 2 ( increase a to 3 )* 3 ( increase a to 4) = 1 x 2 x 3=6. And ultimately a gets a value of  4. However the codepad.org says it is “a=1 a=4” which we had expected earlier.

Take another example ::

int a = 10;
func(a++,a++);

C does not guarantee that the function func would be called with parameters (10, 11) or (11, 10).

No comments: