Operators and Expressions
Operators
Operators are those symbols that perform some specific task.
Like, when we add two numbers we generally use '+' sign. In programming also,
to perform some specific task, compiler has assigned some specific symbols.
These symbols are called operators. The data items that operators act
upon are called operands. Some operators require one operand to act
upon, whereas some require more than one. Thus, depending upon the number of
operands required by the operators, we can broadly divide operators into three
distinct categories.
1.Unary operators (++, -- ,-,sizeof)
2.Binary operators (Arithmetic, Assignment,
Relational, Logical)
3.Tertiary operators (?:)
1.1
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 operand, though some unary
operators are written after their operand.
The most common unary operator is unary minus, where
a numerical constant, variable, or expression is preceded by a minus sign.
e.g. -743,
-a,-root
Hence, this operator requires single operand.
The other commonly used unary operators are: ++ ( increment
operator) and -- (decrement operator). The increment operator causes its
operand to be incremented by 1, whereas the decrement operator causes its
operand to be increased by 1.
e.g a++,
a--, ++a, --a
main()
{
int a=5;
printf("Value of a=%d",a);
a++;
printf("Value of a=%d",a);
a--;
printf("Value of a=%d",a);
getch();
}
output
a=5
a=6 (incremented by 1)
a=5 (decremented by 1)
The increment and decrement operators can each be utilized
in two different ways, depending upon whether the operator is written before or
after the operand. If the operator precedes the operand (e.g. ++i), then the
operand will be altered in value before it is utilized for its intended purpose
within the program. If, however, the operator follows the operand (e.g. i++),
then the value of the operand will be altered after it is utilized. Hence,
increment and decrement can be pre or post.
i++
(post increment), ++i(pre increment), i--(post decrement), --i(pre decrement)
e.g.
printf("i=%d\n",i);
printf("i=%d\n",++i);
printf("i=%d\n",i);
output
i=1
i=2
i=2
The first statement causes the original value of i to be
displayed. The second statement increments i and then displays its value. The
last statement displays the final value of i.
printf("i=%d\n",i);
printf("i=%d\n",i++);
printf("i=%d\n",i);
output
i=1
i=1
i=2
The first statement causes the original value of i to be
displayed. The second statement causes the current value of i to be displayed
and then incremented to 2. The last statement displays the final value of i.
Another
unary operator is sizeof. It returns the size of operand
in Bytes.
e.g. main()
{
int i;
float x;
double d;
char c;
printf("integer: %d\n", sizeof i);
printf("float: %d\n", sizeof x);
printf("double: %d\n", sizeof d);
printf("Character: %d\n", sizeof c);
getch();
}
output
integer: 4
float: 4
double: 8
character: 1
Typecast
operator is also unary operator. It is used to change the data type of a
variable.
Syntax: (type) expression
e.g. (float) x/2;
main()
{
int var1;
float var2;
var2= (float) var1;
}
Unary operators have higher precedence. Also, the associativity of the unary
operator is right to left.
1.2
Binary operators
Binary operators act upon a two operands to produce a new
value. Such, operators can be classified into different categories.
a)Arithmetic operators
Arithmetic operators are the operators used to perform the
arithmetic operations like addition, subtraction, multiplication, division, and
modulo operation. Hence five arithmetic operators are:
+ for addition
- for subtraction
* for multiplication
/ for division
% for remainder operation, modulo
operator
General structure:
Result =
operand1 (Arithmetic operator) operand2
Where, arithmetic operator could be any one of the five
operators mentioned above. Once the operator performs a particular operation,
result is then assigned to 'result'.
·Operands acted upon by
arithmetic operators must represent numeric values. Thus, operands may be
integer, float, or character quantities. Character quantities are also allowed
as each character is associated with equivalent integer number ( ASCII value).
·Modulus operator requires that
both operands be integer and second operator be non zero.
·Similarly, division operator
requires the second operator be non zero.
·Arithmetic operators (except
%) can be used in 3 modes:
Ø
Integer mode: where both the operands are
integer
Ø
Real mode: where both the operands are real
Ø
Mixed mode: where one operand is integer and
second operator is real
·Result is always a floating
point number for real mode and mixed mode. For integer mode, result is always
an integer number.
·All the operators should be
explicitly written. No assumption should be made as in normal math like z=ab is
not valid. We must write z=a*b
e.g.
main()
{
int a=10,b=3;
int c,d,e,f;
c=a+b;
d=a-b;
e=a*b;
f=a%b;
printf("Value of c=%d\n",c);
printf("Value of d=%d\n",d);
printf("Value of e=%d\n",e);
printf("Value of f=%d\n",f);
getch();
}
b)Assignment operators
Assignment operators are used when the value is to be
assigned to an identifier, a variable. With execution of assignment operators,
value at the right is assigned to the left. The destination variable looses the
old value, i.e. old value is over ridden with the new value. If previous value
is also required; it should be saved in some other variables.
General structure
Destination
(assignment operator) Source
The assignment operators available in C are:
= for assignment
+= add with destination and assign
-= deduct from destination and assign
*= multiply with destination and assign
/= divide the destination and assign
%= assign the remainder after dividing the
destination
exp1+=exp2 is equivalent to exp1=exp1+exp2
exp1-=exp2 is equivalent to exp1=exp1-exp2
exp1*=exp2 is equivalent to exp1=exp1*exp2
exp1/=exp2 is equivalent to exp1=exp1/exp2
exp1%=exp2 is equivalent to exp1=exp1%exp2
If the two operands in an assignment expression are of
different data types, then the value of the expression on the right will
automatically be converted to the type of identifier on the left.
e.g. main()
{
int i=5;
float j=3.14;
i=j;
j=i;
printf("value of i=%d\n",i);
printf("value of j=%f\n",j);
getch();
}
output
value of i=3
value of j=3.0
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 an floating point identifier
Now suppose that j and k are both integer type variables,
and that k has been assigned a value of 5. Several assignment expressions that
make use of these two variables are shown below.
Expression Value
j=k 5
j=k/2 2
j=2*k/2 5
j=2*(k/2) 4 (truncated
division followed by division)
For multiple assignment,
identifier1=identifier2=identifier3, assignment operation is carried out form
right to left. So, given expression is equivalent to
Identifier1=(identifier2=identifier3)
Hierarchy of operation
Precedence and associativity comes into role when evaluating
complex mathematical expression in programming. Suppose, we have an expression
like:
Z=a+2*b/c*d+23+a*a;
Precedence defines which of the operator
is to be executed first, like in simple rule of mathematics, BODMAS,
bracket is operated first. However, evaluating expression in programming is not
that simple. Though BODMAS rule is valid, we have to tale in account some other
rules also.
Priority Operators
Ist * / %
2nd + -
3rd =
In case, there is a tie between operators of same priority
preference is given to the one that occurs first. This is called associativity.
Associativity is the
preference of the operators (of same precedence level), when there is tie
between them.
e.g. suppose we have
z=a+b*c
Then, operation occurs as z=a+(b*c) as * higher precedence
than +
But when the case is like
Z=a*b+c/d,
operation occurs as
Z=(a*b)+(c/d)
i.e. multiplication is done first. Then (c/d) is evaluated. Then only the two
values are added. It happens so because * and / have higher precedence than +.
However, as * and / have same precedence
level, * is evaluated first, as the associativity of the arithmetic operators is from left to right,
hence whichever operator occurs first, that is evaluated.
c)Relational and Logical Operators
These operators are very helpful for making decisions.
Depending upon the condition, it returns either 0 or 1. When the condition with
these operators is true, 1 is returned. If the condition is false, it returns
0.
There are four relational operators in C
< less than
> greater than
<= less than or equals to
>= greater than or equals to
·The precedence of these
operators is below the arithmetic and unary operators.
·The associativity of these
operators is from left to right.
·Equality operators are closely
associated with this group
= = equal to
!=
not equal to
·Precedence level of equality
operator is below the relational operators. These operators also have a left to
right associativity.
There are two logical operators
&& logical and
|| logical or
·Logical operators act upon
operands that are themselves logical expressions.
·Individual logical expressions
are combined into more complex conditions that are either true or false.
·For the logical operators, any
non-zero positive value is considered as true.
Consider a case where int
j=7; float k=5.4; char c='w';
Expression Interpretation Value
(j>=6)&&(c= ='w') true 1
(k<11)&&(j>100) false 0
(j>=6)||(c= = 19) true 1
(c!=p)||(j+k)<10 true 1
d)Comma operator
o
C uses comma operator(,) as the separator in
declaration of the same types. e.g. int a,b,c
o
It can also be used while initializing the
content of an array. e.g. int a[3]={1,5,7}
o
It is also used for separating expressions.
e.g. for(i=0,j=1;i<j;i++,j--)
1.3
Ternary operators
Binary operators work on two operands. Unary operators
operate on single operand whereas tertiary operator requires three operands to
operate. Conditional operator is a tertiary operator.
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.
A conditional expression is written in the form
(Test
expression) ? true_value: false-value;
Example: In the conditional expression shown below, assume
that j is an integer variable
(j<0)?0:100
The expression (j<0) is evaluated first. If it is true
(i.e. if the value of j is less than 0), the entire conditional expression
takes on the value 0. Otherwise, the entire conditional expression takes on the
value 100.
4.4 Operator precedence group
Operator category Operators Associativity
Unary operators -
++ -- sizeof (type) R--->L
Arithmetic multiply, divide, and remainder *
/ % L-->R
Arithmetic 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
4.5 Type Conversion
Data type of one type can be converted to another type
explicitly by using type cast operator. In C typecasting can be done as:
(new type)
variable;
Consider a case as:
int a;
float b;
Then, b=(int) a;
Besides type casting operator, there occurs default
promotion or demotion of the value to be assigned during operations.
e.g. #include<stdio.h>
main( )
{
int a;
float b;
a=3.5;
b=30;
}
Here, for a=3.5, 3.5 is demoted to an integer and hence, a
is assigned an integer value of 3. Similarly, 30 is promoted to floating point
value of 30.000000 and assigned to b. In tis case type casting occurs
automatically.
Generally, source data is converted to match the data type
of destination.
4.6 Library functions and Header Files
The C language is accompanied by a number of library
functions that carry out various commonly used operations or calculations. For
example, there are library functions that carry out standard input output
operations (e.g. read and write characters, open and close files, test for end
of file etc.), functions that perform operations on characters (e.g. convert
from lowercase to uppercase, test to see if a character is a uppercase etc.),
functions that perform operations on string (e.g copy a string, compare
strings, concatenation of strings etc.), and functions that carry out various
mathematical calculations (e.g. compute absolute values, square root etc.).
A library function is accessed simply by writing the
function name, followed by a list of arguments that represent information being
passed to a function. The arguments must be enclosed in parenthesis and
separated by commas. The arguments can be constants, variable names, or more complex
expressions. The parenthesis must be present even if there are no arguments.
Example:
abs(j) Returns
the absolute value of j
cos(d) Returns
the cosine of d
rand( ) Returns
random positive number
tolower(c) Convert
letter to lowercase
toupper(c) Convert
letter to uppercase
getchar( ) Enter
a character from the standard input device
putchar(c) Send
a character to the standard output device
printf(…) Send
data items to the standard output device
scanf(…) Enter
data item from the standard input device
C place the required library function declarations in
special source files, called header files so, for every library function used,
associated header file should be included with preprocessor directive.
For example, stdio.h is a header file containing declaration
for input/output routines; math.h contains declarations for certain
mathematical functions; and so on. The required header file must be merged with
the source program during the compilation process. This is accomplished by
placing one or more # include statements at the beginning of the source
program.
#include<stdio.h>
This is called a preprocessor directive. It commands that
the contents of the file stdio.h should be included in the compiled machine
code at the place where # include appears.
Note: The # include line must not terminate with a semicolon
- Only one preprocessor directive can appear in
one line
Example: Read a lowercase character and display its
uppercase equivalent
#include<stdio.h>
#include<conio.h>
#include<stype.h>
void
main( )
{
int lower,upper;
lower=getchar( );
upper=toupper(lower);
putchar(upper);
getch( );
}
This program contains three library functions getchar,
toupper, and putchar.
Also, notice the preprocessor statement
#include<stdio.h> and #include<ctype.h>, which appear at the start
of a program. The statement causes the contents of the files stdio.h and
ctype.h to be inserted into the program when the compilation process begins.
The information contained in these files is essential for the proper
functioning of the library functions getchar, putchar, and toupper.
4.7 Storage Classes in C
There are mainly two locations, where the data will be
stored. These locations are main memory and registers. Storage
class of any variable determines where the value of that variable would be
stored. Beside that, the storage class of any variable provides programmer,
other vital information like:
·What will be the initial value
of the variable?
·Which
functions will the value of the variable be available? That is, scope of the variable.
·How long will the value of
variable be available, i.e. life
span of the variable.
So, any variable declaration essentially comprises following
pattern:
Storage-class data-type
identifier
There are four storage classes in C
a)Automatic storage class
b)Register storage class
c)Static storage class
d)External storage class
a)Automatic storage class
Method of declaring the variable x of
type integer with automatic storage class is:
auto int x; OR int x;
auto is the default storage class for
local variables.
Characteristics
of the variables of this storage class:
Storage: Memory
Default initial value: Garbage
Scope: Local to the block in which the
variable is declared or defined
Life: Till the control remains within
the block where the variable is defined
b)Static Storage class
Method of declaring the variable x of
type integer with static storage class is:
static
int x;
static is the default storage class for
global variables. The two variables below (count and road) both have a static
storage class.
static
int count;
int road;
main( )
{
printf("%d\n",count);
printf("%d\n",road);
}
Characteristics
of the variables of this storage class:
Storage: Memory
Default initial value: Zero
Scope: Local to the block in which the
variable is declared or defined
Life: Value is maintained between
different function calls.
As the value is maintained between different function calls,
usually used as a counter variable that has to be accessed by different function
call.
Given below are two identical programs. All the syntaxes are
same, except the storage class of the variable j.
Program A Program
B
#include<stdio.h> #include<stdio.h>
#include<conio.h> #include<conio.h>
void increment( ) void increment( )
{ {
auto int j=1; static int j=1;
printf("%d",j); printf("%d",j);
j++; j++;
} }
main( ) main(
)
{ {
increment(); increment();
increment(); increment();
increment(); increment();
} }
For Program A:
Output: 1 1 1(Since life of automatic variable is destroyed when the
control exit from the block)
For Program B :Output:
1 2 3 (Since value is maintained between each function calls)
C)
External Storage Class
extern defines
a global variable that is visible to all object modules. Method of declaring
the variable x of type integer with external storage class is:
extern int
x;
Characteristics of
the variables of this storage class:
Storage: Memory
Default initial value: Garbage
Scope: Global
Life: As long as the program execution remains
These variables are declared outside all functions.
D)
Register Storage Class
Method of declaring the variable x of type integer with
register storage class is:
register
int x;
Characteristics of
the variables of this storage class:
Storage: CPU Register
Default initial value: Garbage
Scope: Local to the block in which the variable is declared
or defined
Life: Till the control remains within that block
The values of variables are stored in CPU registers. They
are accessed much faster. Generally, frequently used variables are declared
with register storage class. However, if many variables are declared as of type
register, they may not be register type due to limited number of CPU registers
End of Chapter Four
[ Note: If you have any problems regarding this then you can post the
problem in comment box. we will try to solve this here. Or if you know
any solution, you can also help :) ]
No comments:
Post a Comment