KEMBAR78
C++ Hand Notes | PDF | Integer (Computer Science) | Parameter (Computer Programming)
0% found this document useful (0 votes)
11 views72 pages

C++ Hand Notes

The document outlines the structure and evolution of programming languages, detailing the various generations from machine languages to high-level languages like C. It emphasizes the importance of programming language design, influenced by factors such as hardware and applications, and highlights the characteristics of general-purpose versus specific-purpose languages. Additionally, it discusses the role of database management systems and the features of C as a structured programming language developed in the 1970s.

Uploaded by

calistaugin
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views72 pages

C++ Hand Notes

The document outlines the structure and evolution of programming languages, detailing the various generations from machine languages to high-level languages like C. It emphasizes the importance of programming language design, influenced by factors such as hardware and applications, and highlights the characteristics of general-purpose versus specific-purpose languages. Additionally, it discusses the role of database management systems and the features of C as a structured programming language developed in the 1970s.

Uploaded by

calistaugin
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 72

2

* Memory Unit

To store programs, input data, intermediated and final results

* Input Unit

To obtain input data

* Output Unit

To provide final results as output

A Computer program or software is a sequence of operations performed on the given


input data to produce desired output. Any notation to represent the data and describe the
sequence of operations on it is called a programming language. The stored program model
of computing or Von Newumann computing methodology stipulates the entire program and the
data to be placed in the main memory before the CPU starts executing the program.

Ever since the inception of computers, hundreds of programming languages have been
designed and implemented. Most programmers never use more than a few languages.

However, a study of the broad concepts, underlying programming language design helps
a programmer.
3

- To enhance the understanding of languages known.

- To easily remember useful programming constructs.

- To choose an appropriate language for a given application development.

- To make learning and designing new languages easier.

The design and implementation of programming languages has undergone rapid evolution.
There are several aspects that determine the preference of programmers.

Some of the pertinent features of popular languages are:

- Clarity.

- Simplicity.

- Clear language objectives.

- Simple sentence forms.

- Ease of program verification.

- Specific supports for the application.

- Provisions for hiding mundane details.

- Good facilities to correct errors.

- Clear and simple documentation.

- Capability to execute the programs across different systems.

- Standards compliance.

- Optimal cost of execution, creation, translation and maintenance.

Those languages that are suitable for a wide range of applications are called general
purpose languages. Specific purpose languages are tailor made for particular application
domains. These languages have notations that cater to domain specific applications. Hardware
Description Languages used to describe electronic circuits are examples for specific purpose
languages. This lesson focuses on general purpose programming languages.
4

The design of programming languages is influenced by the following factors:

- Hardware

- Operating environment.

- Applications.

- Models for effective expression of the sequence of operations programming paradigms.

- Theoretical basis including formal proofs for verification.

- Standardisation.

Table 1.1 traces evolution or programming languages highlighting the major influences
at each stage.

Time frame Influence

1950-1955 Primitive computers, Assembly and machine languages, Subprograms, Data


structures, Possibility of level languages

1956-1960 Small, Slow and Expensive computers. mass storage devices, Compilers,
Interpreters code optimization Dynamic Storage management, Notations
for grammars, List processing

1961-1965 Large Expensive computers, Magnetic disk mass storage, Operating


systems, Multi-programming, Syntax directed calipers. Emphasis on general
purpose languages

1966-1970 Instruction sets for computers with varying Size, Speed, expensive mass
storage, Time sharing, Interactive operative environment, Micro
programming, Optimizing compilers, Standard languages flexibility.

1971-1975 Microcomputers, Small, Cheap mass storage, Programming, Software


engineering.

1976-1980 Powerful, Cheap computers, Distributed systems, Embedded systems,


Concurrent programming, Formal semantics, Reliability

1981-1985 Database environments, Focus on Artificial object oriented programming

Table 1.1: Major influences on programming Languages


5

Today programming languages cater to wide ranging operating environment. Table 1.2
Outlines the influence of Operating Environment on language design.

Factor Batch Systems Interactive systems Embedded Systems

Input/output Sequential Files Standard Files Special Devices

Error Handling Re-run Good Diagnosis Recovery is Vial

Timing Constraints None Good Response Stringent (Real Time)

Structure Main block Collection of functions Concurrent Blocks

Table 1.2: Influence of Operating Environment

The distributed and real-time environments are categorized under embedded systems.
The software industry witnessed a rapid increase in the complexity of software problems. Today,
thousands of programmers are needed to solve a given problem. As a consequence, different
models for expressing the solution have been evolved. The object-oriented methodology caters
to large programming have been evolved. The object-oriented methodology caters to large
programming efforts. Also, special considerations play an important role in designing languages
for interacting databases.

When a Central Processing Unit (CPU) comes off the assembly line, the built-in capabilities
are arithmetic and logical operations, input and output and some control functions. A
corresponding set of instructions is also supported. It is to be noted that every brand of CPU
can have a distinct set of instructions.

A programming language is a systematic notation ‘by which computational process are


described. ‘The computational process is a sequence of operations which a machine can perform
for solving the problem at hand. Languages are classified into generations depending on the
sophistication they offer to the programmer in expressing his solution.

1) First Generation Languages

These languages also known as machine languages are closest to the machine
interpretable form. The interpretable of the machine was represented using binary codes called
‘opcods.’ The data was required by the instruction is called an operand’. There are a few
6

standard formats to specify the requisite operand (s). The operands are also expressed as
string of binary sequences.

A typical machine language instruction is thus a sequence of bits. It comprises of parts


namely ‘opcode’ and ‘operands’. The operands are usually address locations in the main memory
internal registers of the CPU. Certain types of instructions permit the user to specify atleast
one operand along with the opcode. A programmer expresses the sequence of operations as
machine instructions. Each such instruction can be interpreted only by the computer.

Programming and usage of the machine was only for people well versed with the machine.
Moreover it was highly error prone and tedious. For example a Machine language segment is
as follows:

Address Opcode Operands

0100 01010000

0101 01010010

0102 10110100 00001001

0104 10110100 00000001 00001101

0107 11001101 00100001

0109 01011010

2) Second Generation Languages

It was a feeble attempt in making programming friendly. The ‘opcode and the operands
are represented as pre-specified symbolic names. These names which look like English words
are called mnemonics. Every mnemonic has a one-to-one correspondence to the machine
instructions (opcodes).

The operands are specified using symbolic addresses. A software program called
assembler converts the program in assembly language into machine language. The mnemonics
can be unique for a given brand of the CPU. For example an language segment is as follows:
7

Mnemonic Operands

PUSH AX

PUSH DX

MOV AH,9

MOV DX, OFFSET

INT 21H

3) Third Generation Languages

These are usually called high level languages. Ever since the inception of computers,
efforts were on to design programming language that resemble natural language. These
language would permit ease of learning, natural ability to express solutions and team efforts.
Moreover, they are hardware independent. A compiler or an interpreter translates the programs
into machine language. Every high level language statement is translated into a sequence of
machine language instructions. Some of the popular third generation languages are BASIC,
FORTRAN, COBOL, PASCAL, C, ADA, C+ + etc.

Every high level language programme is also a sequence of statements. Each statement
has a specific format or syntax. The grammar of a language is a notation to specify the syntax
of various legal sentences of the language. The meaning of the sentence in terms of the
machine instruction sequence is called ‘semantics’ of the statement.

A compiler is a program to translate the entire sequence of statements into the


corresponding machine code or object code. Optimization of object code is possible using
compilers. Also once the object code is generated the entire memory is for this code only.

An interpreter translates the program, statement by statement. It is present in the main


memory at run time also. It is extremely efficient to implement languages ‘requiring sophisticated
run time environment support.

Third generation languages opened up the area of computer programming to a vast


multitude of programmers .Several advanced facilities to make programming easier were
incorporated into high level languages. They are designed with the focus on the end-user to
8

the programmer. Standard compiler writing tools and techniques ensured that they get correctly
translated into the machine code.

4) Fourth Generation Languages

Interactions with databases are typically in the form of short and specific enquiries. A
standard sequence of operations are clubbed together in the form of a statement called ‘Query’.
A collection of such query formats is called a query languages. As the target applications are
database oriented these languages have nice applications base.

5) Fifth Generation Languages

The problem in application domains such as Intelligence are complex and require special
supporting features to efficiently express the solutions. Fifth generation languages are designed
to cater to these needs. Some popular fifth generation languages are LISP, PROLOG,
SMALLTALK etc.

6) Database Methodology

Third generation languages demand considerable time to develop proficiency in that


language. The inertia in learning a new language and the high costs of retraining are often very
prominent drawbacks. Moreover, they do not the aid solution to the problem. Owing to the
complex concepts and syntax the computing power remains accessible to professional
programmers.

The reduction in price of computer systems and availability of inexpensive mass storage
mechanisms paved way for extensive database applications. These databases form the life-
line of organizations across the globe.

A good database management system permit the user to

 CREATE a database

 ADD new data

 ORGANIZE the database into some meaningful order

 MODIFY data
9

 INSERT records at specified places

 REMOVE irrelevant data

 GENERATE reports

 SEARCH the database for specific information

 INT*EGRITY checks on the data

 SECURITY of access

Interactions with database are typically in the form of short and specific enquiries. A
standard sequence of operations are clubbed together in the form of a statement called ‘Query’.
Often the types of queries are also innumerable. A collection of such query formats is called a
Query language. An easy interface called the front-end of a database helps naive users in
constructing queries.

The languages confining to this paradigm are the fourth generation languages. The Chief
characteristics of these languages are as follows:

 Non-procedural code

 Graded levels of user friendliness

 Self teaching software

 Interactive dialogues which clearly specify possible choices at every step.

 Limited functionality and quickly operational

 Fully and consistently defined default options

 Niche applications base

 Simplicity of query formats

 Easy report generation facilities

 Support for generation facilities

 Interfaces to other languages paradigms to harness their capabilities

 Automated documentation
10

 Extensive re-usable modules

 Fast prototyping

 Standards conformance

 Verifiable data models

 Simple code structures

 Automatic code structures

 Ease of maintenance

Check Your Progress - I


1) State whether the following are True or False.

a) A prescribed set of well - defined rules or processes for the solution of a problem in
a series of step is Flow Chart.

b) A program written in machine language is called Object Program.

2) Fill in the blanks

a) is a program to translate the entire sequence of statements into the


corresponding machine code or Object code.

b) translates the program, statement by statement.

c) C was originally developed in 1970’s by .

1.4 Introduction to C languages

C is a general-purpose structured programming language. Its instructions consist of terms


that resemble algebraic expressions, augmented by certain English keywords such as if, else,
for, do and while. In this respect C resembles other high-level structured programming languages
such as Pascal and FORTRAN-77. C also contains certain additional features, however that
allow it to be used at a lower level, thus bridging the gap between machine language and the
more conventional high-languages

This flexibility allows C to be used for systems programming (e.g. for writing operating
systems) as well as for applications programming (e.g. for writing a program to solve a
complicated system of mathematical equations, or for writing a program to bill customers)
11

C is characterized by the ability to write very concise source programs, due to the large
number of operators included within the language. It has a relatively small instruction set,
though actual implementations include extensive library functions which enhance the basic
instructions. Furthermore, the language encourages users to write additional library functions
of their own. Thus, the features and capabilities of the language can easily be extended by the
user.

C compilers are commonly available for computers of all sizes, and C interpreters are
becoming increasingly common. The compilers are usually compact, and they generate object
programs that are small and highly efficient when compared with programs compiled from
other high-level languages. The interpreters are less efficient, though they are easier to use
when developing a new program. Many programmers begin with an interpreter, and then switch
to a complier once the program has been debugged (once all of the programming errors have
been removed).

Another important characteristic of C is that its programs are highly portable, even more
so than with other high-level languages. The reason for this is that C relegates most computer
dependant features to its library functions. Thus, every version of C is accompanied by its own
set of library functions, which are written for the particular characteristics of the host computer.
These library function are relatively standardized. However, each manner from one version of
C to another. Therefire, most C programs can be processed on many different computers with
little or no alteration.

1) History of C

C was originally developed in the 1970’s by Dennins Ritchie at Bell Telephone Laboratories.
It is an outgrowth of two earlier languages, called BCPL and B, which were also developed at
Bell Laboratories. C was largely confined to use within Bell Laboratories until 1978, when Brian
Kernighan and Ritchie published a definitive description of the language (K&RC)

Following the publication of the K&R description, computer professionals, with C’s many
describable features, began to promote the use of the language. By the mid 1980’s the popularity
of C had become widespread. Numerous C compilers and interpreters had been written for
12

computers of all sizes and many commercial application programs had been developed.
Moreover, many commercial software products that were originally written in other languages
were rewritten in C in order to take advantage of its efficiency and its portability.

Most commercial implementations of C differ somewhat from Kernigham and Ritchie’s


original definition. This has created some minor incompatibilities among different
implementations of the language, thus diminishing the portability that the language attempts to
provide. Consequently, the American National Standards Institute (ANSI) has begun work on a
standardized definition of the C language. Most commercial C compilers and interpreters are
expected to adopt the ANSI standard once it has been completed. They may also provide
additional features of their own.

2) Structure of a C Program

Every C program consists of one or more functions, one of which must be called main.
The program will always begin by executing the main function. Additional function definitions
may precede or follow main.

Each function must contain the following:

(a) A function heading, which consists of the function name, followed by an optional list of
argument enclosed in parentheses.

(b) A list of argument declarations, if argument are included in the heading.

(c) A compound statement, which comprises the remainder of the function.

The arguments are symbols that represent information being passed between the function
and other parts of the program. (Arguments are also referred to as parameters).

Each compound statement is enclosed within a pair of braces, i.e.{and}. The braces may
contain combination of elementary statements (called expression statements) and other
compound statements. Thus, Compound statements may be nested, one within another. Each
expression statement must end with a semicolon(;).

Comments may appear anywhere within a program, as long as they are placed within
delimiters /*and*/
13

e.g./* this is a comment */

such statement are helpful in identifying the program’s principal features or in explaining
the underlying logic of various program features.

These program components will be discussed in much greater detail later.

Example:

This is an elementary C program that reads the temperature in centigrade and converts
it into Fahrenheit.

#include (stdio.h> /* LIBRARY FILE ACCESS */

/*PROGRAM TO CONVERT TEMPERATURE /*COMMENT LINE1*/

/* IN CENTIGRADE TO FAREAHELIT /* COMMENT LINE 2*/

main ( ) /* FUNCTION HEADING*/

float c, f; /*VARIABLE DECLARATIONS*/

print f (“Enter the temperature in centigrade /n”); /* OUTPUT STATEMENT*/

The following features should be pointed out in the above program.

1. The program is typed in lower case. Most comments are typed in upper case.

2. The first line contains a reference to a special file (called stdio.h) which must be included
in the program when it is compiled.

3. The second line is comment that identifies the purpose of the program.

4. The third line is a heading for the function main. The empty parentheses following the
name of the functions indicate that this function does not include any arguments.

5. The remaining five lines of the program are indented and enclosed within a pair of braces.
These five lines comprise the compound statement within main.

6. The first indented line is a variable declaration. It establishes the symbolic names c and f
as floating point variables which are used to represent centigrade and Farenheit.
14

7. The remaining four indented lines are expression statements. The second indented line
(printf) generates a request for information (namely centigrade).

8. The fourth indented line is a particular type of expression statement called an assignment
statement. This statement cause the conversion of temperature in centigrade to
temperature in fareheit.

9. The last indented line (printf) causes the calculated value for the fareheit to be displayed.
The numerical value will be preceded by a brief label.

10. Note that each expression statement within the compound statement ends with a semicolon.
This is required of all expression statements.

11. Finally, the liberal use of spacing and indentation separate different parts of the program
into logically identifiable components, and the indentation indicates subordinate
relationships among various instructions. These features are not grammatically essential
but their presence is strongly encourages as a matter of good programming practice.

Execution of the program results in an interactive dialog such as that shown below:

Enter temperature in centigrade 10.0

Farenheit equivalent is 50.0

3) Desirable Program Characteristics

Before concluding this lesson let us briefly examine some important characteristics of
well-written computer programs. These characteristics apply to programs that are written in
any programming language. They can provide us with a useful set of guidelines.

1. Integrity. This refers to the accuracy of the calculations. It should be less if the calculations
are not carried out correctly. Thus the integrity of the calculations is an absolute necessity
in any computer program.

2. Clarity. This refers to the overall readability of the program, with particular emphasis on
its underlying logic. If a program is clearly written, it should be possible for another
programmer to follow the program logic without undue effort. It should also be possible
for the original author to follow his or her own program after being away from the objectives
in the design of C is the development of clear, readable programs through an orderly and
disciplined approach to programming.
15

3. Simplicity. The clarity and accuracy of a program are usually enhanced by keeping thing
as simple as possible, consistent with the overall program objectives. In fact, it may be
desirable to sacrifice a certain amount of computational efficiency in order to maintain a
relatively simple, straight forward program structure.

4. Efficiency. This is concerned with execution speed and efficient memory utilization. These
are generally important goals, though they should not be obtained at the expense of
clarity or simplicity. Many complex programs require a trade off between these
characteristics. In such situations, experience and common sense are key factors.

5. Modularity. Many programs can be broken down into a series of identifiable subtasks. It
is good programming practice to implement each of these subtasks as a separate program
module. In C, such modules are written as functions. The use of a modular programming
design enhances the accuracy and clarity of a program, and if facilitates future program
alterations.

6. Generality. Usually we want a program to be as general as possible, within reasonable


limits. For example, we may design a program to read in the values of certain key
parameters rather than placing fixed values into the program. As a rule, a considerable
programming effort.

Check Your Progress - II


1) State whether the following are True or False.

a) Every C program consists of one or more functions, one of which must be called
main.

b) C is a case sensitive language.

2) Fill in the blanks:

a) Each compound statement is enclosed within .

b) Every C program much contain a .

c) A main ( ) function in a C program should be located .

d) Statement in a C program should begin .


16

1.5 Summary

C is a general - purpose structured programming language. Its instructions consist of


terms that resemble algebraic expression, augmented by certain English keywords such as if,
else, for, do and white. ‘C’ to be used for systems programming (as for writing operating systems)
as well as for applications programming (e.g. for writing a program to solve a complicated
systems of mathematical equations).

1.6 Check Your Answers


I. 1) a) False b) True

2) a) Compiler b) Interpreter c) Dennis Ritchie

II. 1) a) True b) True

2) a) a pair of braces b) main ( ) function

c) anywhere in the program d) in any column

1.7 Model Questions


(1) Explain the main components of a computer?

(2) Discuss the major influences on programming languages in different time frames?

(3) Explain the structure of a C language with an illustration?

(4) What are the desirable program characteristics that enhance the program development
effectively?
17

LESSON - 2
VARIABLES AND EXPRESSION

Structure
2.1 Introduction

2.2 Learning Objectives

2.3 Character and variables

2.4 Constants

2.5 Summary

2.6 Check Your Answers

2.7 Model Questions

2.1 Introduction

In c, a quantity which may vary during program execution is called a variable. Variable
names are names given to the locations in memory of a computer where different constant are
stated. There locations can contain character, integer, real or any such constant.

2.2 Learning Objectives


After leaning this lesson, you should be able to

- Character set and variables

- Constants.

2.3 Character Set and Variables

The C character set consists of upper and lower case alphabets digits, special characters
and white spaces. The alphabets and digits are together called the alphanumeric characters.

Alphabets:

ABCDEF ............................... X Y Z

abcdef ............................... x y z
18

Digits:

0123456789

Special Characters:

, comma < opening angle bracket > closing angle bracket

. period - under score ( left parenthesis

; semicolon $ dollar sign ) right parenthesis

: colon % percent sign [ left bracket

# number ? question mark sign ] right bracket

‘apostrophe & ampersand { left brace

“ quotation ^ caret mark } right brace

! exclamation * asterisk mark / slash

| vertical bar - minus sign \ backslash

~ tide + plus sign

White space characters:

blank space newline carriage return

formfeed horizontal tab vertical tab

1) Identifiers and Keywords

In a C program, every word is either classified as an identifier or a keyword. Identifiers,


as the name suggests, are used to identify or name variables, symbolic constants, functions,
etc. Keywords have perdefined meanings and cannot be changed by the user. There are certain
rules regarding identifier names, as enumerated below:

* Identifier names must be a sequence of letters and digits, and must begin with a letter

* The underscore character (‘_’) is considered a letter.

* Name should not be the same as a keyword (such a int, char, void, if for, while, etc.).
Keywords are predefined by the language, and cannot be used by the programmer in any
19

way other than that specified by the syntax. The following keywords are predefined by the
C language.

auto double int struck

break else long switch

case enum register typedef

char extern return union

const float short unsinged

continue for ­singed void

default goto sizeof volatile

do if static while

* C is case sensitive (i.e. upper and lower case letters are treated differently). Thus, the
names rate, Rate and RATE denote different identifiers. It is a general practice to use
lower or mixed case for variable and functions names, and upper case for symbolic
constants.

* For any internal identifier name ( an identifier declared in the same file or in a header
included in the current file), atleast the first 31 characters are significant in any ANSI C, C
compiler (it may be more in certain compilers, but never less)

2) Variables

A variable is an entity that has a value and is known to the program by a name. A variable
definition associates a memory location with the variable name. A variable can have only one
value assigned to it at any given time during the execution of the program. Its value may
change during the execution of the program.

Example 2.1: f = 1.8 * c + 32

In the above example, f and c are variables.

Variable names are identifiers used to name variables. They are symbolic names given
to memory locations. A variables name consists of a sequence of letter and digits, the first
20

character being a letter. The rules that apply to identifiers (given above) also apply to variable
names. Examples of valid variable names are:

i rank MAX min class-mark

student-name emp-num fact-recur Mark studentName

Examples of invalid variable names are:

a’s illegal character (‘)

fact recur blank not allowed

5root first character should be a letter

student, rec comma not allowed

3) Basic Data Types

The C language supports the following basic data types

char a single byte that can hold one character

int an integer

float a single precision floating point number

double a double precision floating point number

Note: Precision refers to the number of significant digits after the decimal point.

Further, applying qualifiers to the above data types yield additional data types. A qualifier
alters the characteristics of the data type, such as its size or sign. The qualifiers that alter the
size are short and long. These qualifiers are applicable to integers, and yield two more data
types:

short int integer represented by a lesser number of bits (Usually 16)

long int integer represented by a greater number of bits (Usually 32)

The exact sizes of these data types depend on the compiler. Details are given later in this
lesson. The qualifiers long can also be used along with double precision floating point type:
21

long double an extended precision floating point number

The sign qualifiers are signed and unsigned. The sign qualifiers are combined with the
integer data types (int, short int and long m) resulting in six more data types given below:

signed short int

unsigned short int

signed int

signed long int

unsigned long int

These are also applicable to the char data type

signed char

unsigned char

Normally, size qualifiers (short and long) cannot be applied to the data types char and
float, and sign qualifiers (signed and unsigned) cannot be applied to float, double and long
double.

4) Declare Variables

In C, you always have to declare a variable before using it. Before going into the details
of declaring and using the variable types, we need to understand how to input and output
simple strings. The following example illustrates the use of printf to output an integer.

/*integer. c: An example illustrating an integer output. */

# include <stdio.h >

void main ()

{int val;

val = 10;

printf (“%d”, val);}

The output of the program is as follows: 10


22

The program is now explained line by line: int val; is the first statement in the function
main (). it declares the identifier val to be a variable of integer type. In declare a variable of
some type. Precede its name of the data type (float, char and so on). For instance, if a variable
f_val is to be declared a floating point number, then declare f_val as:

float f-val;

Coming back to the program, having declared val an integer, assign a value to it with the
statement:

val = 10;

Before this statement is executed, the value of val is undefined.

Let us now examine the third statement inside the function main ( ):

printf ( “%d”, val);

This outputs, the value of the integer variable val. In the discussion that follows, we shall
use the word parameter to refer to any variable or constant that is passed to a function. Thus,
in the printf statement above, the first parameter is “%d” and the second parameter is val.

The first parameter passed to the function printf is always a string called the format string
enclosed in double quotes. In the above case “%d” is the format string. It tells printf that the
output is an int. The second parameter val provides the actual value to output.

Similarly, %f must be used as the format string to output floating point numbers, %c for
single characters, and so on. All the format types are discussed in detail in the next lesson.
Inside the format string, the % sign followed by a letter informs printf about the type of the
parameter to be output. But the contents of the format string are not restricted to this kind of
type-specifies. Let us examine the previous example again, this time adding something more
to the message.

/* float.c: An example illustrating integer and floating point output. */

# include <stdio.h>

void main ( )
23

{int i_var;

float f_var;

i_var = 10;

f_var = 100.3125;

printf (“i_var is %d and f_var is %f”, i_var, f_var);}

The output of this program is :

i_var is 10 and f_var is 100.3125

From the program, it is observed that more than one parameter can be present, following
the format string in a printf statement. Inside the format string, %d and %f specify the type of
the variables to be output. They are called format specifiers. The first format specifier, %d
corresponds to the first parameter that follows the format string, i_var. It informs printf that
i_var is an integer. Similarly, the second one, %f specifies that f_var is a floating - point number.

The above example illustrates the fact that the output produced by printf is the same as
the format string, except that %d is replaced by the value of the parameter i_var, and %f by the
value of f_var. The first parameter passed to printf, “i_var is the format string, while %d and %f
inside it are the format specifiers.

To summarize, the parameters passed to the printf statement consist of a format string,
followed by any number of parameters. However, each parameter must have a format specifier
(%sign followed by a letter) corresponding to it, inside the format string.

5) printf Format Specifier

In addition to specifying the type of the parameter, the format specifier in printf can also
perform the function of specifying how parameter must be output (for example, in decimal or
hexadecimal). The specifiers %d and %i can be used interchangeably to output integers. Thus,
the statement,

printf ( “%d”, val );

can be replaced by,

printf ( “%i”, val );


24

to get the same output. Also, note that % u and % x are used to output unsigned integers,
but there is a difference, % u outputs it in decimal, while %x outputs it in hexadecimal. To
illustrate this concept, a simple example that converts unsigned decimal numbers to hexadecimal
is given below. Underlined data in this book indicate user input. The function scanf in this
program is new, and is examined in the next section.

/* decimal.c: Conversion of unsigned decimal to hexadecimal number */

# include < stdio.h>

void main ()

{unsigned int inp_int;

scanf ( “%u,” &inp_int);

printf ( “The input integer (in decimal) is %u/n”, inp_int);

printf ( “The input intger (in hexadecimal) is % x/n”, inp_int);}

RUN : 45

The input integer (in decimal) is 45

The input integer (in hexadecimal) is 2d

6) Reading Variables

The scanf function reads the values of variable from the standard input device (keyboard)
and stores them in variables. The example below inputs the again years and computes the
numbers of seconds you have lived. For simplicity, leap years have been ignored.

/* scanf.c: scanf example */

# include <stdio.h>

void main ( )

{float years, secs;

printf ( “Input your age in years: “);


25

scanf ( “%f”, &years: “);

secs = years *34 * 24 * 60 * 60;

printf ( “you have lived for %f seconds /n”, secs ); }

A sample session with the program is given below, where the user has input 21.

Input your age in years: 21

You have lived for 662256000.0 seconds

The statement

scanf (“%f ,” & years);

performs the task of reading the value of the variable years. Like the printf function, the
scan function accepts a format string as its first parameter. But, the second parameter years
(the variable whose value we want to read) is preceded by an ampersand (&). An ampersand
is not required in the case of printf. To understand this, it is necessary to consider a crucial
difference between the two functions. The function printf, whose task is to output, needs only
the value which has to be output. On the other hand, the scanf function stores the input value
in a memory location. To perform this, it must know the location of the variable in memory
(called the memory address of the variable) where the value has to be stored.

To understand the concept of memory address clearly, recall that the computer’s memory
consists of bytes. These bytes are numbered, starting with zero (i.e., the first byte is byte
number of, the second one is byte number 1, and so on). These numbers are called the address
of the bytes.

Each variable in a program occupies a certain number of 1 bytes of the memory. Consider
the floating point variable years in the above example. Assume that it occupies four consecutive
bytes numbered 3064, 3065 and 3067 in the memory. So, the address of years is 3064 (the
lowest numbered memory location). It is this address that scanf requires. In C. the address of
any variable is obtained by preceding the variable name by an ampersand (&)
26

The statement

scanf ( “%f”, &years );

The first parameter “%f” instructs scanf that a floating point numbers must be read. The
second parameter & years informs scanf the location in the memory where the value of the
floating point number entered by the user must be stored.

7) Characters and Character Strings

A character variable can hold one character, which can be any alphabet or symbol.
Characters in C are enclosed within single quotes. The following example illustrates the task of
assigning values to character variables.

/* char.c: Character assignment example. */

# include < stdio.h>

void main ( )

{/* Declare a character. */

chare c;

/* Assign the symbol # to it . Note the single quotes.*/

c = ‘#’;

printf ( “ This is the hash symbol: c/n”, c) ; }

The output is as follows:

This is the hash symbol: #

In the above example, c is a character variable. The character # assigned to c, is enclosed


within a pairs of single quotes (‘). Note that while strings are enclosed in double quotes,
characters are enclosed in single quotes. The format specifier % c is used in the statement:

printf ( “ This is the hash symbol: % c/n”,c);

It specifies that a characters can be treated as integers. To understand this, we must


clarify the concept of value of character variable. A character variable holds one character,
27

which may be a letter, a digit, a punctuation mark, and so on. These character are represented
in the memory by a number, called the code of the character. For example, the code of the
letter A may be 65, that of letter B may be 66, and so on.

Actually, any number can represent the letter A, any other number can be used for B and
so on, but these numbers should be fixed by a coding convention. For example, when the
computer wants the printer to print the letter A, it actully sends the number 65 to the printer. The
important point here is that the printer must see the number 65 and print the letter A, and not
something else. Hence, the printer must also use the same codes as the computer, for all the
symbols. This led to the establishment of ASCII codes (ASCII: American Standard Code for
Information Interchange). ASCII codes are widely used all over the world to represent various
symbols in a computer. In C, the size of one character is 8 bits (one byte).

Here is a simple example that reads the ACII code of a number and prints out the symbol
associated with the code.

/* ascii.c: ASCII code example */

# include <stdio.h>

void main ()

{int code;

char symbol;

printf ( “ Input an ASCII code (0 to 127): “ );

scanf ( “ % d “ , & code);

symbol = code

printf ( “ The symbol corresponding to % d is % c/n “, code, symbol ) ; }

Run 1 :

Input an ASCII code ( 0 to 127): 75

The symbol corresponding to 75 is K


28

Run 2 :
Input an ASCII code (0 to 127) : 50

The symbol corresponding to 50 is 2

