Operators and Expressions
The type of operations that can be performed on the data objects are specified by the operators.The data items on which an operator acts are called its operands. The operators can be unary, binary or ternary depending upon whether it operates on one, two or three operands. An operator along with its operands constitute a simple expression.A compound expression can be formed by using simpler expressions as operands of the different types of operators.The evaluation order of the operators in an expression will be determined by the operator precedence rules followed in the language.To begin with, let us first consider the arithmetic operators.
The binary arithmetic operators are +, -, *, /, which correspond to addition, subtraction, multiplication and division respectively. The modulus operator %, returns the remainder after integer division. The % (modulus) operator cannot be applied to float or double type data. Arithmetic operators associate left to right.
The binary + and - operators have the same precedence when used in a calculation, but they have lower precedence than*, /, and % operators. To change the order of precedence the brackets () are used.
Example 3.1 :
c=3 + 5 * 2; /* will assign 13 to the variable c*/
c=(3 + 5) * 3;/*will store 24 in the variable c*/
The unary operators + and - have the highest precedence.
Example 3.2 :
c=-b; /* will store -8 into c*/
Example 3.3 :
The following is an example of a complex arithmetic expression which involves multiple arithmetic operators.
int a=2, b=4, c=8, d=9, e;
e= a * b / c - a * 2 + d * 3;
Taking into account the operator precedence given in the Table 3.3, the evaluation of theexpression a*b/c - a*2+d*3 will produce 24, which will be stored in e.
3.2reLATIONAL and LOGICAL OPERATORS
The relational operators supported in C are
Table 3.1: Relational Operators
The relational operators >, <, >=, <= have the same precedence. The equality operator == and the not equal to operator != have lower precedence than the remaining relational operators. The relational operators have lesser precedence than arithmetic operators, so an expression like i < style=""> Similarly it will be treated as true if the evaluation of an expression results in a non-zero value.
Let i=5, j=6, k=7, b=0The following Table 3.2 illustrates the results of evaluation of some relational expressions
Table 3.2 : Expressions with interpretations
The logical operators supported in C are && (and) and || (or). Expressions connected by && and || are evaluated left to right, and evaluation stops as soon as the truth or falsehood of the condition is known.
The unary negation operator returns true if the expression evaluates false (i.e. the evaluation produces zero), true otherwise.
Example 3.5 :
int i=5, j=6, k=7, b=0,e,f;
f=((i + j) <> (k - j)); /* the expression in the right hand side
evaluates to false and a 0 is assigned to f */
e=(k == j+1) || (b > i); /* the expression evaluation produces true; so e gets 1*/
There are two such operators ++ (for pre or post increment) and -- (for pre or post decrement).
Example 3.6 :
i++; /* is equivalent to i=i+1;*/
--i;/* is equivalent to i=i-1*/
/*Here the value of i will be incremented first and then j will be assigned the incremented value, so finally j will get the value 3*/
/*The assignment will take place first then the incrementation. The variable j will receive the old value of i that is 3 and i will come out of that statement with the value of 4*/
Unlike other programming languages such as Pascal or FORTRAN, C treats assignment of values to a variable to be the result of evaluation of the assignment operator(=).The assignment of values to an identifier is done in the following way :
x=i * 3 + j - 5; /* x gets 57 */
k=(i=i + j * 4) - (m / 2); /* note assignment operatoris used in the expression in the right hand side also; k gets 79 */
The following is an example of multiple assignment.
i=j=9; /* is equivalent to j=4; i=j; */
In such cases assignments are carried out from right to left.
Compound Assignment Operators
The compound assignment operators help in writing compact expressions.
For example the following statement,
c=c + 5;
can be written as
c += 5;
f = f * (g + h);
is equivalent tof *= (g+h);
The data type conversion takes place when an operator has operands of different data types. In such cases all operands are converted to a common data type according tosome set of rules. An operand which can take up values of a narrower domain is automatically converted into another operand of wider domain without losing important information, such as converting an integer tofloating point in an expression like f + i (where f is a floating point variable, i is of integer type).
Type conversion of operands helps in preventing data loss. Such data loss can occur when an attempt is made to assign a wider operand (like a floating data) into a narrower one (like int).
Since the char is internally a small integer, the operands of char data type can be extensively used in character arithmetic allowing considerable flexibility in certain kinds of character conversions.
Many operators cause conversions and yield result types in a similar way. The effect is to bring operands into common type, which is also the type of the result. This approach is known as usual arithmetic conversion, and is carried out with the help of the following rules :
*if either operand is long/double, convert the other to long/double.
*if either operand is double, other operands are converted to double, and the result is double
*if either operand is float, convert the other to float.
*char and short get converted to int.
*if either operand is long, convert the other to long
The automatic conversion of data type according to the above mentioned set of rules may cause data loss. Consider the following example :
If f is a float and i is an int, then
would cause conversion of i to a floating point value before assigning to f.But in
the conversion of floating point value of f to int will cause truncation of its fractional part.
Consider another example :
If f is float and i, j are int the following expression,
f=(i / j);
would fail to assign the fractional part of the integer division into the variable f.
Explicit type conversion can be forced in any expression, using a unary operator called a cast.Such type casting is expressed as,
(data type) expression
when the expression is converted to the named data type it may be treated as if the expression was assigned to a variable of the specified type.
If i and f are floating pointvariables, the expression
(i + f) % 2;
is invalid since modulo (%) operator operates on an integer operand (the first operand is of type floating point rather than an integer). The expression
((int) (i + f)) % 2
forces explicitly the first operand (i + f) of modulo (%) to int, and therefore it is valid.
3.6TERNARY OR CONDITIONAL OPERATOR
Simple conditional operations can be performed with a conditional operator (? :). A conditional expression uses the conditional operator andis written in the following manner
The evaluation of such an expression begins with the evaluation ofexpression1. Ifthe evaluation of expression1 returns true (non-zero value)then expression2 is evaluated, otherwise expression3 gets evaluated.
Example 3.7 :
max=(a > b) ? a:b ; /* compares a and b and returns the higher value to max */
result=(a == 0) ? 0 : b /a;/*prevents division byzero*/
3.7 OPERATOR PRECEDENCE
The following table shows operator precedence (in decreasing order) and also associativity of the operators.Thus unary operators have highest precedence whereas assignment operator has least precedence.The operator precedence can be changed in an expression by enclosing the operation and its operand(s) in a parenthesis.