Operators and Expressions

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.

3.1 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 :

int c=0;b=8;

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 the expression a*b/c - a*2+d*3 will produce 24, which will be stored in e.

1. Suppose x, y and z are integer variables that have been assigned the values x=18, y=3 and z=-3. Determine the value of each of the following arithmetic expressions.

(a) x + y * z (d) x % (y * x) (g) x + y /z (j) x * (z % y)

(b) 2 * x +4 - (y -z) (e) x / z (h) x * (y/z)

(c) x / y + z (f) x % z + 1 (i) (x * z) % y -1















3.2 reLATIONAL and LOGICAL OPERATORS

The relational operators supported in C are

>

greater than

<

less than

==

equal to

!=

not equal to

>=

greater than equal to

<=

less than equal to

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.

Example 3.4 :

Let i=5, j=6, k=7, b=0 The following Table 3.2 illustrates the results of evaluation of some relational expressions

Expression

Interpretation

Value

i <>

true

1

(j + k) < (i + 5)

false

0

(j == 6)

true

1

(!b)

true

1

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*/

3.3 inCREMENT/DECREMENT OPERATORS

There are two such operators ++ (for pre or post increment) and -- (for pre or post decrement).

Example 3.6 :

int i=2,j=0;

i++; /* is equivalent to i=i+1;*/

--i;/* is equivalent to i=i-1*/

j=++i;

/*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*/

j=i++;

/*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*/


3.4 assignment operator

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 :

= ;

i=15;

j=17;

m=8;

x=i * 3 + j - 5; /* x gets 57 */

k=(i=i + j * 4) - (m / 2); /* note assignment operator is 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;

Similarly

f = f * (g + h);

is equivalent to f *= (g+h);

3.5 Type conversion

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 to some 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 to floating 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

f=i;

would cause conversion of i to a floating point value before assigning to f. But in

i=f;

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 point variables, 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. Consider a C program having the following declarations:

int a, b;

long l;

short k;

float x;

double d;

char c;

Identify the data type of each of the following expressions:

(a) a * c (d) ((int ) d) + l (g) a+ l + b

(b) x + c (e) a * x (h) -k + c

(c) d + x (f) k - b (i) l + c











3.6 TERNARY OR CONDITIONAL OPERATOR

Simple conditional operations can be performed with a conditional operator (? :). A conditional expression uses the conditional operator and is written in the following manner

expression1 ? expression2 : expression3 ;

The evaluation of such an expression begins with the evaluation of expression1. If the 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 by zero*/

4. For a C program having the following declarations and initial assignments:

int i = 9, j = 5, k;

float x = 0.05, y = - 0.001, z;

char a, b = ‘b’, c = ‘c’ , d = ‘d’;

Determine the value of each of the following assignment expressions. Use the values originally assigned to the variables for each expression.

(I) k = (i + j) / y (ii) i + = (j - 3)

(iii) z = (x + y)/i (iv) k = z = y

(v) k = (j ==6) ? i : j (vi) i = -j

(vii) k = (j > 3) ? i: j (viii) k *= (x * y)

(ix) y -= -x (x) z = (x >0.1) ? x : d

(xi) x *= 2 (xii) z = k / (j + 1)

(xiii) i/ = j (xiii) a = (c <>

(xiv) a= b =d (xv) i -= (j >= 3) ? j : i















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.

Operator category

Operators

Associativity

unary operator

- ++ -- ? sizeof (type)

R ®L

arithmetic operator multiply , divide and remainder

* / %

L®R

arithmetic operator add and subtract

+ -

L®R

relational operators

< <= > >=

L®R

equality operators

== !=

L®R

logical and

&&

L®R

logical or

||

L®R

conditional operator

? :

R®L

assignment operator

= += -= *= /= %=

R®L

Table: 3.3 Operator precedence

0 comments: