In order to perform different kinds of operations, C uses different kinds of operators. An operator indicates an operation to be performed on data that yields a value. Using various operators in C one link the variables and constants. An operand is a data item on which operators perform the operations. C is rich in the use of different operators. C provides four classes of operators. They are 1) Arithmetic 2) Relational 3) Logical 4) Bitwise. Apart from these basic operators, C also supports additional operators.
3.1 Types of operators
Type of Operator Symbolic Representation
Arithmetic operators + , -, *, / and %
Relational operators >,<,= =,>=.<= and !=
Logical operators &&, II and !
Increment and decrement operator ++ and --
Assignment operator =
Bitwise operators &,I,",»,«and -
Comma operator ,
Conditional operator ? :
3.2 PRIORITY OF OPERATORS AND THEIR CLUBBING
Various relational operators have different priorities or precedence. If an arithmetic expression contains more operators then the execution will be performed according to their priorities. The precedence is set for different operators in C.
List of operators with priority wise (hierarchical) are shown in Table 3.2.
Table 3.2 List of operators with priority wise
Operators Operation Clubbing Priority
. Function call
Array expression or square bracket
Structure Operator Left to right 1st
type Unary plus
Size of an object
Type cast Right to Left 2nd
Modular division Left to Right 3rd
Subtraction Left to Right 4th
>> Left shift
Right Shift Left to Right 5th
>= Less than
Less than or equal to
Greater than or equal to Left to Right 6th
Inequality Left to Right 7th
& Bitwise AND Left to Right 8th
^ Bitwise XOR Left to Right 9th
| Bitwise OR Left to Right 10th
&& Logical AND Left to Right 11th
|| Logical OR Left to Right 12th
? : Conditional operator Right to Left 13th
=,*=,-=, &=,+=,^=, |=,<<=, >>= Assignment operator Right to Left 14th
, Comma operator Left to Right 15th
1) When two operators of the same priority are found in the expression, precedence is given to the extreme left operator.
3.3 COMMA AND CONDITIONAL OPERATOR
1) Comma operator (,) The comma operator is used to separate two or more expressions. The comma operator has the lowest priority among all the operators. It is not essential to enclose the expressions with comma operators within the parenthesis. For example the statements given below are valid.
2) Conditional operator (?) The conditional operator contains a condition followed by two statements or values. If the condition is true the first statement is executed otherwise the second statement.
The conditional operator (?) and (:) are sometimes called ternary operators because they take three arguments. The syntax of conditional operator is as given below.
Condition? (expression1): (expression2);
Two expressions are separated by a colon. If the condition is true expression1 gets evaluated otherwise expression 2. The condition is always written before? Mark.
3.4 ARITHMETIC OPERATORS
There are two types of arithmetic operators. They are 1) Binary Operator and 2) Unary Operator
a) Binary operator Table 3.3 shows different arithmetic operators that are used in 'C'. These operators are commonly used in most of the computer languages. These arithmetic operators are used for numerical calculations between the two constant values. They are also called as Binary Arithmetic Operators. The examples are also shown in the Table 3.3 In the program variables are declared instead of constants.
Table 3.3 Arithmetic operators
Arithmetic Operators Operator Explanation Examples
+ Addition 2+2=4
- Subtraction 5-3=2
* Multiplication 2*5=10
/ Division 10/2=5
% Modular Division 11%3=2 (Remainder 2)
b) Unary Operators Unary operators are increment operator (++), decrement (- -) and minus (-) . These operators and their descriptions are given in the Table 3.4.
Table 3.4 Unary arithmetic operators
Operator Description or Action
& Address Operator
Size of Gives the size of variable
a) Minus (-) Unary minus is used to indicate or change the algebraic sign of a value.
b) Increment (++) & Decrement (--) Operators The C compilers produce very fast efficient object codes for increment and decrement operations. This code is better than generated by using the equivalent assignment statement. So, increment and decrement operators should be used whenever possible. •
The operator ++ adds one to its operand. Whereas the operator - - subtracts one from its operand. For justification x=x+1 can be written as x++; and x=x-1; can be written as x--;. Both these operators may either follow or precede the operand. That is, x=x+ 1; can be represented as x++; 01 ++x;
If ++ or - are used as a suffix to the variables name then the post increased / decreased operations take place. Consider an example for understanding ++ operator as a suffix to the variable.
In the above equation the current value of y is used for the product. The result is 200, which is assigned to 'z'. After multiplication, the value of y is increased by one.
If “++" or "-“are used as a prefix to the variable name then pre increment/ decrement operations take place. Consider an example for understanding "++" operator as a prefix to the variable.
In the above equation the value of y is increased and then used for multiplication. The result is 220, which is assigned to 'z'.
The following programs can be executed for verification of increment and decrement operations.
c) Size of 0 and '&' Operator The size of ( ) operator gives the bytes occupied by a variable. The number of bytes occupied varies from variable to variable depending upon its dab types.
The '&' operator prints address of the variable in the memory. The example given below illustrates the use of both the operators.
3.5 RELATIONAL OPERATORS
These operators are used to distinguish between two values depending on their relations. These operators provide the relationship between the two expressions. If the relation is true then it returns a value 1 otherwise 0 for false relation. The relational operators together with their descriptions, example and return value are described in Table 3.5.
Table 3.5 Relational Operator
Operators Description or Action Example Return Value
> Greater than 5>4 1
< Less than 10<9 0
<= Less than or equal to 10<=10 1
>= Greater than equal to 11>=5 1
= = Equal to 2==3 0
! = Not equal to 3!=3 0
The relational operator's symbols are easy to understand. They are self-explanatory. However readers benefit a program is illustrated below.
3.6 LOGICAL OPERATORS
The logical relationship between the two expressions are checked with logical operators. Using these operators two expressions can be joined. After checking the conditions it provides logical true (1) or false (0) status. The operands could be constants, variables, and expressions. The Table 3.6 describes the three logical operators together with examples and their return values.
Table 3.6 Logical Operators
Operator Description or Action Example Return Value
&& Logical AND 5>3 && 5<10 1
|| Logical OR 8>5 || 8<2 1
! Logical NOT 8 ! = 8 0
From the above table following rules can be followed for logical operators.
1) The logical AND (& &) operator provides true result when both expressions are true otherwise 0.
2) The logical OR (I I) operator provides true result when one of the expressions is true otherwise 0.
3) The logical NOT operator (!) provides 0 if the condition is true otherwise 1.
3.7 BITWISE OPERATORS
C supports a set of bitwise operators as listed in the Table 3.7. C supports six bit operators. These operators can operate only on integer operands such as int, char, short, long int etc.
Table 3.7 Bitwise operators
>> Right shift
<< Left shift
^ Bitwise xor (Exclusive OR)
~ One's complement
& Bitwise AND
| Bitwise OR
You have now studied the various operators such as arithmetic, logical and relational which are essential to write and execute programs. The precedence of the operators in the arithmetic operations furnished in the form of a table. The conditional & comma operators and programs on them, also described in this chapter. You are made aware of the logical operators OR, AND and NOT. Full descriptions on bit wise operators have been illustrated. Numerous Simple examples have been provided to the users to understand the various operators. The reader is expected to write more programs on this chapter.
Answer the following questions.
1. Explain different types of operators available in C?
2. What are the uses of comma (,) and conditional (?) operators?
3. What are Unary operators and their uses?
4. Describe logical operators with their return values?
5. Distinguish between logical and bitwise operators.
6. What are the relational operators?
7. What is the difference between '=' and '= = ‘?
8. What are the symbols used for a) OR b) AND c) XOR d) NOT operations?
9. Explain the precedence of operators in arithmetic operations?
10. List the operators from higher priority to least priority?
11. What is the difference between %f and %g?
12. What is the difference between division and modular division operations?
13. What are the ASCII codes? List the codes for digits 1 to 9, A to Z and a to z.
We have already seen that individual constants, variables, array elements and function references joined together by various operators to form expressions. We have also mentioned that C includes a number of operators which fall into several different categories. In this chapter we examine certain of categories in detail. Specifically, we will see how arithmetic operators, unary operators, relational and logical operators, assignment operators and the conditional operator are used to form expressions.
The data items that operators act upon are called operands. Some operators require two operands, while others act upon only one operand. Most operators allow the individual operands to be expressions. A few operator permit only single variables as operands (more about this later).
3.1 ARITHMETIC OPERATORS
There are five arithmetic operators in C. They are
% remainder after integer division
The %operator is sometimes referred to as the modulus operator.
There is no exponentiation operator in C. However, there is a library function (pow) to carry out exponentiation (see Sec.3.6).
The operands acted upon by arithmetic operators must represent numeric values. Thus, the operands can be integer quantities, floating-point quantities or characters (remember -that character constants represent integer values, as determined by the computer's character set). The remainder operator (%) requires that both operands be integers and the second operand be nonzero. Similarly, the division operator (I) requires that the second operand be nonzero.
Division of one integer quantity by another is referred to as integer division. This operation always results in a truncated quotient (i.e., the decimal portion of the quotient will be dropped). On the other hand if a division operation is carried out with two floating-point numbers, or with one floating-point number and one integer, the result will be a floating-point quotient.
Operands that differ in type may undergo type conversion before the expression takes on its final value. In general, the final result will be expressed in the highest precision possible, consistent with the data types of the operands. The following rules apply when neither / operand is unsigned.
1. If both operands are floating-point types whose precisions differ (e.g., a float and a double), the lower precision operand will be converted to the precision of the other operand, and the result will be expressed in this higher precision. Thus, an operation between a float and a double will result in a double; a float and a long double will result in a long double; and a double and a long double will result in a long double. (Note: In some versions of C, all operands of type float are automatically converted to double.)
2. If one operand is a floating-point type (e.g., float, double or long double) and the other is a char or an int (including short int or long int), the char or int will be converted to the floating-point type and the result will be expressed as such. Hence, an operation between an int and a double will result in a double.
3. If neither operand is a floating-point type but one is a long int, the other will be converted to long int and the result will be long into Thus, an operation between a long int and an int will result in a long int.
4. If neither operand is a floating-point type or a long int, then both operands will be converted to int (if necessary) and the result will be into Thus, an operation between a short int and an int will result in an int.
A detailed summary of these rules is given in Appendix D. Conversions involving unsigned operands are also explained in Appendix D.
3.2 UNARY OPERATORS
C includes a class of operators that act upon a single operand to produce a new value. Such operators are known as unary operators. Unary operators usually precede their single operands, though some unary operators are written after their operands.
Perhaps the most common unary operation is unary minus, where a numerical constant, variable or expression is preceded by a minus sign. (Some programming languages allow a minus sign to be included as a part of a numeric constant. In C, however, all numeric constants are positive. Thus, a negative number is actually an expression, consisting of the unary minus operator, followed by a positive numeric constant.)
Note that the unary minus operation is distinctly different from the arithmetic operator which denotes subtraction (-). The subtraction operator requires two separate-operands.
3.3 RELATIONALAND LOGICAL OPERATORS
There are four relational operators in C. They are
< less than
<= less than or equal to
> greater than
>= greater than or equal to
These operators all fall within the same precedence group, which is lower than the arithmetic and unary operators. The associatively of these operators is left to right.
Closely associated with the relational operators are the following two equality operators.
== equal to
!= not equal to
The equality operators fall into a separate precedence group, beneath the relational operators. These operators also have a left-to-right associatively.
These six operators are used to form logical expressions, which represent conditions that are either true or false. The resulting expressions will be of type integer, since true is represented by the integer value 1 and false is represented by the value 0.
3.4 ASSIGNMENT OPERATORS
There are several different assignment operators in C. All of them are used to form assignment .expressions which assign the value of an expression to an identifier.
The most commonly used assignment operator is = Assignment expressions that make use of this operator are written in the form
identifier = expression
where identifier generally represents a variable, and expression represents a constant, a variable or a more complex expression.
Remember that the assignment operator = and the equality operator == are distinctly different. The assignment operator is used to assign a value to an identifier, whereas the equality operator is used to determine if two expressions have the same value. These operators cannot be used in place of one another.
Beginning programmers often incorrectly use the assignment operator when they want to test for equality. This results in a logical error that is usually difficult to detect.
Assignment expressions are often referred to as assignment statements, since they are usually written as complete statements. However, assignment expressions can also be written as expressions that are included within other statements (more about this in later chapters).
If the two operands in an assignment expression are of different data types, then the value of the expression on the right (i.e., the right-hand operand) will automatically be converted to the type of the identifier on the left. The entire assignment expression will then be of this same data type.
Under some circumstances this automatic type conversion can result in an alteration of the data being assigned. For example:
A floating-point value may be truncated if assigned to an integer identifier.
A double-precision value may be rounded if assigned to a floating-point (single-precision) identifier.
An integer quantity may be altered if assigned to a shorter integer identifier or to a character identifier (some high-order bits may be lost).
Moreover the value of a character constant assigned to a numeric-type identifier will be dependent upon the particular character set in use. This may result in inconsistencies from one version of C to another.
The careless use of type conversions is a frequent source of error among beginning programmers.
THE CONDITIONAL OPERATOR
Simple conditional operations can be carried out with the conditional operator (? :). An expression that makes use of the conditional operator is called a conditional expression. Such an expression can be written in place of the more traditional if -else statement, which is discussed in Chap.6.
A condition expression is written in the form
expression 1 ? expression 2 : expression 3
When evaluating a conditional expression, expression 1 is evaluated first. If expression 1 is true (i.e., if, its value is nonzero), then expression 2 is evaluated and this becomes the value of the conditional expression. However, if expression 1 is false (i.e., if its value is zero),then expression 3 is evaluated and this becomes the value of the conditional expression. Note that only one of the embedded expressions (either expression 2 or expression 3) is evaluated when determining the value of a conditional expression.
The C language is accompanied by a number of library functions that carry out various commonly used operations or calculations. These library functions are not a part of the language per se, though all implementations of the language include them. Some functions return a data item to their access point; others indicate whether a condition is true or false by returning a 1 or a 0, respectively; still others carry out specific operations on data items but do not return anything. Features which tend to be computer-dependent are generally written as library functions.
For example, there are library functions that carry out standard input/output operations (e.g., read and write characters, read and write numbers, open and close files, test for end of file, etc.), functions that perform operations on characters (e.g., convert from lower- to uppercase, test to see if a character is uppercase, etc.), and function that perform operations on strings (e.g., copy a string, compare strings, concatenate strings, etc.), and functions that carry out various mathematical calculations (e.g., evaluate trigonometric, logarithmic and exponential functions, compute absolute values, square roots, etc.). Other kinds of library functions are also available.
Library functions that are functionally similar are usually grouped together as (compiled) object programs in separate library files. These library files are supplied as a part of each C compiler. All C compilers contain similar groups of library functions, though they lack precise standardization. Thus there may be some variation in the library functions that are available in different versions of the language.
A typical set of library functions will include a fairly large number of functions that are common to most C compilers such as those shown in Table 3-2 below. Within this table, the column labeled "type" refers to the data type of the quantity that is returned by the function. The void entry shown for function srand indicates that nothing is returned by this function.
A more extensive list, which includes all of the library functions that appear in the programming examples presented in this book, is shown in Appendix H. For complete list, see the programmer's reference manual that accompanies your particular version of C.
A library function is accessed simply by writing the function name, followed by a list of arguments that represent information being passed to the function. The arguments must be enclosed in parentheses and separated by commas. The arguments can be constants, variable names, or more complex expressions. The
parentheses must be present, even if there are no arguments.
A function that returns a data item can appear anywhere within an expression, in place of a constant or an identifier(i.e., in place of a variable or an array element). A function that carries out operations on data items but does not return anything can be accessed simply by writing the function name, since this type of function reference constitutes an expression statement.
Table 3-2 Some Commonly Used Library Functions
Function Type Purpose
abs(i) Int Return the absolute value of i.
ceil(d) double Round up to the next integer value (the smallest integer that is greater than or equal to d).
cos(d) double Return the cosine of d.
cosh (d) double Return the hyperbolic cosine of d.
exp (d) double Raise e to the power d (e =2.7182818. .. is the base of the natural (Naperian) system of logarithms).
fabs (d) double Return the absolute value of d.
floor (d) double Round down to the next integer value (the largest integer that does not exceed d).
fmod (d1,d2) double Return the remainder (i.e., the noninteger part of the quotient) of d1/d2, with same sign as d1.
getchar () int Enter a character from the standard input device.
log (d) double Return the natural logarithm of d.
pow (d1,d2) double Return d1 raised to the d2 power.
printf(…) int Send data items to the standard output device (arguments are complicated see Chap. 4).
pitcher © int Send a character to the standard output device
rand ( ) int Return a random positive integer.
sin (d) double Return the sine of d.
sqrt (d) double Return the square root of d.
srand (u) void Initialize the random number generator.
scanf(…) int Enter data items from the standard input device (arguments are complicated see Chap. 4).
tan (d) double Return the tangent of d.
toascii © int Convert value of argument to ASCII.
tolower © int Convert letter to lowercase
toupper © int Convert letter to uppercase.
Type refers to the data type of the quantity that is returned by the function.
c denotes a character-type argument
i denotes an integer argument
d denotes a double-precision argument
u denotes an unsigned integer argument
1. What is an expression? What are its components?
2. What is an operator? Describe several different types of operators that are included in C.
3. What is an operand? What is the relationship between operators and operands?
4. Describe the five arithmetic operators in C. Summarize the rules associated with their use.
5. Summarize the rules that apply to expressions whose operands are of different types.
6. How can the value of an expression be converted to a different data type? What is this called?
7. What is meant by operator precedence? What are the relative precedence’s of the arithmetic operators?
8. What is meant by associativity? What is the associativity of the arithmetic operators?
9. When should parentheses be included within an expression? When should the use of parentheses be avoided.
10. In what order are the operations carried out within an expression that contains nested parentheses?
11. What are unary operators? How many operands are associated with a unary operator?
12. Describe the six unary operators discussed in this chapter. What is the purpose of each?
13. Describe two different ways to utilize the increment and decrement operators. How do the two method differ?
14. What is the relative precedence of the unary operators compared with the arithmetic operators? What is their associativity?
15. How can the number of bytes allocated to each data type be determined for a particular C compiler?
16. Describe the four relational operators included in C. With what type of operands can they be used? What type of expression is obtained?
17. Describe the two equality operators included in C. How do they differ from the relational operators?
18. Describe the two logical operators included in C. What is the purpose of each? With what type of operands can they be used? What type of expression is obtained?
19. What are the relative precedence’s of the relational, equality and logical operators with respect to one another and with respect to the arithmetic and unary operators? What are their associativities?
20. Describe the logical not (logical negation) operator. What is its purpose? Within which precedence group is it included? How many operands does it require? What is its associativity?
21. Describe the six assignment operators discussed in this chapter. What is the purpose of each?
22. How is the type of an assignment expression determined when the two operands are of different data types? In what sense is this situation sometimes a source of programming errors?
23. How can multiple assignments be written in C? In what order will the assignments be carried out?
24. What is the precedence of assignment operators relative to other operators? What is their associativity?
25. Describe the use of the conditional operator to form conditional expressions. How is a conditional expression evaluated?
26. How is the type of a conditional expression determined when its operands differ in type?
27. How can the conditional operator be combined with the assignment operator to form an "if -else" type statement?
28. What is the precedence of the conditional operator relative to the other operators described in this chapter? What is its associativity?
29. Describe, in general terms, the kinds of operations and calculations that are carried out by the C library functions.
30. Are the library functions actually a part of the C language? Explain.
31. How are the library functions usually packaged within a C compiler?
32. How are library functions accessed? How is information passed to a library function from the access point?
33. What are arguments? How are arguments written? How is a call to a library function written if there are no arguments?
34. How is specific information that may be required by the library functions stored? How is this information entered into a C program?
35. In what general category do the #define and #include statements fall?
C supports a rich set of operators. We have already used several of them, such as =, +. -, *, & and, <.An operator is a symbol that tells the computer to perform certain mathematical or logical manipulations. Operators are used in programs to manipulate data and variables. They usually form a part of the mathematical of logical expressions.
C operators can be classified into a number of categories. They include:
1. Arithmetic operators.
2. Relational operators.
3. Logical operators.
4. Assignment operators.
5. Incrementand decrement operators.
6. Conditional operators.
3.2 ARITHMETIC OPERATORS
C provides all the basic arithmetic operators. They are listed in Table 3.1. The operators +, -, * and I all work the same way as they do in other languages. These can operate on any built-in data type allowed in C. The unary minus operator, in effect, multiplies its single operand by -1. Therefore, a number preceded by a minus sign changes its sign.
Table 3.1 Arithmetic Operators
+ Addition or unary plus
- Subtraction or unary minus
% Modulo division
Integer division truncates any fractional part. The modulo division produces the remainder of an integer division. Examples of arithmetic operators are:
a – b a + b
a * b a / b
a % b -a * b
Here a and b are variables and are known as operands. The modulo division operator % cannot be used on floating point data.
Note that C does not have an operator for exponentiation. Older versions of C does not support unary plus but ANSI C supports it.
When both the operands in a single arithmetic expression such as a+b are integers, the expression is called an integer expression, and the operation is called integer arithmetic. Integer arithmetical ways yields an integer value. The largest integer value depends on the machine, as pointed out earlier. In the above examples, if a and b are integers, then for a = 14 and b = 4 we have the following results:
a - b = 10
a + b = 18
a / b = 3 (decimal part truncated)
a % b = 2 (remainder of division)
During integer division, if both the operands are of the same sign, the result is truncated towards zero. If one of them is negative, the direction of truncation is implementation dependent. That is,
6/7 = 0 and -6/-7 = 0
but -6/7 may be zero or -1. (Machine dependent)
Similarly, during modulo division, the sign of the result is always the sign of the first operand (the dividend.) That is
-14 % 3 = -2
-14 % -3 = -2
14 % -3 = 2
An arithmetic operation involving only real operands is called eal arithmetic. A real operand may assume values either in decimal or exponential notation. Since floating point values are rounded to the number of significant digits permissible, the final value is an approximation of the correct result. If x, y, and z are floats, then we will have:
x = 6.0/7.0 = 0.857143
Y = 1.0/3.0 = 0.333333
z = -2.0/3.0 = -0.666667
The operator % cannot be used with real operands.
When one of the operands is real and the other is integer, the expression is called a mixed-mode arithmetic expression. If either operand is of the real type, then only the real operation is performed and the result is always a real number. Thus
15/10 = 1
More about mixed operations will be discussed later when we deal with the evaluation of expressions.
3.3 RELATIONAL OPERATORS
We often compare two quantities, and depending on their relation, take certain decisions. For example, we may compare the age of two persons, or the price of two items, and so on. These comparisons can be done with the help of relational operators. We have already used the symbol '<', meaning 'less than'. An expression such as
containing a relational operator is termed as a relational expression. The value of a relational expression is either one or zero. It is one if the specified relation is true and zero if the relation is false. For example
10 < 20 is true
20 < 10 is false
C supports six relational operators in all. These operators and their meanings are shown in Table 3.2.
Table 3.2 Relational Operators
< is less than
<= is less than or equal to
> is greater than
>= is greater than or equal to
== is equal to
!= is not equal to
A simple relational expression contains only one relational operator and takes the following form:
ae-1 relational operator ae-2
ae-1 and ae-2 are arithmetic expressions, which may be simple constants, variables or combination of them. Given below are some examples of simple relational expressions and their values:
4.5<= 10 TRUE
4.5< -10 FALSE
-35>= 0 FALSE
10< 7+5 TRUE
a+b== C+D TURE only if the sum of values of
a and b is equal to the sum of values of c and d.
When arithmetic expressions are used on either side of a relational operator, the arithmetic expression will be evaluated first and then the results compared. That is, arithmetic operators have a higher priority over relational operators.
Relational expressions are used in decision statements such as, if and while to decide the course of action of a running program. We have already used the while statement in chapter 1. Decision statements are discussed in detail in Chapters 5 and 6.
3.4 LOGICAL OPERATORS
In addition to the relational operators, C has the following three logical operators.
&& meaning logical AND
:: meaning logical OR
I meaning logical NOT
The logical operators && and :: are used when we want to test more than one condition and make decisions. An example is:
a > b && x == 10
An expression of this kind which combines two or more relational expressions is termed as a logical expression or a compound relational expression. Like the simple relational expressions, a Iogical expression also yields a value of one or zero, according to the truth table shown in Table 3.3. The logical expression given above is true only if a> b is true and x == 10 is true. If either (or both) of them are false, the expression is false.
Table 3.3 Truth Table
Value of the expression
op-1 && op-2 op-1|| op-2
Non-zero Non-zero 1 1
Non-zero 0 0 1
0 Non-zero 0 1
0 0 0 0
Some examples of the usage of logical expressions are:
1. If (age> 55 && salary < 1000)
2. If (number < 0 :: number> 100)
We shall see more of them when we discuss decision statements.
3.5 ASSIGNMENT OPERATORS
Assignment operators are used to assign the result of an expression to a variable. We have seen the usual assignment operator, ' = '. In addition, C has a set of 'shorthand' assignment operators of the form
Where v is a variable, exp is an expression and op is a C binary arithmetic operator. The operator op= is known as the shorthand assignment operator.
The assignment statement
v op= exp;
is equivalent to
v = v op (exp);
with v evaluated only once. Consider an example
X += y+1;
This is same as the statement
x = x + (y+1); r
The shorthand operator += means 'add y+1 to x' or 'increment x by y+1'. For y = 2, the above statement becomes
X += 3;
and when this statement is executed, 3 is added to x. If the old value of x is, say 5, then the new value of x is 8. Some of the commonly used shorthand assignment operators are illustrated in Table 3.4. •
Table 3.4 Shorthand Assignment Operators
Statement with simple Statement with
assignment operator shorthand operator
a = a + 1 a += 1
a = a – 1 a -= 1
a = a * (n+ 1) a *= n+1
a = a / (n+1) a /= n+ 1
a=a%b a %= b
The use of shorthand assignment operators has three advantages:
1. What appears on the left hand side need not be repeated and therefore it becomes easier to write.
2. The statement is more concise and easier to read.
3. The statement is more efficient. -
These advantages may be appreciated if we consider a slightly more involved statement, like
value (5*j-2) = value(5*j-2) + delta;
With the help of the + = operator, this can be written as follows:
value (5*j-2) += delta;
It is easier to read and understand, and is more efficient because the expression 5*j - 2 is evaluated only once.
3.6 INCREMENATND DECREMENT OPERATORS
C has two very useful operators not generally found in other languages. These are the increment and decrement operators:
++ and --
The operator + + adds 1 to the operand while - - subtracts 1. Both are unary operators and take the following form:
++m; or m++;
--m; or m--;
++m; is equivalent to m = m+1; (or m += 1;)
--m; is equivalent to m == m-1; (or m -= 1;)
We use the increment and decrement statements in for and while loops extensively.
While ++ m and m ++ mean the same thing when they form statements independently they behave differently when they are used in expressions on the right-hand side of an assignment statement. Consider the following:
y = + +m;
In this case, the value of y and m would be 6. Suppose, if we rewrite the above statements as
y = m++;
then the value of y would be 5 and m would be 6. A prefix operator first adds 1 to the operand and then the result is assigned to the variable on left. On the other hand, a postfix operator first assigns the value to the variable on left and then increments the operand.
Similar is the case, when we use + + (or - -) in subscripted variables. That is, the statement
a [I++] = 10;
is equivalent to
a [l] = 10;
i = i+ 1;
The increment and decrement operators can be used in complex statements. Example:
m = n++ -j+10;
Old value of n is used in evaluating the expression .n is incremented after the evaluation. Some compilers require a space on either side of n+ + or + +n.
A ternary operator pair "?:" is available in C to construct conditional expressions of the form
exp1 ? exp2 : exp3;
where exp1, exp2, and exp3 are expressions.
The operator ? : works as follows: exp1 is evaluated first. If it is nonzero (true), then the expression exp2 is evaluated and becomes the value of the expression. If exp1 is false, exp3 is evaluated and its value becomes the value of the expression. Note that only one of the expressions (either exp2 or exp3) is evaluated. For example, consider the following statements.
a = 10;
b = 15;
x = (a > b) ? a : b;
In this example, x will be assigned the value of b. This can be achieved using the if else statements as follows:
If (a > b)
x = a;
x = b;
3.8 BITWISE OPERATORS
C has a distinction of supporting special operators known as bitwise operators for manipulation of data at bit level. These operators are used for testing the bits, or shifting them right or left. Bitwise operators may not be applied to float or double. Table 3.5 lists the bitwise operators and their meanings. They are discussed in detail in Appendix I.
Table 3.5 Bitwise Operators
& bitwise AND
| bitwise OR
^ bitwise exclusive OR
<< shift left
>> shift right
~ One's complement
3.9 SPECIAL OPERATORS
C Supports some special operators of interest such as comma operator, sizeof operator, pointer operators (&and*) and member selection operators (. and -». The comma and sizeof operators discussed in this section while the pointer operators are discussed in Chapter 11. Member selection operators which are used to select members of a structure are discussed in Chapters 10 and 11. ANSI committee has introduced two preprocessor operators known as "string-izing" and "token-pasting" operators (# and ##). They will be discussed in Chapter 13.
The Comma Operator
The comma operator can be used to link the related expressions together. A comma-linked list expressions are evaluated left to right and the value of right-most expression is the value of the combined expression. For example, the statement
value = (x = 10, Y = 5, X+Y);
first assigns the value 10 to x, then assigns 5 to y, and finally assigns 15 (Le, 10+5) to value. Since comma operator has the lowest precedence of all operators, the parentheses are necessary. Some applications of comma operator are:
In for loops:
for (n = 1, m = 10; n <= m; n++. m++)
In while loops:
while(c = getchar( ), c != '10')
f = x, x = y, y = t;
The slzeof Operator
The sizeof is a compile time operator and, when used with an operand, it returns the number of bytes the operand occupies. The operand may be a variable, a constant or a data type qualifier.
n =sizeof(long int):
The sizeof operator is normally used to determine the lengths of arrays and structures when their sizes are not known to the programmer. It is also used to allocate memory space dynamically to variables during execution of a program.
3.10 ARITHMETIC EXPRESSIONS
An arithmetic expression is a combination of variables, constants, and operators arranged as per the syntax of the language. We have used a number of simple expressions in the examples discussed so far. C can handle any complex mathematical expression!). Some of the examples of C expressions are shown in Table 3.6. Remember that C does not have an operator for exponentiation.
3.11 EVALUATIONOF EXPRESSIONS
Expressions are evaluated using an assignment statement of the form
variable = expression;
Table 3.6 Expressions
Algebraic expression C expression
a x b – c a*b-c
(m+n) (x+y) (m+n) * (x+y)
c a * b/c
3x' +2x+ 1 3*x*x+2*x+1
Variable is any valid C variable name. When the statement is encountered, the expression is evaluated first and the result then replaces the previous value of the variable on the left-hand side. An variables used in the expression must be assigned values before evaluation is attempted. Examples of evaluation statements are
x = a *b - c;
Y = b I c * a;
z = a - b I c + d;
The blank space around an operator is optional and adds only to improve readability. When these statements are used in a program, the variables a, b, c, and d must be defined before they are used in the expressions.
3.12 PRECEDENCE OF ARITHMETIC OPERATORS
An arithmetic expression without parentheses will be evaluated from left to right using the rules of precedence of operators. There are two distinct priority levels of arithmetic operators in C
High priority * I %
Low priority + -
The basic evaluation procedure includes two left-to-right passes through the expression. During the first pass, the high priority operators (if any) are applied as they are encountered. During the second pass, the low priority. operators (if any) are applied as they are encountered. Consider the following evaluation statement that has been used in the program of Fig. 3.4.
x = a-b/3 + c*2-1
When a = 9,b = 12, and c = 3, the statement becomes
x = 9-12/3 + 3*2-1
and is evaluated as follows
Step1: x = 9-4+3*2-1
Step2: x = 9-4+6-1
Step3: x = 5+6-1
Step4: x = 11-1
Step5: x = 10
These steps are illustrated in Fig. 3.5. The numbers inside parentheses refer to step numbers.
However, the order of evaluation can be changed by introducing parentheses into an expression. Consider the same expression with parentheses as shown below:
Whenever parentheses are used, the expressions within parentheses assume highest priority. If two or more sets of parentheses appear one after another as shown above, the expression contained in the left-most set is evaluated first and the right-most in the last. Given below are new steps.
9 - 12/3 + 3*2 - 1
Step1: 9-1216 * (2-1)
Step2: 9-12/6 * 1
Step3: 9-2 * 1
This time, the procedure consists of three left-to-right passes. However, the number of evaluation steps remain the same as 5 (i.e equal to the number of arithmetic operators).
Parentheses may be nested, and in such cases, evaluation of the expression will proceed outward from the innermost set of parentheses. Just make sure that every opening parenthesis has a matching closing one. For example
9 - (12/(3+3) * 2) - 1 = 4
9 - ((12/3) + 3 * 2) - 1 = -2
While parentheses allow us to change the order of priority, we may also use them to improve understandability of the program. When in doubt, we can always add an extra pair just to make sure that the priority assumed is the one we require.
3.13 SOME COMPUTATIONAL PROBLEMS
When expressions include real values, then it is important to take necessary precautions to guard against certain computational errors. We know that the computer gives approximate values for real numbers and the errors due to such approximations may lead to serious problems. For example, consider the following statements:
a = 1.013.0;
b = a *3.0;
We know that (1.0/3.0)3.0 is equal to 1. But there is no guarantee that the value of b computed in a program will equal 1.
Another problem is division by zero. On most computers, any attempt to divide-a number by zero will result in abnormal termination of the program. In some cases such a division may produce meaningless results. Care should be taken to test the denominator that is likely to assume zero value and avoid any division by zero.
The third problem is to avoid overflow or underflow errors. It is our responsibility to guarantee that operands are of the correct type and range, and the result may not produce any overflow or underflow.
3.14 TYPE CONVERSIONS IN EXPRESSIONS
Automatic Type Conversion
C permits mixing of constants and variables of different types in an expression, but during evaluation it adheres to very strict rules of type' conversion. We know that the computer considers one operator at a time, involving two operands.
If the operands are of different types, the 'lower' type is automatically converted to the 'higher' type before the operation proceeds. The result is of the higher type.
Given below is the sequence of rules that are applied while evaluating expressions. All short and char are automatically converted to int; then
1. if one of the operands is long double, the other will be converted to long double and the result will be long double;
2. else, if one of the operands is double, the other will be converted to double and the result will be double;
3. else, if one of the operands is float, the other will converted to float and the result will be float;
4. else, if one of the operands is unsigned long int, the other will be converted to unsigned long int and the result will be unsigned long int;
5. else, if one of the operands is long int and the other is unsigned int, then:
(a) if unsigned int can be converted to long int, the unsigned int operand will be converted as such and the result will be long int;
(b) else, both operands will be converted to unsigned long int and the result will be unsigned long int;
6. else, if one of the operands is long int, the other will be converted to long int and the result will be long int;
7. else, if one of the operands is unsigned int, the other will be converted to unsigned int and the result will be unsigned int.
Note that some versions of C automatically convert all floating-point operands to double precision.
The final result of an expression is converted to the type of the variable on the left of the assignment sign before assigning the value to it. However, the following changes are introduced during the final assignment.
1. float to int causes truncation of the fractional part.
2. double to float causes rounding of digits.
3. long int to int causes dropping of the excess higher order bits.
Casting a Value
We have just discussed how C performs type conversion automatically. However, there are instances when we want to force a type conversion in a way that is different from the automatic conversion. Consider, for example, the calculation of ratio of females to males in a town.
ratio = female_number/male_number
Since female...number and male...number are declared as integers in the program, the decimal part of the result of the division would be lost and ratio would represent a wrong figure. This problem can be solved by converting locally one of the variables to the floating point as shown below:
ratio = (float)female_number/male_number
The operator (float) converts the female_number to floating point for the purpose of evaluation of the expression. Then using the rule of automatic conversion, the division is performed in floating point mode, thus retaining the fractional part of result.
Note that in no way does the operator (float)affect the value of the variable female_number. And also, the type of femaleJ1umber remains as int in the other parts of the program.
The process of such a local conversion is known as casting a value. The general form of a cast is:
Where type-name is one of the standard C data types. The expression may be a constant, variable or an expression. Some examples of casts and their actions are shown in Table 3.7.
Table 3.7 Use of Casts
x = (Int) 7.5 7.5 is converted to integer by truncation.
a = (Int) 21.3/(lnt) 4.5 Evaluated as 21/4 and the result would be 5.
b = (double)sum/n Division is done in floating point mode.
y = (Int) (a+b) The result of a+b is converted tointeger.
z = (Int)a+b a is converted to integer and then added to b.
p = cos((double)x) Converts x to double before using it.
3.15 OPERATOR PRECEDENCE AND ASSOCIATIVITY
Each operator in C has a precedence associated with it. This precedence is used to determine how an expression involving more than one operator is evaluated. There are distinct levels of precedence and an operator may belong to one of the levels. The operators at the higher level of precedence are evaluated first. The operators of the same precedence are evaluated either from left to right or from right to left, depending on the level. This is known as the associativity property of an operator. Table 3.8 provides a complete list of operators, their precedence levels, and their rules of association. The groups are listed in the order of decreasing precedence (rank 1 indicates the highest precedence level and 15 the lowest). The list also includes those operators which we have not yet discussed.
It is very important to note carefully, the order of precedence and associativity of operators. Consider the following conditional statement:
if (x == 10 + 15&&y< 10)
The precedence rules say that the addition operator has a higher priority than the logical operator (&&) and the relational operators (== and <). Therefore, the addition of 10 and 15 is executed first. This is equivalent to:
If (x == 25&&y<10)
The next step is to determine whether x is equal to 25 and y is less than 10. If we assume a value of 20 for x and 5 for y, then
x = = 25 is FALSE (0)
Y < 10 is TRUE (1)
Note that since the operator < enjoys a higher priority compared to ==, y < 10 is tested first and then x == 25 is tested.
Finally we get:
If (FALSE && TRUE)
Because one of the conditions is FALSE, the complex condition is FALSE.
In the case of &&, it is guaranteed that the second operand will not be evaluated if the first is zero and in the case of ::, the second operand will not be evaluated if the first is non-zero.
3.16 MATHEMATICAL FUNCTIONS
Mathematical functions such as COS, sqrt, log, etc. are frequently used in analysis of real-life problems. Most of the C compilers support these basic math functions. However, there systems that have a more comprehensive math library and one should consult the reference manual to find out which functions are available. Table 3.9 lists some standard math functions.
As pointed out earlier in Chapter 1, to use any of these functions in a program, we should include the line:
in the beginning of the program. In addition, the command for compilation should be:
cc filename -lm
under UNIPLUS SYSTEM 5 operating system.
Table 3.8 Summary of C Operators
OPERATOR DESCRIPTION ASSOCIATIVITY RANK
() Function call Left to right 1
[ ] Array element reference
+ Unary plus
- Unary minus Right to left 2
! Logical negation
~ Ones complement
* Pointer reference (indirection)
sizeof Size of an object
(type) Type cast (conversion)
* Multiplication Left to right 3
+ Addition Left to right 4
<< Left shift Left to right 5
>> Right shift
< Less than Left to right 6
<= Less than or equal to
> Greater than
>= Greater than or equal to
== Equality Left to right 7
& Bitwise AND Left to right 8
^ Bitwise XOR Left to right 9
| Bitwise OR Left to right 10
&& Logical AND Left to right 11
|| Logical OR Left to right 12
?: Conditional expression Right to left 13
= Assignment operators Right to left 14
*= /= %=
+= -= &=
Comma operator Left to right 15
Table 3.9 Math Functions
acos(x) Arc cosine of x
asin(x) Arc sin of x
atan(x) Arc tangent of x
atan2(x,y) Arc tangent of xly
cos(x) Cosine of x
sin(x) Sine of x
tan(x) Tangent-of x
cosh(x) Hyperbolic cosine of x
sinh(x) Hyperbolic sine of x
tanh(x) Hyperbolic tangent of x
ceil(x) x rounded up to the nearest integer
exp(x) e to the power x (ex)
fabs(x) Absolute value of x.
floor(x) x rounded down to the nearest integer
fmod(x,y) Remainder of xly
log(x) Natural log of x, x > 0
log10(x) Base 10 log of x, x > 0
pow(x,y) x to the power y (XV)
sqrt(x) Square root of x, x > = 0
1.x and y should be declared as double.
2. In trigonometric and hyperbolic functions, x and yare in radians.
3. All the functions return a double.