The second run shows that just as the letter A is a symbol having as ASCII code, the digit
2 is also a symbol having an ASCII code of the digit 0 is 48, that of 1 is 49 and so on. To
illustrate, let us say that the computer has to print the number 3210. It sends the following
codes to the printer: 51 50 49 48

These are the ASCII codes of the digits 3,2.1 and 0, respectively.

Coming back to the program, statement

symbol = code;

Assigns the value of the integer variable code to the character variable symbol. In the
printf statement,

printf ( “ The symbol corresponding to %d is %c\n “, code, symbol);

%d is used to output its ASCII code contained in the integer code. The format specifier %
c is used to output the actual symbol corresponding to the value contained in the character
variable symbol.

We now come to the topic of strings. A strings in C is a sequence of consecutive characters


in the memory, the last one being the null character. A null character has an ASCII code O, and
is called the end - of - string marker in C. A string variable having 20 characters can be declared
by using the statement:

char my_string [ 20 ]

Strings are enclosed within double quotes. Consider an example that assigns a string
and prints it on the screen. The format specifier for a string is % s, which can be observed in
the printf statement in the example below:
29

/* string.c: String example */

# include <stdio.h>

void main ( )

{char my_string [ 20 ] = “ 13 is unlucky .”;

printf ( “my_string ; %s\n” , my_string ) ; }

The format specifier % s is replaced by the value of the string constant. The output of the
program is as shown below:

my_string: 13 is unlucky.

The variable my_string is just a sequence of bytes in memory whose values are the
ASCII codes of each symbol of the string. The null character (a byte with value zero) is placed
at the end of the string. Giben below are the character of my_string and their values in memory.

String : 1 3 i s u n l u

ASCIICode 49 51 32 105 115 32 117 110 108 117

String : c k y . /0

ASCII code : 99 107 121 46 0

The number are the ASCII codes of the individual characters of the string (the ASCII
code of the letters is 115, that of y is 121 and so on). The value 0 appearing at the end is the
null character. It serves to terminate the string (i.e., marks the end of the string).

8) Qualifiers

Qualifiers modify the behavior of the variable type to which they are applied. We have
seen declarations such as

int i ;

This declaration specifies that i is an integer which takes both positive and negative
values, that is, i is a signed integer by default. The above declaration could also be written as
30

singed int i ;

but the qualifier signed is not necessary, since int is signed by default. If the variable i is
used to hold only positive values (for example, to hold the number of students in a class), we
declare:

unsigned int i ;

Here, the qualifier unsigned is applied to the data type int. This qualifier modifies the
behavior of the integer so that the number contained in a variable of this type is unsigned.

Qualifiers can be classifies into two types:

- Size qualifiers

- Sign qualifiers

Size Qualifiers, applied to int

Size qualifiers alter the size of the basic data type. There are two size of the basic data
type. There are two size qualifiers that can be applied to integers (i.e., to the basic type int):
short and long. In any ANSI C compiler, the sizes of short int, int and long int follow the restrictions
given below:

 The minimum size of a short int is 16 bits

 The size of an int must be greater than or equal to that of a short int

 The size of a long int must be greater than or equal to that of an int

 The minimum size of a long int is 32 bits

In most compilers available on DOS, the size of a short int and an int are the same, both
occupying 16 bits. A long int occupies 32 bits. But in 32 - bit compilers such as GNU C, an int
and a long int are of the same size (32 bits), while short int is 16 bits. On the other hand, almost
all UNIX compilers have short int of size 16 bits, int and long int being 32 bits.

Size of Operator

To find out the size of each type on your compiler, try the example below. It uses the size
of operator, that gives the size of any data type in bytes.
31

/* size.c: example to illustrate size of operator /

# include <stdio.h>

void main ( )

{ printf ( “Size of a short int is % d\n”, size of (short int) );

printf ( “size of an int is % d\n”, size of (int) );)

printf ( “size of a long int is % d\n”, sizeof (long int) );}

The output of this program when compiled with Borland’s compiler (Borland C Version
3.0) and run, gives the following output:

Size of a short int is 2

Size of an int is 2

Size of a long int is 4

On almost all UNIX systems, the program gives the following output:

Size of a short int is 2

Size of an int is 4

Size of a long int is 4

The name of the variable type is passed to the size of operator in closed parentheses.
The number of bytes occupied by a variable of that type is given by the size of operator. The
size of operator is very useful in developing portable programs. It is a bad practice to assume
the size of a particular type since its size may very from compiler to compiler.

The size of operator also takes variable names and returns the size of the variable given,
in bytes.

For example, the statements,

int i;

printf ( “ The size of i is %d/n”, size of (i) );

will output (on a compiler where int is 16 - bit):

The size of i is 2
32

The result would have been the same if size of (int) had been used instead of size of (i),
since i is an int. But passing the variable name to size of is a better practice. If the type of i has
to be changed later, the rest of the program need not be modified.

What are the format specifiers used in the printf format string for short and long integers?
For short integers, kit is %hd (or % hi) and for long integers, it is %d (or % li). The following
example illustrates input-output statement for short and long integers.

/* inout.c: Input - output of short and long ints. */

# include main ()

{short int shorti;

long int longi;

printf ( “Input long int:”);

scanf ( “%hd “, &shorti );

printf ( “Input long int:” );

scanf ( “%d” , & longi ) ;

printf ( “shorti = %hd and longi = %d”, shorti, longi ) ; }

A sample run is given below :

Input short int: 12

Input long int: 2000000000

——————

shorti = 12 and longi = 2000000000

limits.h

The header file limits.h contains the largest and smallest values that each of the various
data types can hold. The name of the constant, the meaning, and the smallest acceptable
magnitude is given in lesson 7.
33

Size qualifier for double

The type qualifier long can also be applied to the data type double. A variable of the type
long double has more precision than a variable of the type double. Observe that C provides
three data types for real numbers: float, double and long double. In any C compilers, you can
be sure that the precision of a double is greater than or equal to that of float, and that the
precision of a long double is greater than or equal to that of a double, i.e.,

precision of long double > = precision of double > = precision of float

Regarding the range that a floating point number can hold, the ANSI standard does not
specify whether one type of floating point number can hold more than the other. So different
compilers may provide different ranges for floating point numbers. The standard guarantees
that the maximum floating point number is at 37 least 102.

Some compilers may provide a greater range. To find out the actual range that compiler
offers, a program may refer to the constants defined in float.

Sign Qualifiers

The keywords signed and unsigned are the two sign qualifiers that specify whether a
variable can hold both negative and positive numbers, or only positive numbers. These qualifiers
can be applied to the data types int and char only.

An example of declaring an unsigned integer is :

unsinged int it;

As mentioned before, signed int is the same as int ( i.e., int is signed by default). The type
char may be the same as either signed chare or unsigned char. This varies from compilers give
the option of treating a char as singed or fact, many compilers give the option of treating a char
as singed or unsigned. This fact (whether a char is signed or unsigned) does not matter when
we use a variable of the type char to hold a single character. But when used as an 8-bit integer,
it does matter whether the variable type dealt with is signed or unsigned.

9) typedef Statement

The typedef statement is used to give new names to existing types. For example, the
statement
34

typedef unsigned, long ulong;

declares ulong a new type. Equivalent to unsigned long. It can be used just as any other
type in a program For example the statement,

ulong u;

declares u to be of the type ulong. Also sizeof (ulong) gives the size of the new variable
type in bytes.

10) Promotion and Typecasting

Consider the following example which assigns int to a float:

int i;

float f;

i = 5;

f = i;

The last statement assigns i to f. Since i is an integer while f is a floating point variable,
the integer i is converted to float automatically. This type of conversion, when the variable of
lower type (which holds lower precision) is converted to higher type (which holds higher range
of values or has higher precision) is converted to a higher precision is called promotion.

Another example of promotion is the conversion of a character to an integer. This particular


type of promotion is called integral promotion. For example,

int i;

char c;

c = ‘a’;

i = c;

The value present in the character variable c, i.e., the ASCII code of the character a is
assigned to the character a is assigned to the integer i. If an integer is represented by sixteen
bits, the lower eight bits will have the value of the while the upper eight bits will be filled with
zeros. In some cases, the upper bits are filled with ones instead of zeros. To understand this,
let us examine the concept of sign extension.
35

Conversion to a signed integer involves extending the sign. In case of signed numbers,
the most significant bit is assumed to be the sign. If this bit is l, the number is assumed to be
negative, and if it is 0, it is assumed to be positive. When a character having its most significant
bit set to one is assigned to a signed integer, the lower eight bits will be filled with l’s. On the
other hand, if the character value has its most significant bit set property of filling the upper bits
of the higher type with 0’s. This of the lower type is called sign extension. Sign extension takes
place only if the variable of the higher type is signed. If the variable of the higher type is
unsigned, its upper bits will always be filled with 0’s

Assignments of variable of higher types of lower types result in truncation. For example,
the sequence,

f = 7.5;

i = f;

results in the fractional part (.5) discarded. The value 7 is assigned to the integer i.

In addition to automatic conversions, we can forcibly convert one type to another. The
following example illustrates the need for forcible conversion.

int i, j;

float f;

i = 12;

j = 5;

f = i/j;

printf ( “ %f \n” , f);

The output of this sequence of statement is as follow: 2

This is inspite of the fact that 12/5 is 2.4 and it can be assigned to f. Since both i and j are
integers in the expression,

f = i/j

Integer division takes place, and the quotient 2 is assigned to f. Though the variable on
the left-hand side of the assignment operator is a floating point variable, it does not cause
36

floating point division to take place. One of the operands involved in the division must be a
floating point number. We can achieve this by temporarily converting either i or j to a floating
point number. The division expression must be changed to

f = (float) i/j;

We are explicitly converting i to floating point number in the above expression. Explicit
type conversions are called typecasting. The general syntax of typecasting given below:

(type) variable - name

The type name to which conversion is to be done is placed in closed parentheses preceding
the variable name.

Typecasting can also be used to convert a higher type to a lower type. For example, if f
is a float whose value is 2.7, the expression,

(int) f

evaluates to 2.

11) Value-initialized Variables

We can declare an integer variable i by the statement:

int i;

In order to initialize the variable i we can use two statements as shown below:

int i;

i = 5;

and then use the variable i. A simpler way to achieve this is to combine them into a single
statement as given below:

int i = 5

A statement like the one above is preferred, since it is simpler, less prone to mistakes,
and often leads to more efficient programs. When multiple variable are being declared in a
single statement, initialization is done in the following way:

int i = 10, j = 5 ;
37

Also, the right side of the = symbol can have an expression. For following is a valid
sequence of statement:

int i = 10, j = 5;

int k = i/j;

that will initialize the value of k to 2.

Check Your Progress - I


1) State whether the following are True or False.

a) A quantity which may vary during program execution is called variables.

b) The first character in the variable name must be a number.

2) Fill in the blanks:

a) The range for integer is .

b) The size of character is .

c) Real constants are often called .

2.4 Constants

A constant does not change its value during the entire execution of the program. Constants
can be classified as integer constants, floating point constants, character constants and
enumeration constants. Additionally, string literal can specify strings.

Example
Valid constants 48 6432 001

Invalid constants 964 (space not allowed )

1) Integer Constants

Integer constants can be specified in three ways: (i) Ordinary decimal numbers (base
10). For example, 175 is an integer constant specified in base 10. (ii) Octal numbers (base8).
Octal numbers are specified with a leading zero, rest of the digits consists of those lying between
0 and 7. For example, 0175 is an integer consist specified in octal whose base 10 or decimal
38

value is 125. (iii) Hexadecimal numbers (base 16). Hexadecimal numbers are specified with 0x
or OX the beginning. The digits that follow Ox must be numbers in the range 0-9 or one of the
letters a-f or A-F example, OX175 is the same as Ox175, i.e., either a lower case or an upper
cans x can used.

A size or sign qualifier can be appended at the end of the constant. The suffix u is used
for unsigned int constants, l for long int constants and s for short int constants. Either of the
cases can be used.

Example
1. unsigned integer constants

56789U

56789u

2. Long integer constants

7689909L

7689909l

0675434L (A long integer constant specified in octal)

0x34ADL (A long integer constant in hexadecimal with upper and lower case letters)

3. The suffixes can be combined and can be specified in any order

6578890994Ul

6578890994ul

We can use smaller integer constants that are stored with fewer bits for which the qualifiers
used are s and us.

4. Short integer constants

120S - 1000s

5. Unsigned short integer constants

120US

1000us
39

Ordinarily, these suffixes are not needed. The compiler considers large integer constants
to be of the type long automatically. These suffixes are useful in situations where the value
may fit in an int but you want to treat it as long.

2) Floating Point Constants

Floating point constants have decimal point or an exponential sign or both.

Decimal notation: Here the number is represented as a whole number followed by a


decimal point and a fractional part. It is possible to omit digits before or after the decimal point.

The following are examples of valid floating point constants:

241., .976, -.71 and + .5

Exponential notation: Exponential notation is useful in representing numbers whose


magnitudes are very large or very small. The exponential notation consists of a mantissa and
an exponent. The exponent is positive unless preceded by a minus sign. Consider the number
231.78. This can also be written as 0.23178e3 representing the number 0.23178 is the mantissa,
and 3 is the exponent.

As another example, the number 75000000000 can be written as 75e9 or 75e11. Similarly
0,00000000045 can be written as 0.45e-9.

(i) The following examples are valid constants

2000.0434

3.4e4

3e8

(ii) The following are some invalid constants

3.4E.4 exponent must be an integer

3e 8 blank not allowed

Normalized exponential representation is the one in which the value of the mantissa is
adjusted to a value between 0.1 and 0.99. For example, the number 75000000000 is written as
0.75e11 after normalization.
40

The mantissa exponential representation of real constants are given below.

The mantissa is either a real number expressed in decimal notation or an integer.

The mantissa can be preceded by a sign.

The exponent is an integer preceded by an optional sign.

The letter ‘e’ can be written in lowercase or uppercase.

Embedded white space is not allowed.

By default, real constants are assumed to be double. Suffixes for F can be used to
specify the float values. For example, 0.257 is assumed to be a double constant, while 0.257f
is a float constant. l or L can be used to specify long double values. For example, 0.257L is a
long double constant.

3) Character Constants

A character constants is enclosed within single quotes.

Example 2.4

Valid character constants: ‘a’ ‘5’ ‘\n’

Invalid character constants ‘ab’ ‘54’

Note: Multiple characters can also be enclosed within single quotes. The compiler will
not report any error. The value of the constant however, depends upon the compiler used. This
notation of having multiple characters within single quotes is practically never used.

In side the single quotes, a backslash character starts an escape sequence. \xhh specifies a
character constant in hexadecimal, where his any hexadecimal digit. The hexadecimal digits hh
give the ASCII value of the character. For example, the character constant \xo7 represents the BEL
character. Run the following program to hear a beep on the computer.

/* beep.c: example illustrating Beep sound */

# include <stdio.h>

void main ( )

{printf ( “%c”, ‘\x07’ ); }


41

\0ooo specifies a character constant in octal where, o is any octal digit. As before, ooo is
the ASCII value of the number specified in octal. For example the ASCII code of K is 75. the
character constant \0113 specifies this character in octal.

The complete list of escape sequences is given below

\a Beep (Alert)

\b Backspace

\f Formfeed

\n Newline

\t Horizontal tab

\r Carriage return

\\ Backslash

\’ Single quote

\” Double quote

\v Vertical tab

\? Question mark

\0 Null

\0oooCode specified in octal

\xhh Code specified in hexadecimal

Hence, \xo7 in the printf statement in the above example can be replaced by \a.

Example

(i) printf ( “\\ is a backslash. \n” ); will print as follows:

\ is a backslash.

(ii) printf ( “This \” is double quote.\n” ); will print:

This “ is a double quote.


42

4) Enumeration Constants

An enumeration is a user defined type with value ranging over a finite set of identifiers
called enumeration constants. For example,

enum color {red, blue, green};

defines color as a new type having three values. red, blue and green. Each of these is an
enumeration constant. In the program, color can be used as a new type. A variable of type
color can have any one of the three values: red, blue or green. For example, the statement,

color c;

declares C to be of type color. Internally the C compiler treats an enum type (such as
color) as an integer itself. The identifiers red, blue and green above represent the consecutive
integer values of 0, 1 and 2 respectively. So, the statement,

c = blue;

printf ( “As an int, c has the value %d\n”, c );

will print,

As an int, c has the value 1

Constant values can be explicitly specified for the identifiers. When the value of one
identifier is specified in this manner, the value of the next element is the next higher integer.

For example, if the definition of color is

enum color {red = 10, blue, green = 34};

Then the statement c = red will assign the value 10 to c.c = blue will assign the value 11
to c, and c= green will assign the value 34. If no value is specified for green, it will assume the
value 12.

Enumerations are a convenient way to associate constant integers with meaningful names.
They have the advantage of generating the values automatically. Use of enumeration constants,
in general, makes the program easy to read and change at a later date.
43

Names in different enum must be distinct. The following example is invalid.

enum emotion {happy, hot, cool};

enum weather {hot, cold, wet};

It is not difficult to see why the above declarations are invalid It is because, the name hot
has the value 1 in enum emotion and the value 0 in weather. In the program, if you use the
name hot, there is an ambiguity as to which value to use. On the other hand, values need not
be distinct in the same enumeration. For example, the following declaration is perfectly valid.

enum weather {hot, warm = 0, cold, wet};

The names hot and warm can be interchangeably used, since both represent the value 0.-

Consider the variable days_of_week. is declared as the declaration of this enum. The
enumeration constants are Sun Mon Tues Wed Thu Fri Sat. These constants are separated by
commas.

enum days_of_week {Sun, Mon, Tues, Wed, Thu, Fri, Sat}

5) String Literals

A string literal is a sequence of characters enclosed within double quotes. The character
may consist of letters, numbers, escape sequences and space. To make it easier to write long
strings, string constants are concatenated at the compile time. For example, the strings:

“C is the best” and

“C is “ “the best” are the same.

An Important Difference: ‘A’ and “A”

The notations ‘A’ and “A” have an important difference: the first (‘A’) is a character constant,
while the second (“A”) is a string constant. The notation ‘A’ is a constant occupying a single
byte containing the ASCII code of the character A. The notation “A” on the other hand, is a
constant that occupies two bytes, one for the ASCII code of A and another for the null character
with the value 0, that terminates all strings.
44

6) const Qualifier

To understand the necessity of const identifiers, consider the following program which
calculates tax on the given salary, assuming that the rate of taxation is 30%.

/*tax.c: program to compute tax */

# include <stdio.h>

void main ( )

{float sal, tax;

printf ( “ salary: “ );

scanf ( “%f”, & sal );

tax = sal * 0.3;

printf ( “tax = %f\n”, tax );}

The program works correctly. It uses the numeric constant 0.3 to calculate the tax sinc
the rate of taxation is 30%. But assume that the program computes the tax at many different
points. If the tax rate changes, all the statements that computer the tax will have to be modified.
An obvious solution to this problem is to declare a variable called tax_rate that will have the
current tax rate. In case the tax rate changes, we only need to update the variable tax_rate.
The modified program is given below.

/*tax1.c: program to compute tax using a variable */

# include <stdio.h>

void main ( )

{float tax_rate = 0.3;

float sal, tax;

printf ( “ salary: “ )

scanf ( “%f”, & sal );

tax = sal * tax_rate;

printf ( “tax = %f\n”, tax );}


45

The statement,

tax = sal * tax_rate;

in the above program is more readable than

tax = sal * 0.3;

in the earlier one. This disadvantage is that any statement written carelessly can modify
its value. Then, all subsequent calculations of the tax will yield wrong results. In a very long
program, if such a problem is encountered, it could be very difficult to find where exactly is has
been modified. To avoid suffering the consequences of such carelessness, declare the variable
tax_rate as const. The statement that declared tax_rate would now be changed to:

const float tax_rate = 0.3;

This informs the compiler that tax_rate is a constant floating-point number, its value is
0.3 and it cannot be modified anywhere in the program. A statement, such as

tax_rate = 0.99;

Will cause a compile-time error, enabling you to detect the mistake early and save
debugging time. The complete program using a constant identifier tax_rate is given below.

/* const.c: program to illustrate the use of the keyword const. */

# include <stdio.h>

void main ( )

{const float tax_rate = 0.3;

float sal, tax;

printf ( “ salary: “ );

scanf ( “%f”, & sal );

tax = sal * tax_rate;

printf ( “tax = %f\n”, tax );}

Another way to achieve the effect of const identifiers is by the use of # define preprocessor
directive as shown below:
46

# include <stdio.h>

# define tax_rate 0.3

void main ( )

{float sal, tax;

printf ( “ salary: “ );

scanf ( “%f”, & sal );

tax = sal * tax_rate;

printf ( “tax = %f\n”, tax );}

Notice that in the statement,

# define tax_rate 0.3

There is no terminating semicolon (;) as in all preprocessor directives. The directive


instructs the pre-processor to substitute 0.3 for all the occurrences of the identifier tax_rate in
the succeeding part of the program.

This is the key difference between the use of constant identifiers and the #define directive.
The compiler treats the former as a value that cannot change in the program, while the latter is
handled by the preprocessor that replaces all instances of tax_rate by 0.3.

Note that conventionally, such constants are specified in the upper case. Normally the #
define directive would be:

# define TAX-RATE 0.3

RAX-RATE is then used in the rest of the program.

Programming Examples

Example

/* interest.c: calculation of simple interest and compound

interest */
47

# include <stdio.h>

# include <math.h> /* For the function pow */

void main ( )

{float p, t, r, ncmp_year;

float simple, compound, cmp_amount;

printf ( “principal: “ );

scanf ( “%f” , & p );

printf ( “Rate: “ );

scanf ( “%f” , & r );

printf ( “Time: “ );

scanf ( “%f”, & t );

printf ( “Compoundings per year: “ );

scanf ( “%f”, & ncmp_year );

simple = p * t * r/100;

/* Calculate the amount resulting from compound

interest. */

cmp_amount = p * pow ( 1+ r/ (ncmp_year*100)

ncmp_year * t);

/* Compute the compound interest from the amount and principal */ compound =
cmp_amount - p;

printf ( “The simple interest is: %f\n”. simple);

printf ( “The compound interest is: %f\n”, compound );}

Run:

principle: 1000

——

Rate: 10

Time: 2
48

Compoundings per year: 4

The simple interest is: 200.000000

The compound interest is: 218.402954

While compiling in UNIX, use cc - 1m <filename> instead of cc <filename>, since it uses


the function pow from the match.h header file in the program. The function pow above needs
some explanation. There is no operator in C which acts as the exponentiation (or to the power
of) operator. The function pow is used for this purpose. Two floating-point numbers are passed
to pow; it computes the first number raised to the power of the second, and returns the answer.
In the above example, the function pow is called thus:

pow (1+ r/ (ncmp_year*100), ncmp_year* t)

The first number passed to pow is 1+r/ (ncmp_year*100). The second number is
ncmp_year * t. The two are separated by a comma, as in the case of printf where the variables
to be output that are passed to printf are separated by commas. Observe that the interest
values are printed with 6 digits after the compiler. Whereas, it is sufficient if they are printed
with the precision operations are given in the next lesson.

Example

/*temper.c: Conversion of centigrade to fahrenheit and vice-versa */

# include <stdio.h>

void main ( )

{float c, f;

printf ( “Enter temperature in celsius:”);

scanf ( “%f”, &c );

f = 1.8 * c + 32;

printf ( “Equivalent fahrenheit = %f\n”, f);

printf ( “\nEnter temperature in fahrenheit:”);


49

scanf ( “%f”, &f );

c = (f - 32) / 1.8;

printf ( “Equivalant celsius = %f\n”, c );}


Run 1:
Enter temperature in celsius: 10

Equivalent fahrenheit = 50.000000


Run 2:
Enter temperature in fahrenheit: 50

Equivalent celcius = 10.000000


Example
/*triangle.c: Computation of area of a triangle give the three sides*/

#include <stdio.h>

#include <math.h> /* For the function sqrt */

void main ( )

{float a, b, c;

float peri, s, area;

printf ( “Enter the 3 sides: “ );

scanf ( “%f %f %f”, &a, &b, &c );

peri = a + b + c;

s = peri / 2;

area = sqrt (s* (s - a) * (s - b) * (s - c) );

printf ( “Area of the triangle is %f\n”, area );}


Run:
Enter the 3 sides: 4 5 6

---

Area of the triangle is 9.921567


50

In the above example, the library function sqrt is used to find the square root. This function
accepts of a floating point number and returns its square root.
Example
/* triangle 2.c: Area of the triangle given the base and height */

#include <stdio.h>

void main ( )

{float b, h;

float area;

printf ( “Enter the base: “ );

scanf ( “%f”, &b );

printf ( “Enter the height: “ );

scanf ( “%f”, &h );

area = b * h / 2;

printf ( “Area of the triangle is %f”, area );}


Run:
Enter the base: 3

Enter the height: 2

Area of the triangle is 3.000000

Check Your Progress - II


1) State whether the following are True or False.

a) A constant is a quantity which may vary during the program execution.

b) Floating point constants have decimal point or an exponential sign or both.

2) Fill in the blanks

a) constants is enclosed within single quotation.

b) is a sequence of characters enclosed within double quotes.


51

2.5 Summary

In this lesson we have covered variable and expression. We have also covered character
set, special characters, Identifiers and keyword.

2.6 Check Your Answers


I. 1) a) True b) False

2) a) -32, 768 to 32, 767 b) one character c) 4 bytes

II. 1) a) False b) True

2) a) character b) String literal

2.7 Model Questions


(1) Explain the four basic data types in C. What is the size in bytes of each type in DOS and
Unix platforms

(2) Explain the four basic types of constants in C

(3) What is meant by explicit type casting? When is it useful?

(4) What are the different types of qualifiers? Explain.


52

LESSON - 3
OPERATORS AND EXPRESSIONS

Structure
3.1 Introduction

3.2 Learning Objectives

3.3 Operators

3.4 Summary

3.5 Check Your Answers

3.6 Model Questions

3.1 Introduction

Operators are c’s forte. It is extremely rich in operators. It has as many as 45 different
operators. We are going to discuss most of there operator and their interaction with are another
in this lesson.

3.2 Learning Objectives


After leaning this lesson, you should be able to

– operators and expressions

3.3 Operators

An operator, in general, is a symbol that operates on a certain data type. For example,
the operator is the addition operation. It can operate on integer, character and real (float,
double and long double) numbers. An expression is a combination of variables, constants and
operators written according to the syntax of the language. In C, every expression evaluates to
a value, i.e., every expression results in some value of a certain type that can be assigned to a
variable.

Let us take the simple example of an assignment operator and analyses the concept of
evaluation. In C, the ‘=’ symbol is the assignment operator. Its duty is to set the value of the
variable on the left hand side to that of the right hand side. The left hand side of the assignment
operator (=) and the right hand side together form an expression.
53

For example, if the variables i and j have been declared by the statement,

int i, j;

then a valid expression involving the assignment operator would be as follows:

i = 5;

The above statement assigns the value 5 to i. In addition, the whole expression evaluates
to the value that has been assigned (i.e., 5). So, the statement,

j = i = 5;

Will first execute i = 5. This expression evaluates to 5. When we say that i=5 evaluates to
5, what we actually mean is that the i = 5 part (inside the expression j = i = 5) can be replaced
by the number 5. So you can imagine that at the run time, the value 5 is first assigned to i.
Then, the statement becomes

j=5

and 5 is assigned to j. Thus, the value of both i land j after the above statement is
executed, is 5.

1) Types of Operators

In C, operators can be classified into various categories based on their utility and action.
A list of operator types is given below:

 Arithmetic operators
 Relational operators
 Logical operators
 Assignment operators
 Increment and decrement operators
 Conditional operators

 Comma operator

2) Arithmetic Operators

The arithmetic operators perform arithmetic operations and can be classified into unary
and binary arithmetic operators. The arithmetic operators can operate on any built-in data
type/ A list of arithmetic operators and their meanings are given below:
54

Operator Meaning

+ addition or unary plus

– subtraction or unary minus

* multiplication

/ division

% modulo division (remainder after division)

Note: .C has no operator for exponentiation. However, a function y pow (x,y) exists in
math.h which returns X. The unary minus operator has the effect of multiplying its operand
by - 1

Integer arithmetic: When two operands such as x and y are declared integers, an
arithmetic performed on these integers is called integer arithmetic. It always yields an integer
value.

Example

Let x and y be declared by the statement: int x = 16, y = 5, (x and y are integers with
values 16 and 5, respectively)

Then the integer arithmetic operations yield the following results:

x + y = 21

x – y = 11

x * y = 80

x / y = 3 The result is truncated, the decimal part is discarded.

x % y = 1 The result is the remainder of the integer division and the sign of the result is
always the sign of the first operand.

Note: In integer division operation, the result is truncated towards zero if both the operands
are of the same sign, and is dependent on the machine if one of the operands is negative.
55

Example

6/8=0 -6 / -8 = 0 -6 / 8 = 0 or -1

The result is machine dependent

Floating point arithmetic: Floating point arithmetic involves operands of real type
in decimal or exponential notation. The floating point results are rounded off to the number of
significant digits specified and hence, the final value is only an approximation of the correct
result. The remainder operator % is not applicable to floating point arithmetic operands.

Example

Let a and b be declared by the statement float a = 14.0, b = 4.0; (a and b are float
variables with values 14.0 and 4.0 respectively) and p, q and r be floating point variables: then
the floating point arithmetic operations will yield the following results:

p = a / b = 3.500000 q = b / a = 0.285714

r = a + b = 18.00000

Mixed mode arithmetic: In mixed mode arithmetic, if either of the operands is real,
the resultant value is always a real value. For example, 35 / 5.0 = 7.0. Here, since 5.0 is a
double constant, 35 is converted to a double and the result is also a double.

3) Relational Operators

While arithmetic operators are used to evaluated arithmetic expressions, relational


