Pages

Operator precedence

Precedence of Operators 
The precedence of operators is a rule which decides the sequence (or order) in which operators are solved. Operators are solved in highest to lowest precedence order.
   

The Order of Evaluation
In an expression containing different kind of operators, the correct order of evaluation must be followed so that the outcome is correct. There is a description of rules that how an expression is solved by your program.
  1. The expressions in parenthesis and function calls are solved first. If parentheses are nested then they are solved in inner to outer order.
  2. Then increment and decrement operators are solved. If postfix form is used, then the variable is replaced by its original value. If prefix form is used then the variable is replaced by its modified i.e. incremented value.
  3. All typecasting are performed.
  4. Then arithmetic operators are solved. Multiplication, Division and Modulus are solved first. Then Addition and Subtraction operators are solved. If two or more operators have same precedence level then they are solved according to associativity rule.
  5. All relational operators are solved. <, >, <= and >= are solved first. Then = = and != are solved.
  6. All logical operators are solved. AND operator is solved first. Then OR is solved.
  7. If, conditional operator is present then it is solved.
  8. At last assignment operators are solved.     
Type Conversions in C
Type conversion refers to the conversion of one data type into other. This either happens automatically or performed by user. When this happens automatically, it is called Automatic Type Conversion (or Implicit Type Conversion). But when performed by user is called User Defined Type Conversion (or Explicit Type Conversion). Automatic type conversion includes Type PromotionType Demotion and Truncation. Whereas User defined type conversion includes typecasting - which involves the uses the cast operator

Automatic Type Conversions
All types of automatic type conversions are actually performed by compiler. This process is called Coercion. Each type of automatic type conversion is discussed here in detail. 

Type Promotion in Expressions
Data types can be arranged into “lower to higher” order. A lower data type is the one which has small memory size and range, and a higher data type is the one which has large memory size and range. Therefore character is the “lowest” data type and double is the highest one. The Hierarchy of Data types can be easily understood from the following diagram.    
Type Promotion

                                                                
Type promotion refers to the conversion of a lower data type into higher one, directly. This frequently occurs in expression when a lower data type is operated with higher one. A character is converted to integer directly, an integer is converted to float or double. And a float is converted to double. Therefore, in an expression which contains different types of variables the result is obtained in higher data type.
Consider the following declarations –
char ch = ’A’;
int i = 5;
float f = 25.25f;
double d = 225.25;
double result;
Now consider a statement, build using these variables –
result = (ch / i)  + (f / i) + (d / f) + (d / i);
The expression in right hand side is solved like this– the ch in sub expression (ch/i) replaced by the ASCII value of ’A’ that is 65. Then it is operated with the value of i, 5. The i in sub expression (f / i) is replaced by 5 and this 5 is promoted to float 5.0. The f in sub expression (d / f) is replaced by the value 25.25f and this is promoted to double 25.25. The i in sub expression (d / i) is replaced by its value 5 and then this is promoted to double 5.0. The results obtained in each sub expression are 13, 5.05, 8.920792, and 45.05.
Now, they are added. Integer 13 is added with float 5.05 gives float 18.05. This float 18.05 is added with double 8.920792, gives a double value 26.970792. Again, this double value 26.970792 is added with double 45.05, gives the final result 72.020792 as double. Hence the final result obtained as double which was the highest data type in the original expression.       
This is how it happens –


Type Promotion in Assignments
When a lower data type is assigned to higher one the value of lower data type is first promoted and then stored in the higher data type. For example, if x is a integer variable with value 50 and y is a real (float or double) variable then on writing the statement –
y = x;
the value of x is first replaced at RHS and promoted to 5.0. As shown here –
y = 5.0;
Now, it will be assigned to y. The value in x will remain 5.
When you assign a character to integer the ASCII value of that character is assigned to the integer.
This is shown here –
char ch = ’A’;
int x;
x = ch; // assigning ch to i will assign the ASCII value of ’A’ i.e. 65, to x
printf(“Value of x = %d”,x);
The output is:
Value of x = 65
Type Demotion
Type Demotion occurs when a higher data type is assigned to a lower one. In this case the value of the higher data type is so converted that it can fit into the lower data type. For example, an integer is always capable to hold all type of character i.e. ASCII values. But character is not enough to hold all type of integer values. Therefore, when you assign an integer value to a character, the value is so converted (i.e. demoted) that it can fit into the character. If x is an integer with value 200 and ch is a character variable, then on assigning x to ch the value of x, 200 will be converted to fit into ch. For this 256 is subtracted from 200 this gives -56. This is in the range of character. Following example illustrates this thing.
/* Proram to illustrate type demotion */
     #include<stdio.h>
     #include<conio.h>

     int main(void)
     {
        char ch;
        int x = 200;
        clrscr();
        ch = x;
        printf("The value of ch = %d",ch);
        getch();
        return 0;
     }
     Output is –
     The value of ch = -56

From the above example it is clear that you must use integer variables to hold values which are out of character’s range. In the above example the value chosen is 200. Clearly, it is outside the range of character (-128 to +127). That’s why type demotion occurred.  If the value were within the range of character, for example 100, then no type demotion would occur.    
In case of integers, when a value out of range is assigned to the variable, 65536 is subtracted from that value so that it can fit into integer. For example if you assign 40000.00 to an integer, the integer will get
-25536, which has been calculated as 40000 – 65536. Here is the program to illustrate this.
/* Program to illustrate type demotion */

     #include<stdio.h>
     #include<conio.h>

     int main(void)
     {
        int x = 40000.00;
        clrscr();
        printf("The value of x = %d",x);
        getch();
        return 0;
     }

     Output is –
     The value of x = -25536

