Wednesday, December 18, 2013

Chapter 4: Operators and Expressions


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