operators are used to compare arithmetic, logical and character expressions. We often compare
two similar quantities and depending on their relation, take some decisions. These comparisons
can be done with the help of relational operators. Each of these operators compare their left hand
side with their right hand side. The whole expression involving the relational operator then evaluates
to an integer. It evaluates to zero if the condition is false, and 1 (one if it is true.

Operator Meaning

< less than

> greater than


56

<= less than or equal to

>= greater than or equal to

== equal to

!= not equal to

In order to study the relational operators in the right perspective, it is necessary to know
the fundamentals of an if statement. Consider a simple example that uses a relational operator
in an if statement. Details of the if statement are dealt with in the next lesson, but presently we
need to have a basic idea of its function. The if statement evaluates an expression and executes
the next statement only if the expression evaluates to true (a non-zero integer). The following
example inputs two integers and tests for equality.

/* relation.c: Example of using relational operator in an if statement */

# include <stdio.h>

void main ( )

{ int i, j;

print ( “Input two numbers: “ );

scanf ( “%d%d”, &i, &j );

if ( i = = j )

printf ( “They are equal. \n” );

printf ( “Got the message?\n” ); }

The if statement in the above example needs special mention. A pair of round braces
follow the if statement. If the condition within these braces (which is i = = j here ) is true, the
statement just after the if statement is executed, otherwise it is skipped. Let us now run the
program, enter two equal number and see what happens.

Input two numbers: 34 34

——

They are equal.


57

Got the message?

since i and j are both 34, the condition i = = j in the if statement

if ( i = = j )

evaluates to 1, and statement following the if statement, which is

printf ( “They are equal.\n” );

is executed. Thereafter, the execution continues normally, and the last statement of the
program

printf ( “Got the message?\n” );

is executed finally.

If the program is run with unequal numbers the output appears as follows:

Input two numbers: 34 45

——

Got the message?

Since i and j are not equal, the condition i = = j in the if statement evaluates to 0. The
statement that follows the if statement is skipped, and the message They are equal is not
displayed.

Note that in C, the operator for testing equality is = = (two = signs placed together). One
of the most common mistakes is to use single = sign to test for equality. For example, consider
the following sequence of statements:

int i = 3, j = 70;

if ( i = = j )

printf ( “They are equal.\n” )

printf ( “They are not equal. \n” )

As expected, the following message is printed:

They are not equal.

On the other hand, here is the wrong version that uses single = for comparison.
58

int i = e, j = 70;

if ( i = j )

printf ( “They are equal.\n” );

else

printf ( “They are not equal.\n” );

Since i = = j evaluates to false (0), the statement following the else keyword is executed.

The above sequence of statements cause the following (erroneous) output to be printed:

They are equal

This happens because the result of an assignment operator is the assigned value itself.
Here, since the condition used in the if statement is i = j, the value of j (70), is assigned to i, and
the assignment expression evaluates to 70, which is non-zero. Since any non-zero value is
considered to be true, the statement following if is executed, printing a message that the two
values are equal.

Examples of other relational operators are given below. Suppose i and j are declared
with

int i = 10, j = 20;

Here the expression,

i>j

is false (because i is not greater than j). Recall that every expression evaluates to a value
in C. The above expression evaluates to false. But in C, there is no special data type to represent
true of false. Integers are used for this purpose. The integer zero represents false and any
non-zero integer represents true. So, the expression i > j evaluates to zero. The expressions i <
j and i < = j evaluate to 1, since the relations are true.

For example, if the variable t is declared an integer, the statements,

t = (i < j );

printf ( “%d\n”, t );

will print 1. More examples are given below:


59

When using relational operators, the signed or unsigned nature of the numbers being
compared becomes important. Neglecting this fact can lead to hard-to find errors. For example,
here is a program that uses the varable type char as an 8-bit integer. Whether char is signed or
unsigned depends on the compiler used.

/* char.c: Using char as an 8-bit integer */

#include <stdio.h>

void main ( )

{ /* Integer value being assigned to a char */

char c = 255;

char d = -1;

if ( c < 0 )

printf ( “c is less than 0\n” );

else

printf ( “c is not less than 0\n” );

if ( d < 0 )

printf ( “d is less than 0\n” );

else

printf ( “d is less than 0\n” ); }

If the compiler used to compile the above program treats a char as signed, then the
output of the program will be:

c is less than 0

d is less than 0

The second lined is true, since the number assigned to d, which is -1 is indeed less than
0. The first line is false, since the number we have assigned to c is 255, and is definitely greater
than 0. But the catch is that both -1 and 255 have same binary representation in 2’s complement
arithmetic. Treating char as signed has the effect that both are treated as signed numbers (
i.e., as -1 in this case).
60

On the other hand, if the compiler treats a char as unsigned, the output will be:

c is not less than 0

d is not less than 0

The first line is now correct, but the second is not. Again, when a char is treated as
unsigned, both numbers ( c and d ) are assumed to be 255, and hence not less than 0. This is
certainly an obstacle to writing portable programs. The solution lies in explicitly declaring variables
of type char as signed or unsigned when using them as 8-bit integer values. Similarly, the
signed or unsigned nature of numbers is important even in case of normal integers. Making the
above program portable lies in changing the declaration of the characters.

/*char8.c: Using char as an 8-bit integer the right way */

#include <stdio.h>

void main ( )

{ /* Integer value being assigned to a char */

Unsigned char c = 255;

signed char d = -1;

if ( c < 0 )

printf ( “c is less than 0\n” )

else

printf ( “c is not less than 0\n” );

if ( d < 0 )

printf ( “d is not less than 0\n” );

else

printf ( “d is not less than 0\n” );}

Now, irrespective of the compiler, the output of the program is as follows:

c is not less than 0

d is less than 0
61

4) Logical Operators

A logical operator is used to compare or evaluate logical and relational expressions. There
are three logical operators in C language. They are:

Operator Meaning

&& Logical AND

 Logical OR

! Logical NOT

An expression involving && or || is sometimes called compound expression, since the


expression involves two other expressions, that is, each of these operators (&& and ) take
two expressions, one to the left and another to the right.

Logical AND: For example, consider the following expression:

a > b && x = = 10

The expression on the left is a a>b and that on the right is x = = 10. The whole expression
evaluates to true ( 1) only if both expressions are true ( if a is greater than b and the value of x
is equal to 10)

Logical OR: Consider the following example involving the ÈÈoperator:

a < m a < n

The expression is true one them is true, or if both of them are true. That is, if the value of
a is less than that of m or n. Needless to say, it evaluates to true in case a is less than both m
and n.

Logical NOT: The ! (NOT) operator takes single expression and evaluates to true (1) if
the expression if false (zero), and evaluates to false (0) if the expression is true. In other words,
it just reverses the value of the expression. For example, consider:

! (x > = y)
62

The expression after the ! operator, in this case is x >= y. The not expression evaluates
to true only if the value of x is neither greater than nor equal to y (i.e., only if x is less than y).
Therefore, the whole expression including the ! operator is the same as:

x<y

So what is the use of this operator? The ! operator is convenient to use when you want to
test whether the value of a variable is zero. For example,

if (!i )

printf ( “The value of i is zero. \n” );

The expression inside the braces of the if statement is: !i

This is true only if the value of i is zero.

5) Bitwise Operators

A bitwise operator operates on each bit of data. These operators are used for testing,
complementing or shifting bits to the right of left. Usually bitwise operators are not useful in
cases of float and double variables. A list of bitwise operators are given below.

Operator Meaning

& bitwise AND

bitwise OR
¦
^ bitwise XOR

<< shift left

>> shift right

~ bitwise complement

To experiment with these operators, assume that a, b and c are integers declared by the
statement.

int a = 13, b = 7, c;

Also, for convenience, let us assume that an integer occupies 16 bits (2 bytes).
63

The binary representation of a is 0000 0000 0000 1101.

The binary representation of b is 0000 0000 0000 0111.

(The space appearing after every 4 bits are only for clarity. Actually, the integers are
merely 16 continuous bits).

Bitwise AND: The statement,

c = a & b;

make use of the bitwise AND operator. After this statement is executed, each bit in c will
be 1 only if the corresponding bits in both a and b are 1. For example, the right most bit of both
integers is 1, and hence the right most bit in c is 1. The next bit is 0 in a and 1 in b. Hence the
second bit (from the right) in c is 0. Applying this reasoning to all the bits in each integer, the
value of c after the above statement is executed, will be 0000 0000 0000 0101 which, in decimal
is 5 and is illustrated below:

Bitwise AND operator: a & b

a 0000 0000 0000 1101

b 0000 0000 0000 0111

a & b 0000 0000 0000 0101

Bitwise OR: The statement

c = a b;
¦

make use of the bitwise OR operator. After this statement is executed, a bit in c will be 1
whenever at least one of the corresponding bits in a or b is 1. In the above example, the value
of c will be 0000 0000 0000 1111, i.e., decimal 15 and is illustrated below.

Bitwise OR operator: a ¦ b

a 0000 0000 0000 1101

b 0000 0000 0000 0111

a b 0000 0000 0000 1111


¦
64

Bitwise XOR: The statement

c = a ^ b;

make use of the bitwise XOR operator. After this statement is executed, a bit in c will be
I whenever the corresponding bits in a and b differ. So, in the above example, the value of c will
be 0000 0000 0000 1010 which, in decimal is 10 and is illustrated below.

Bitwise EX -OR operator: a ^ b

a 0000 0000 0000 1101

b 0000 0000 0000 0111

a ^ b 0000 0000 0000 1010

Left shift operator: The left bit-shift operator, << is a binary operator. For example
consider the statement

c = a << 3;

The value in the integer a is shifted to the left by three bit positions. The result is assigned
to the integer c. Since the value of a is 0000 0000 0000 1101 the value of c after the execution
of the above statement is 0000 0000 1010 1000 (140 in decimal) and is illustrated below:

Left-Shift <<

drop off <— 0000 0000 0000 1101 <— insert 0’s

after left-bit shift by 3 places i.e., a << 3

0000 0000 0110 1000

The three left-most bits drop off due to the left shift (i.e., they are not present in the
result). Three zeros are inserted in the right. The effect of shifting a variable to the left by one
bit position is to multiply it by 2. In the above example, a is shifted left by 3 positions, which is
equivalent to 3 multiplying a by 2*2*2*, i.e., 2. Since the initial value of a is 13, the value
assigned to c is 13*8=140.

While multiplying a number by a power of 2, considerable saving in execution time can


achieved by using the left bit-shift operator instead of the multiplication operator, since shifting
is faster than multiplication.
65

Right shift operator: The right bit-shift operator is also a binary operator. For example,
consider:

c = a >> 2;

The value of a is shifted to the right by 2 positions. Since the value of a is 0000 0000
0000 1101, the value of c after the execution of the above statement is 0000 0000 0000 0011
(3 in decimal) and is illustrated below:

Right-Shift >>

insert 0’s —> 0000 0000 0000 1101 —> drop off

after right shift by 2 places i.e., a >> 2

0000 0000 0000 0011

The 2 right-most bits drop off (are not present in the result), and zeros are inserted in the
left effect of shifting a variable to the right by one bit position is to perform integer division by 2
(i.e., divide by 2 and truncated the result). Hence, shifting to the right by 2 bit position has the
effect of integer division by 2*2*=4. Since the initial value of a is 13, shifting to the right by 2 bit
positions yields the value 3 ( the result of dividing 13 by 4 and truncating the result).