From the above program it is clear that you must use float or double variables to hold values which are out of integer’s range. In chapter 7 you will study how to modify the range and memory size of a data type so that it can fulfill our needs. You will learn the techniques that can make an integer to hold a value which is outside the range -32768 to + 32767.
The Secret of 256 and 65536
Truncation
When you assign a real value to an integer the fractional component of that real gets lost and the integer portion is assigned to the integer. This is known as truncation. For example, if you assign 27.36 to an integer i than i will get only 27, the fractional part .36 will lost. Here is the code to clear this –

int i;
i = 27.26;
printf(“Value of i = %d”,i);
The output is –
Value of i = 27

User Defined Type Conversions (or Explicit Type Conversions or Typecasting)
User defined type conversions or explicit type conversions are actually called typecastingTypecasting refers to the conversion of one data type into other, explicitly. The mechanism of typecasting uses cast operator. The cast operator is actually the type conversion operator. Using this, you can convert one type into other, or more specifically, a value of one type into a value of another type. The general form of cast operator is –
(target type) operand
Target type is the data type required. And operand is the variable or constant that you want to cast into the target type. Remember that cast is a unary operator.
Consider a declaration of x and y –
int x = 10, y = 3;
When x is divided by b, the result would be 3.i.e the integer quotient because x and y both are integer here. On writing x/y the result would be always 3 (not 3.33….).  Suppose, you want to obtain the real quotient i.e. 3.33…. For this, either x or y must be declared as real (i.e. float or double). But it is possible that the rest of the program’s code might not permit this. Or changing the type of x or y (from int to float or double) would affect the other parts of the program –  for example – if you are calculating x % y somewhere in your program, then changing x and/or y from int to float, will make this calculation illegal. In this situation, you must use a cast to temporary change the value of x or y from integer to float (or double), just for the purpose of division. And this cast will not change the actual type of x and y.     
The division x / y now, would be written as –
(float) x / y
this would generate the required quotient 3.33…..   See, the x is preceded by the float keyword surrounded in parenthesis. This is the cast operator which will change the value of x from integer to float. Not permanently, just for the purpose of division. And x will remain an integer after this typecasting. Here is the step by step description that shows the working of the cast operator.
  • (float) x / y                typecasting of x to float
  • (float) 10 / 3              values of x and y are replaced
  • 10.0 / 3                      the 10 is now 10.0, cast has been done
  • 3.333333                   the required result

The same result can be obtained by applying the cast to y, instead of x. This is shown here –
  •  x / (float) y                  typecasting of y to float
  •  10 / (float) 3                values of x and y are replaced
  • 10 / 3.0                        the 3 is now 3.0, cast has been done
  • 3.333333                     the required result

Now, consider one more case. If x and y declared as –
float x = 10.0f, y = 3.0f;
Then the result of x / y would always be 3.33333. To perform an integer division, both x and y will require a cast to integer. Changing either x or y, would not generate the desired result. Because casting a single operand into integer would let the other to remain a real. And the division will generate a real quotient, because, when an integer is operated with a real the result comes as real. So, x and y both must be cast to integer. This is shown here.
  •  (int) x / (int) y              casting of x and y both to integer
  •  (int) 10.0 / (int) 3.0      values of x and y are replaced
  • 10 / 3                           10.0 and 3.0 are now 10 and 3, cast has been performed
  •  3                                  3 is the required result, the quotient of integer division

Here is the program that shows the casting of integer to float
/* Explicit Conversion of integer to float */

     #include<stdio.h>
     #include<conio.h>

     int main(void)
     {
        int x = 10, y = 3;
        float quotient;
        clrscr();
        printf("x = %d y = %d\n",x,y);
        quotient = (float) x / y;
        printf("quotient = %f",quotient);
        getch();
        return 0;
     }
            The output is –
     x = 10 y = 3
     quotient = 3.333333
Please note that in the above program it is necessary to define the quotient as float. Because
(float) x / y would give the result 3.333333.
And here is the program that shows the casting of floats to integer.
/* Explicit Conversion of floats to integer */

     #include<stdio.h>
     #include<conio.h>

     int main(void)
     {
        float x = 10.0, y = 3.0;
        int quotient;
        clrscr();
        printf("x = %f y = %f\n",x,y);
        quotient = (int) x / (int) y;
        printf("quotient = %d",quotient);
        getch();
        return 0;
     }
The output is –
     x = 10.000000 y = 3.000000
     quotient = 3

Overflow and Underflow in Expressions

As you know all data types have predefined ranges. In expressions, when a resultant value of an operation exceeds the maximum value defined in the range, this is called overflow, and when it is below the minimum value in the range, this is called underflow.   

For example, consider three integer variables declared as –
int x = 20000, y = 30000, z;
Suppose, you want to add x and y and store the result in z.  Simply, you will write this –
z = x + y;
To, print the result of x + y you will write this –
printf(“x + y = %d”,z);
But here is the output –

Strange! It is not 50000. Why? The reason is simple. When the expression x + y is evaluated values of x and y are obtained and added. Adding 20000 and 30000 generates the result 50000. But, according to the rules of the language, the result of the operation between two integers must be an integer. You may ask 50000 is indeed an integer then what’s the problem. Just think about the range of integer. It is -32768 to +32767. So the resultant integer must be in the range. Here, 50000 exceed the maximum value of the range. So, to fit it into the range, 65536 is subtracted. This gives -15536, and then it is assigned to z. The value of z is then printed.  Since the result of the expression x + y has cross the maximum value of the range, we will say that an overflow has occurred. 

Next : Relational Operator
Previous : Arithmetic Operators 

No comments:

Post a Comment