Shifting negative number: Note that zeros are not always inserted in the left, as shown in
the above example. If the number is negative to begin with then 1 is inserted in the left for every
bit shifted to the right. For example, if we assign a negative number, say -3 to a with the
statement:

a = -3;

Then the binary representation of a would be the two’s complement of the magnitude. To
find the 2’s complement of 3, take the binary representation of 3, complement it bitwise, and
add 1 to the result. The binary representation of 3 is: 0000 0000 0000 0011

Complementing bitwise (i.e, taking each bit and inverting it, making it 0 if it is 1 and vice-
versa), we get: 1111 1111 1111 1100
66

Add 1 to this sequence to get 2’s complement.

1111 1111 1111 1101

This is the binary representation of -3 Now, the statement,

c = a >> 2;

will shift the value of a by 2 bit positions to the right and insert two 1’s in the left. So, at
end of this operation, the value of c will be:

1111 1111 1111 1111

This is a number which is in 2’s complement form again. To see the magnitude of this
negative number, take 2’s complement again (2’s complement of a 2’s complement is the
original number itself), resulting in

0000 0000 0000 0001

indicating that the number is -1 in decimal.

In the case of unsigned integers, the bit inserted on the left is always 0. Note that the
value of the bit inserted on the left varies with the sign only in the case of a right shift. In case
of a left shift, the bit on the right is always 0.

6) Bitwise Complement Operator

The bitwise complement operator (~) is a unary operator. It gives the value got by
complementing each bit of the operand. To illustrate its usefulness, consider a situation where
it is required to clear the least significant a can use the & operator to bitwise AND the integer
with a constant having only the least significant four bits initialized to zero.

i = i & 0xfff0;

But this method assumes that the size of an integer is 16 bits. If an integer is of 32 bits,
the above method clears the most significant sixteen bits also. Another way is to use the right
and left shift operators and the fact that a left shift always shifts in zeros to the right. The
statement below shifts the integer 4 bits to the right, and shifts it back 4 bits to the left.

i = (i>>4) << 4;
67

This method though portable, involves two shifts. It can be done more efficiently using
the ~ operator, as follows:

i = i & ~ 0xf;

The integer constant 0xf has only its significant four bits set. When the bitwise complement
(~) operator is applied to it, an integer that has all bits set except the least four significant bits,
is obtained. Applying the bitwise AND now gives the desired result. Expressions such as above,
where the variable being assigned to and the variable being operated on, are the same, permit
an easier method. For example, the assignment expression i = i & ~ 0xf above can be written
as:

i & = ~0xf;

The operator &= performs the bitwise AND operation on the operand on its left.

To illustrate the bitwise operators, a complete sample program is given below. This program
reads an integer and prints the value of a specified bit in the integer. The bits are numbered
from 0, starting from the right. For example, to find the value of the second bit of an integer i,
it is necessary to shift i to the right by two bits, and take the least significant digit.

/* extract.c: Finishing the nth bit */

#include <stdio.h>

void main ( )

{ /* i is the input integer and n, the bit position to extract. */ int i, n;

/* bit is the value of the bit extracted (0 or 1) */

int bit;

printf ( “Input an integer: “ );

scanf ( “%d”, &i );

printf ( “Bit position to extract: “ );


68

scanf ( “%d”, &n );

bit = (i >> n) & 1;

printf ( “The bit is %d” bit );}

The statement,

bit = (i >> n) & 1;

first shifts i to the right by n bits and then masks (clears) all bits of i except the least
significant bit, giving us the value of the bit which we wanted. Parentheses are not required in
the above statement, since the operator >> has a greater precedence than & (i.e., in an
expression, if both >> and & are present, the >> operator is executed first). Since this fact is
not so obvious, it is always better to use parentheses in such situation, for the sake of readability.

Arithmetic assignment operators: We have already used the assignment operator


= (equal sign). As we know, this operator evaluates the expression on the right, and assigns
the resulting value to the variable on the left. Other forms of assignment operators exist, that
are obtained by combining various operators such as +, -, *, etc., with the = sign. For example,
there is a += operator that evaluates the expression to its right, and adds the resulting value to
the variable on its left.

The statement a += 5; will add the number 5 to the value of a. Similarly, a+=b-c will
evaluate b-c first, and adds the result to the value of a. The other assignment operators are:

-= /= *=
¦= &= ^=

These have obvious meanings. They evaluate the expression on their right, and use the
result to perform the corresponding operation on the variable on the left. Apart from the above
assignment operators, bit-shift assignment operators also exist. They are:

>>= <<=

For example, the statement,

a <<= 5;

will shift the bits of a to the left by 5 bit positions.


69

7) Increment and Decrement Operators

The increment and decrement operators are very useful in C language. They are
extensively used in for and while loops. The syntax of the operators is given below:

++<variable name> __ __ <variable name>

<variable name ++ <variable name > __ __

The operator ++ adds 1 to the operand and — subtracts 1 from the operand. These
operators manifest in two forms: prefix and postfix. For example, the ++ operator can be used
in two ways:

++m and m++

These are two different expressions. The first expression immediately increments the
value of m by 1. For example, the statements,

int t, m = 1;

t = ++m;

printf ( “prefix operator: t = %d, m = %d\n”, t, m );

will print,

prefix operator: t = 2, m = 2

The expression ++m will cause the value of m to be incremented first, and then this value
is assigned to t, resulting in both having the same value. On the other hand, the statement,

int t, m = 1;

t = m++;

printf ( “Postfix operator: t = %d, m= %d\n”, t, m );

will output

postfix operator: t =1, m =2


70

The expression m++ will first evaluate the value of m (which is 1), resulting in 1 being
assigned to t and then the value of m being incremented to 2.

8) Conditional Operator (ternary operator)

The conditional operator consists of two symbols: the mark (?) and the colon (:). This is
the only operator in C that three operands. The syntax of the operator is given below:

expression 1 ? expression 2: expression 3;

Let us examine the ternary operator through an example. This program reads two integers
and displays the value of the larger of the two. If they are equal, then naturally either of them
will be printed.

/*max.c: Example to find the maximum using the conditional operator */

#include <stdio.h>

void main ( )

{ int i, j, larger;

printf ( “Input two integers: “ );

scanf ( “%d%d”, &i, &j );

larger = i>j ? i: j;

printf ( “The larger of the two is %d\n”, larger );}

The statement that uses the conditional operator is:

larger = i>j ? i : j;

It has three components; the expression i>j before the question mark, and the variable i
and j after it, one on each side of the ‘:’. We shall first see a sample run of the above program,
and then analyses what the conditional operator does.

Input two integers: 34 45

——

The larger of the two is 45


71

Let us now see what the conditional statement does.

 First, the expression before? (which is i > j) is evaluated. In the above case, the expression
is false.

 Since the expression before? is false, the whole expression involving the conditional
operates to the expression following the colon (:). In this case, this is just the variable j.

Here is one more test run.

Input two integers: 5 -1

The larger of the two is 5

In this case, the conditional statement operates as follows:

 as before, the expression before? (which is i>j) is evaluated. The expression is true,
since i is 5 and j is -1.

 since the expression before? Is true, the whole expression involving the conditional
operators evaluates to the expression before the colon (:) In this case, this is the variable
i

9) Comma Operator

A set of expressions separated by commas is a valid construct in the C language. For


example, i and j are declared by the statement: int i, j;

Consider the following statement that makes use of the comma operator:

i = (j = 3, j + 2);

The right hand side consists of two expressions separated by comma. The first expression
is j=3 and the second is j+2. These expression are evaluated from left to fight. That is, first the
value 3 is assigned to j and then the expression j+2 is evaluated, giving 5. The value of the
entire comma-separated expression is the value of the right-most expression. In the above
example, the value assigned to i would be 5.
72

10) Other Operators

The operator size of gives the size of the data type or the variable in terms of bytes
occupied in the memory, as illustrated earlier. Another operator is the member selection operator
(. and ->) which is used with structures and unions. Pointer operators, *and & are explained in
detail in later chapters.

11) Operator Precedence and Associativity

Consider the following two statements:

int a + 10, b = 15, c = 3, d;

d = a + b * c;

In the above expression, b is multiplied by c first. The result is added to a and the sum is
assigned to d. Since multiplication is done before addition, the multiplication operator has a
higher precedence than the additional operator. In order to override the precedence, braces
can be used. For example, the statement,

d = (a + b) * c;

would add a to b first, multiply the result by c and assign the product to d. Associativity of
an operator can be left-to-right or right-to-left. For example, in the expression.

d = a - b -c;

The first (left-most) minus is evaluated first. The variable b is subtracted from a. Then the
second minus is evaluated, causing c to be subtracted from the result. Thus, in the case of
many minus operators appearing in an expression without braces, the operators are evaluated
starting from the left-most operator and proceed rightward. The minus operator thus associates
from left to right. On the other hand, the equality operator associates from right to left. For
example, in the statement,

d = a = c;

the second (right-most) equality operator is evaluated first. The variable c is assigned to
a. The expression a = c evaluates to the value of a after the assignment has taken place. Then
this value is assigned to d, when the left-most equality operator is executed.
73

All the operators have been listed here for the purpose of completeness. Many of the
operators pertain to scop and pointers, and hence you may not be familiar with them. These
will be explained in a later lessons. The operators are divided into 16 categories. The first
category has the highest precedence; second category (unary operators) takes second
precedence, and so on down to the comma operator, which has the lowest precedence. The
operators within each category have equal precedence. The unary, and assignment operators
associate right-to-left: all other operators associate left-to-right.

Order of evaluation of operands: The C language specifies the associativity of operators,


but does not specify the order in which the operands of a operator are evaluated. For example,
in a statement like

sum = (++a) - (_ _ a);

the two operands are ++a and __ a. It is left to the compiler as to which expression it
evaluates first. If it evaluates ++a first, sum will be equal to -1, otherwise it will be 1.

Check Your Progress - I


1) State whether the following are True or False.

a) Operator is a symbol which represents a particular operation that can be performed


same data.

b) Each relational operator needs are operand for comparison of the values.

c) ++ is the increment operator.

d) >= is the logical operator.

e) * is the multiplication operator.

2) Fill in the blanks

a) General form of conditional operator is .

b) is Modulo Division operator..

c) is the right shift operator..

d) operator needs two operands for comparison of their values.

You might also like