Thats How We C

Vineeth Kartha
Vineeth KarthaStudent à BITS Pilani, Goa campus

A text Book on C programming, availalble for free. Please feel free to share copy or redistribute this work.

thats
o
we
cVineethKartha
Thats How We C
Vineeth Kartha
Thats How We C
This work is licensed under the Creative Commons Attribution-NonCommercial-
ShareAlike 3.0 Unported License. To view a copy of this license,
visit http://creativecommons.org/licenses/by-nc-sa/3.0/
or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain
View, California, 94041, USA.
The design and artwork on the cover page of this book was done by Mr. Vishnu
Sivadas, and the artwork from openclipart.org was used. www.openclipart.org.
This book has been typeset in LATEX
You are free to share, copy or distribute this book
Thats How We C
Dedicated to my Parents
&
My dear friends of GECB
EEE(2008-2012)
A Tribute to
Dennis M. Ritchie
(1941-2011)
Thats How We C
Contents
Preface xiii
1 Introduction 1
2 Basic Concepts 4
2.1 Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Compilers and Compiled Language . . . . . . . . . . . . . . . . . 5
2.3 Structure of a Compiler . . . . . . . . . . . . . . . . . . . . . . . 5
2.4 Interpreters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.5 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3 Identifiers and Data Types 9
3.1 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.1.1 Keywords in C . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 The Basic Data Types . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3.1 Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3.2 Floating Point . . . . . . . . . . . . . . . . . . . . . . . . 11
3.3.3 Character . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.4 The Data Type Specifiers . . . . . . . . . . . . . . . . . . . . . . 12
3.4.1 signed or unsigned . . . . . . . . . . . . . . . . . . . . . 12
3.4.2 long or short . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4.3 const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4.4 volatile . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.5 The Storage Class . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.5.1 Automatic variables (auto) . . . . . . . . . . . . . . . . . 12
3.5.2 Static variables (static) . . . . . . . . . . . . . . . . . . 13
3.5.3 External variables (extern) . . . . . . . . . . . . . . . . . 13
3.5.4 Register variables (register) . . . . . . . . . . . . . . . . 13
3.6 User Defined Data Types . . . . . . . . . . . . . . . . . . . . . . 13
3.6.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.6.2 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.6.3 Union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.6.4 Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.6.5 Typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.6.6 Typecasting . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.7 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4 Input/Output Operations 16
4.1 The gets() and puts() . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
vii
viii Contents
5 Operators 19
5.1 Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.1.1 Arithmetic Operators . . . . . . . . . . . . . . . . . . . . 19
5.1.2 Relational Operators . . . . . . . . . . . . . . . . . . . . . 20
5.1.3 Logical Operators . . . . . . . . . . . . . . . . . . . . . . 20
5.1.4 Assignment Operators . . . . . . . . . . . . . . . . . . . . 20
5.1.5 Bitwise Operators . . . . . . . . . . . . . . . . . . . . . . 20
5.2 Unary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.2.1 Unary plus and minus . . . . . . . . . . . . . . . . . . . . 22
5.2.2 Increment and Decrement Operators . . . . . . . . . . . . 22
5.3 Ternary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.3.1 Conditional Operator . . . . . . . . . . . . . . . . . . . . 23
5.3.2 Precedence and Associativity . . . . . . . . . . . . . . . . 23
5.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6 Control Statements 25
6.1 if...else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6.1.1 Nested if else . . . . . . . . . . . . . . . . . . . . . . . . 26
6.2 switch case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.3 Conditional Operator . . . . . . . . . . . . . . . . . . . . . . . . 27
6.4 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.4.1 Entry Controlled Loops . . . . . . . . . . . . . . . . . . . 28
6.4.2 Exit Controlled Loops . . . . . . . . . . . . . . . . . . . . 29
6.4.3 The break Statement . . . . . . . . . . . . . . . . . . . . 29
6.4.4 The continue Statement . . . . . . . . . . . . . . . . . . 30
6.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7 Structured Data Types 31
7.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.2 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
7.2.1 Nested Structures . . . . . . . . . . . . . . . . . . . . . . 33
7.2.2 Unnamed Structures . . . . . . . . . . . . . . . . . . . . . 34
7.3 Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
7.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8 Functions 36
8.1 Passing Values to Arguments . . . . . . . . . . . . . . . . . . . . 37
8.1.1 Pass by Value . . . . . . . . . . . . . . . . . . . . . . . . . 38
8.1.2 Pass by Reference . . . . . . . . . . . . . . . . . . . . . . 38
8.2 The return Statement . . . . . . . . . . . . . . . . . . . . . . . . 38
8.3 Functions with Variable Argument List . . . . . . . . . . . . . . 38
8.4 Scope of a Function . . . . . . . . . . . . . . . . . . . . . . . . . 40
8.5 Arrays as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . 40
8.6 Recursive Functions . . . . . . . . . . . . . . . . . . . . . . . . . 41
8.7 Command Line Arguments . . . . . . . . . . . . . . . . . . . . . 43
8.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
9 Pointers 45
9.1 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . 46
9.2 Call By Reference . . . . . . . . . . . . . . . . . . . . . . . . . . 46
9.3 Pointer to Function . . . . . . . . . . . . . . . . . . . . . . . . . . 47
9.4 Pointers and Arrays . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.5 Structure Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . 49
9.6 Dynamic Memory Allocation . . . . . . . . . . . . . . . . . . . . 50
9.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Contents ix
10 Advanced Data Structures 53
10.1 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
10.2 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
10.2.1 Implementation of Queues . . . . . . . . . . . . . . . . . . 58
11 File Handling in C 62
11.1 File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
11.1.1 Reading from a file . . . . . . . . . . . . . . . . . . . . . . 63
11.1.2 Writing to Files . . . . . . . . . . . . . . . . . . . . . . . . 64
11.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
12 Sorting Algorithms 66
12.1 Bubble Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
12.2 Selection Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
12.3 Insertion Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
13 The Preprocessor 68
13.1 #define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
13.2 Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
13.3 #undef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
13.4 #include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
13.5 #if—Conditional Inclusion . . . . . . . . . . . . . . . . . . . . . 70
14 Numerical Techniques: A Brief Introduction 71
14.1 Solution of Linear Equations . . . . . . . . . . . . . . . . . . . . 71
14.1.1 Gauss Elimination . . . . . . . . . . . . . . . . . . . . . . 71
14.1.2 Gauss Jordan . . . . . . . . . . . . . . . . . . . . . . . . . 73
14.2 Solving Transcendental Equations . . . . . . . . . . . . . . . . . . 75
14.2.1 Bisection Method . . . . . . . . . . . . . . . . . . . . . . . 75
14.2.2 Newton Raphson Method . . . . . . . . . . . . . . . . . . 77
14.3 Numerical Integration . . . . . . . . . . . . . . . . . . . . . . . . 79
14.3.1 Trapezoidal Method . . . . . . . . . . . . . . . . . . . . . 79
14.3.2 Simpson’s 1/3𝑟𝑑
Rule . . . . . . . . . . . . . . . . . . . . 80
14.4 Numerical Solution of Ordinary and Partial Differential Equations 82
14.4.1 Euler’s Method . . . . . . . . . . . . . . . . . . . . . . . . 82
14.4.2 Runge-Kutta Method . . . . . . . . . . . . . . . . . . . . 83
14.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
A ISO C Headers and Some Functions 86
B GCC 89
Bibliography 90
List of Tables
3.1 List of keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2 int data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.3 float data type . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.1 Conversion Characters . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 Escape Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.1 Bitwise AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.2 Bitwise OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.3 Bitwise XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.4 Bitwise NOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.5 Precedence and Associativity . . . . . . . . . . . . . . . . . . . . 24
List of Figures
2.1 Life Cycle of a Program . . . . . . . . . . . . . . . . . . . . . . . 7
3.1 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
8.1 Tower of Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
10.1 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
10.2 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
x
List of Programs
4.1 Standard I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2 gets() and puts() . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.1 Increment and decrement operators . . . . . . . . . . . . . . . . . 22
5.2 Find the output . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1 Largest of two numbers . . . . . . . . . . . . . . . . . . . . . . . 25
6.2 switch case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.3 for loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
6.4 while loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
7.1 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
8.1 Area of Square . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
8.2 Variable argument list . . . . . . . . . . . . . . . . . . . . . . . . 39
8.3 Arrays as arguments . . . . . . . . . . . . . . . . . . . . . . . . . 41
8.4 Factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
8.5 Command line arguments . . . . . . . . . . . . . . . . . . . . . . 44
9.1 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . 46
9.2 Call by reference . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
9.3 Pointer to function . . . . . . . . . . . . . . . . . . . . . . . . . . 47
9.4 Detect end of string . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.5 Structure Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . 49
9.6 Dynamic Memory Allocation . . . . . . . . . . . . . . . . . . . . 51
10.1 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
10.2 Pointer Implementation of Stack . . . . . . . . . . . . . . . . . . 55
10.3 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
11.1 Reading from a file . . . . . . . . . . . . . . . . . . . . . . . . . . 63
11.2 Writing to a file . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
14.1 Gauss Elimination . . . . . . . . . . . . . . . . . . . . . . . . . . 72
14.2 Gauss Jordan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
14.3 Determinant of a Matrix . . . . . . . . . . . . . . . . . . . . . . . 74
14.4 Bisection Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
14.5 Newton Raphson Method . . . . . . . . . . . . . . . . . . . . . . 78
14.6 Trapezoidal Method . . . . . . . . . . . . . . . . . . . . . . . . . 80
14.7 Simpson’s 1/3𝑟𝑑
Rule . . . . . . . . . . . . . . . . . . . . . . . . . 81
14.8 Euler’s Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
14.9 Runge-Kutta Method . . . . . . . . . . . . . . . . . . . . . . . . 84
xi
Thats How We C
Preface
Programming can be a nightmare for many, the reason is that they don’t have
an understanding of what they are handling. Programming can be made in-
teresting and fun. It is actually even more interesting and easy than all other
sciences because all we need to do an experiment with a programming language
is the computer and software. Thanks to the free software movement, almost
all program compilers and IDEs are available as free software. I do not claim
this book to be a masterpiece compared to many other books that are avail-
able today, but I do know that it will help someone someday. I hope this book
will be of help to at least some of the readers. I’m open to all criticisms and
appreciations.
I wrote this book using free software tools—Open Office Writer, Open Office
Draw, Gimp and LATEX. All the example programs have been tested using gcc-
4.4.5. This book is being released under the Creative Commons License.
I would like to express my gratitude to Mr. Vishnu Sivadas for his sincere
effort in designing the cover page, proof reading the book and typesetting it.
Finally I request the readers to pardon me for any errors that might have
crawled in irrespective of all efforts to avoid them. You can contact me at
vineeth.kartha@gmail.com.
Vineeth Kartha
xiii
Thats How We C
Chapter 1
Introduction
“Let us change our traditional attitude to the construction of programs: Instead
of imagining that our main task is to instruct a computer what to do, let us
concentrate rather on explaining to human beings what we want a computer to
do.”
Donald E. Knuth
Almost everyone has his own notion about programming. For most of the
beginners programming is a herculean task which is accomplished only by geeks
and they look at and approach the programming languages with such an idea
and as a result they fail to enjoy it.
Before we start we should have a clear answer to two basic questions.
1. What is programming?
2. What is software?
Let’s answer the first question. We spent a lot of money and time in buying
our computers. We take care in choosing the processor, the accessories, the
memory capacity and all other such aspects, but despite all this our computers
are the stupidest things in the world. We have to tell it very precisely what,
when and how to do things, our computers cannot think. The only advantage is
that it acts fast and it is a very obedient slave. So it will do exactly (it will even
destroy itself if your command says so). So the process of telling our computers
what to do is called programming.
Programming is also explained as the breaking of a task into small steps.
Programming is actually a step by step approach in solving a larger problem.
Suppose we are given the task to sort out students in a class according to their
marks, we look for the top mark first and we proceed so on till we have sorted
out each student, this is programming, our brain has been programmed through
our experiences and we act accordingly.
Unfortunately our computers aren’t smart enough. So we have to tell it.
The second question, what is software?
Most often the answer will be, a program executed on the computer!
A program is merely a set of instructions that a computer executes. Software
is much more than that.
Software is the collection of
1. Instructions that we call as programs
1
2 1. Introduction
2. Data structures that we used to handle data in the program
3. Documentation that includes all hard copy and soft copies that describes
the use and operation of the program
Today all software can be classified in 7 domains:
1. System Software: A collections of programs written to service other
programs, some process deterministic data (text editors, compilers etc.),
others process indeterministic data (OS, drivers etc.). It is characterized
by heavy interaction with hardware. It requires principles of scheduling,
resource sharing, memory management, complex data structures etc.
2. Application Software: Stand alone programs that solve a specific busi-
ness need. Applications in this area process business or technical data in a
way that facilitates business operation or management/technical decision
making used to control business in real time.
3. Engineering/Scientific Software: These are tools that help engineers
to analyse and interpret data obtained from experiments.
4. Embedded Software: This is a software that resides within a product
or system and is used to implement and control feature and function for
end user.
5. Product-line Software: Designed to provide specific capability for use
by many different customers.
6. Web Applications: These are network centric software, category spans
a wide array of applications found on the internet today.
7. Artificial Intelligence: Makes non-numerical algorithms to solve com-
plex problems that are not amenable to computation or straight forward
analysis. Applications within this area include robotics, expert system,
pattern recognition, artificial neural networks, game playing etc.
Now, as we are clear about what programming and software is, let’s see how
we can become a good programmer.
To be a good programmer you should be able to think in a simple and unnatural
way. The characteristics of a good programmer are:
a. Logical thinking
b. Patience
c. Perceptive
d. Faces a challenge with joy
Programming is something to have fun, tackle a problem head on and get
involved in it until solved. That will make you the best programmer. Also try to
learn a few languages through and out, it’s always better to know one language
completely than to know several languages and yet not being able to use all it’s
features.
By now the reader should have some idea about whether programming is
his/her cup of tea. If it is, let’s move on and learn one of the most beautiful
and mostly used programming language, C.
3
In the early days of computer development, there were two levels of program-
ming, the machine level and the assembly level. Programming and debugging
using these two methods was tedious and time consuming. The programmer
had to manage the hardware components himself. He had to consider every
aspect of the hardware before he can write a program.
Later on when computers became more common, another class of languages
called high level languages developed. Fortran, Cobol, Basic, C were all such
high level languages. These languages could be written in the human under-
standable form. These languages made the underlying hardware invisible to the
programmers and made the syntax easier.
It was in the 1970s along with the development of UNIX that the concept
of system programming languages, having attributes of both “low level” and
“high level” languages also developed. System programming languages have the
advantages of high level languages and also help in taking control of underlying
hardware itself.
C was developed as a system programming language by Brian W. Kerning-
han and Dennis M. Ritchie at Bell Labs. Two earlier versions were named A
and B.
Though C was developed for implementing system software, later on it was
used for application software and soon C became a general purpose language. C
can be used in many places where assembly language played major role. Today
even microcontroller programming is done in C.
The first version which is known as K & R C (named after it’s inventors)
remained a standard till 1983 when “The American National Standards Insti-
tute” formed a committee to establish a standard specification of C. In 1989,
the standard was ratified as ANSI X3. 159-1989 “Programming Language C”.
This version of the language is often known as ANSI C, Standard C or some-
times C89. In 1990 ANSI C was adopted by ISO as ISO/IEC 9899:1990 which
is called C90. In the late 1990s again revision was made incorporating inline
functions, data types like long long int and complex to represent complex
numbers, variable length arrays and also support for one line comment.
C has directly and indirectly influenced many of the major languages avail-
able today. So learning C can make you master of almost all programming
languages. The concepts are almost the same.
References
1. “The C Programming Language”, K & R.
2. “Development of C Language”, Dennis M. Ritchie.
3. “Software Engineering: A Practitioner’s Approach”, Roger S. Pressman.
Chapter 2
Basic Concepts
Let us look into detail a few points mentioned in the previous chapter. We
learned that a program can be written in machine language which is nothing
but just 1s and 0s, assembly language where we use shorter words but still
lengthy steps to do even the simplest task.
For both these two methods the programmer should thoroughly know the
architecture1
of the microprocessor they are programming on. These programs
will be platform dependent, i.e., a program written for the Intel Pentium IV
processor will not work on a Core 2 Duo or the latest i7 processors.
Then we have the high level programming which is much easier to learn and
practice and it helps in making faster, platform dependent programs. Let us
look at a simple statement to add 2 numbers.
In most high level languages we will write
c = a+b;
where result of a+b is stored in c.
This is quite well understood even by a person who doesn’t know programming.
Now let’s look at the assembly code for an Intel 8085 processor.
MVI A, value
ADD B
The statements are almost understood (ADD B tells us that we are adding
value in B). But we don’t really understand what is being added. Here one of
the number should be in the accumulator and the value in register B should
be added to it. This might seem confusing to those who are new to assembly
programming and this itself is the disadvantage of assembly programming.
The machine code will contain a series of 1s and 0s which is not possible to
by-heart and so we see how high level languages made programming easy.
But there is a catch in that, machines understand only machine code, and,
this is the lowest level at which a program can be written as it is directly
understood by the machine. But we have just seen the practical difficulties
associated with it.
1It is the conceptual design and fundamental operational structure of a computer system,
it’s a functional description of requirements and design implementation for various parts of a
computer.
4
2.1 Assembler 5
Both assembly language and high level language programs need to be con-
verted to machine code before they can be executed.
2.1 Assembler
A utility program called assembler translates the assembly language codes to
machine code. It creates an object code as it’s output which can be executed
by the machine. The object code generated will be specific to each micropro-
cessor, or microcontroller. There are various assemblers like TASM, NASM etc.
Though studying assembly language is difficult, learning it gets you more closer
to your hardware. And also C is a system level programming language and so
C has several features to include assembly programs of which we will see later
on.
When we deal with translation of high level languages to machine code, we
come across two terms, compiled and interpreted languages.
2.2 Compilers and Compiled Language
Compilers itself are programs that transform a program in high level language
to an executable program. C is defined to be a compiled language that means
the source code is given to a compiler which converts it to the executable form.
Early compilers were written in assembly language. Some compilers gener-
ate an object code (executable file) that can run on various platforms. Such a
compiler is called cross-compiler. Later on compilers were written in the respec-
tive languages itself. It was called self hosting compiling and was first created
for LISP at MIT in 1962. But then arouse the ‘chicken & egg problem’. How
can we have a chicken without an egg and how can we have an egg without a
chicken?
Suppose we have written a compiler for language X in X itself then how will
we compile it first? Most often an interpreter or compiler written in Y is used
first. This method is called bootstrapping.
The advantages of bootstrapping are
1. It’s a non-trivial test of language being compiled.
2. Compiler developers need to know only that particular language.
2.3 Structure of a Compiler
A compiler consists of
→ Front End: Where it checks the language semantics, displays errors and
generates the IR (Intermediate Representation).
→ Middle End: Here code is optimized, useless code is removed and con-
stants are identified and propagated.
→ Back End: Here finally the IR is converted to assembly code.
6 2. Basic Concepts
2.4 Interpreters
These are also programs used to convert source code to object code.
It may be a program
1. that executes instructions directly
2. translates source code into some efficient intermediate representation and
immediately executes this
3. expilcitly executes stored precompiled code made by a compiler
The most commonly used compilers for C are CC (C Compiler) and GCC
(GNU Compiler Collection).
These two are used in Unix and Linux operating systems.
∗ mingw32 is an extension to GCC that does cross compilation.
∗ TURBO C is a compiler for Windows.
TURBO C is not only a compiler but an Integrated Development Envi-
ronment.
Now let’s move on to the language itself. We will first have a look at the
basic program.
#include <stdio.h>
int main ()
{
printf("Hello World"); // Prints Hello World
return 0;
}
The first line of the program, the #include is called the preprocessor and
stdio.h is called header file. Header files are files that contain some predefined
functions, in our program the printf() is used to print a text Hello World
on the screen and this function is defined in the header file stdio.h. A header
file is different from a library file and most often people confuse them. Header
files merely contain declaration of functions but the library functions contain
the actual implementation of the functions. Library files are binary files.
∗ Another feature of the C program is the function main(). Anything that
has to be executed should lie in the main().
∗ Each and every instruction in the program is called statements and state-
ments should terminate with a semicolon (;).
∗ You might have noticed a sentence starting with //. This is called com-
ments. Comments are used for easy understanding of the code and for
writing explanations on the code. A commented part will not be executed
by the compiler, so this feature can be used to deactivate a certain part
of the code than deleting it.
Comments are of two types,
a. Single line: It starts with //(two forward slashes), and it should lie
in one line.
b. Multi-line: It starts with /* followed by multiple lines of comments
and it should be terminated by */.
2.4 Interpreters 7
∗ The statements in main() are one block of statements as such.
It should be contained within opening and closing braces {}.
∗ And finally we have the return 0; statement. This statement tells the
compiler that on end of the program the number zero should be returned
to the operating system by the main().
These return statements are quite useful in proper termination of programs
especially when a program crashes. This statement will be explained in
detail in the chapter on functions.
Now we have seen some common features of a C program. We have just
scratched the surface of a vast topic. We will see in detail all these concepts in
the coming chapters.
The life cycle of a program is shown in Figure 2.1.
Figure 2.1: Life Cycle of a Program
Now we will see how to convert our Hello World program to an executable.
Open notepad and save the above program as hello.c. Then open the
‘Terminal’ in ‘Applications’ and type
cc hello.c
Make sure you were in the same folder as the hello.c file.
Now type
./a.out
You should see Hello World on your screen or else check the error messages
and check your program. a.out is the output file generated.
In a TURBO C compiler, on the menu bar there will be compile command
and a run command. Another point for TURBO C users is that the output
screen will not be visible because the program executed and terminated. So to
hold the output for some time, before the return 0; insert a getch();, now
the screen will wait till a key on keyboard is pressed.
Again for cc and gcc we can name the output file by any name we want.
For that compile as follows
gcc -o name file.c
Now to execute you type
./name
The switch -o means output. There are several more switches, see appendix for
more details on GCC.
8 2. Basic Concepts
Now the reader must have had an idea about the basic requirements and
procedures in making a program.
2.5 Exercise
1. Write a short note on the life cycle of a program.
2. Write a brief note on C programming.
3. Write short notes on compiled and interpreted languages with example.
4. Write advantages of interpreted languages.
5. What is bootstrapping?
References
1. “Microprocessor and its Applications”, B. Ram.
2. “Microprocessor and its Applications”, Gaonkar.
3. K & R C.
4. “C Programming in Unix”, John Vally.
Chapter 3
Identifiers and Data Types
3.1 Identifiers
Throughout our program we will have to use variables to store different types
of data. Variables are like containers that contain a value assigned to it, we can
use this variable name instead of that particular value throughout the program
depending on it’s visibility1
.
There are certain rules to be remembered while naming variables:
∙ The name should start with an alphabet.
∙ The name should not be any reserved keywords like int, float, volatile
etc.
∙ The names are case sensitive. AVG and avg are different variables.
∙ The name should not contain special characters like $, #, ! but it can
contain (underscores).
∙ The name can contain alphabets from a–z, A–Z and 0–9.
∙ The name should not start with a number.
∙ The name should not contain spaces.
∙ The name can start with an underscore but usually such variables are used
by the system. So it is better to avoid such a situation.
When naming a variable it is always advisable to
∙ Name the variable depending on what it represents.
∙ Keep them as short as you can but they should be understandable about
what they represent.
3.1.1 Keywords in C
Table 3.1 shows the list of keywords in C.
1A variable can be made available throughout the program or only in a particular part of
the code. We will discuss in detail about this in the coming chapters.
9
10 3. Identifiers and Data Types
auto break case char const continue default do
double else enum extern float for goto if
int long register return short signed sizeof static
struct switch typedef union unsigned void volatile while
Table 3.1: List of keywords
3.2 Data Types
Data types in C can be classified as shown in Figure 3.1 below.
Figure 3.1: Data types
3.3 The Basic Data Types
3.3.1 Integer
An integer is a numeric item that can contain a positive or negative whole
number.
int varname;
We can also declare many variables in a single line and even initialize their
values.
int var1 , var2 , var3 =5;
When an integer data type is declared the compiler allocates 2 or 4 bytes of
space, depending on the operating system. The Unix and Linux environments
3.3 The Basic Data Types 11
provide a 4 byte memory whereas it is 2 bytes long in the MS-DOS environment.
Type modifiers can be used to get a desired size irrespective of the OS. Usually
an integer can contain a value between −32, 768 to 32,767. We can use the type
modifier unsigned to limit the range to only the positive side. The following
table shows the size and limit of the int data type with different type modifiers.
Declared Length in bytes Value Range
int 2 or 4 At least −32, 768 to 32,767
long int 4 −2, 147, 483, 647 to 2,147,483,648
short int 2 −32, 768 to 32,767
unsigned int 2 or 4 At least 0 to 65,535
unsigned short 2 0 to 65,535
unsigned long 4 0 to 4,294,967,295
Table 3.2: int data type
3.3.2 Floating Point
A floating point is a class of numeric variables that allow the storage of fractions
and exponents to very precise values. A floating point number has a sign, an
integer part and a fractional or exponential part.
float var1 , var2 =1.2;
E.g. 3.2435𝐸 + 03 is the same as 3243.5
Normally floating point number are 4 bytes long, the data type double can
be used to make an 8 byte long floating point number. The floating point
numbers can be set with the precision of how many digits to be displayed after
the decimal point.
Declared Length in bytes Limits of positive values
float 4 8.43𝐸 − 37 to 3.37𝐸 + 38
double 8 2.225074𝐸 − 308 to 1.797693𝐸 + 308
long double 10 2.225074𝐸 − 308 to 1.797693𝐸 + 308
Table 3.3: float data type
The float data type allows signed values, so using unsigned along with
float or double will cause a compiler error.
3.3.3 Character
A character is a single byte containing any character in ASCII code. It can be
alphabets, numbers2
, special characters, newline, form feed etc. A char data
type occupies one byte of memory. They are stored in their ASCII form.
char a, b=‘c’, c=‘1’;
2We can represent numbers with the char data type but we cannot treat them as numbers
and cannot be used for calculations.
12 3. Identifiers and Data Types
A character string can be declared only as an array.
char a[10];
These data types can be further modified using the data type modifiers and
storage class specifiers.
3.4 The Data Type Specifiers
3.4.1 signed or unsigned
unsigned data items are used for positive values. But signed data items can
have values ranging from a minimum negative value to a maximum positive
value.
3.4.2 long or short
The short type is used for saving memory. It has half length of long type.
3.4.3 const
The keyword const is used along with a variable name to make it a constant.
Throughout the scope of the variable it’s value will remain a constant and any
attempt to modify the value during runtime will result in an error.
3.4.4 volatile
When a variable is declared as volatile, we are telling the compiler that the
value of the variable might be changed at any time—without any action being
taken by the code the compiler finds nearby.
3.5 The Storage Class
The storage class specifier specifies the segments of the program where the
variable is recognized, and how long the storage of the value of variable will
last. The storage class specifiers are:
3.5.1 Automatic variables (auto)
This is the storage class that a compiler uses by default. A variable declared
with auto as the storage specifier is stored in the memory and it is local to the
function in which it is declared. Auto variables declared in different functions
even though having the same name are independent. The life cycle of such
variables are till the function which contains them are executed.
auto int a;
3.6 User Defined Data Types 13
3.5.2 Static variables (static)
These variable contain the value zero by default when created or we can say
that they are initialized with zero, unless we give a value. These variables are
local to the function but they exist till termination of the program. So the value
of the static variable unlike the auto variable is not lost once the function is
over, it exists till the end of the program. And so if the function is called for a
second time somewhere else in the program then the variable uses the previously
stored value. Such variables can be used as counters.
static int a;
3.5.3 External variables (extern)
The scope of such variables are global, i.e., they are available all over the pro-
gram. Sometimes a single program may contain several files linked, a variable
with storage specifier extern is available everywhere. So it is accessible by all
the functions in the program. If a function contains a local variable with the
same name as an extern variable then in the function preference will go first
to the local variable. This is a point to be kept in mind.
extern int a;
3.5.4 Register variables (register)
Register variables are similar to auto variables, the only difference is that the
auto variables are stored in the memory whereas the register variables are stored
in the registers of the CPU. We use the register variables because the CPU
registers respond much faster than the memory. Register variables maybe of 2
or 4 bytes and so most suitable for integer and character data types, also the
CPU registers are needed for other processes of the system so they should be
used only when necessary. We should not use too many register variables.
register int a;
3.6 User Defined Data Types
3.6.1 Arrays
Arrays are a collection of the same data type. There are one-dimensional and
multi-dimensional arrays in C. Eg. a character array can be used to store a
word, sentence or even a paragraph depending upon the size of the array.
int num [20];
This is an array with space for 20 integers. The first element of an array is
located at num[0], the next one at num[1] and so on. The last element is at
num[19]. In general, an array of size 𝑛 has first element at arrayname[0] and
last element at arrayname[n-1]. We can create arrays for any data type, even
14 3. Identifiers and Data Types
for the user defined data types that we will see shortly. A multi-dimensional
array can be considered as an array of arrays. We can represent a matrix as a
two-dimensional array. For a character array of size 𝑛, we can store only 𝑛 − 2
characters because the last ((𝑛−1)𝑡ℎ
) position is occupied by the null character
0 which represents the termination of the string.
3.6.2 Structure
An array can contain only values of same data type. Suppose we want to group
the details of a student like roll number, name, marks, rank etc., we have to
create a structure. A structure can be considered as a group of different data
types. We will study in detail about structures and unions in a later chapter.
3.6.3 Union
Union is similar to structure . The only difference is that a structure occupies
a memory equivalent to the sum of lengths of all elements present in it whereas
the size of a union is equal to the size of the largest element present in it.
3.6.4 Enumerations
Enumerations are nothing but just assigning names to numbers.
enum{sun ,mon ,tue ,wed ,thur ,fri ,sat}
With the above declaration we can use sun to represent 0, mon to represent
1 and so on. We can also change the values.
enum{sun=1,mon ,tue ,wed ,thur ,fri ,sat}
Then the numbering starts from 1 and goes on increasing by 1.
3.6.5 Typedef
Typedef cannot be considered as a pure data type because all it does is to
rename an existing data type to a new one. Eg.
typedef int number;
typedef char name [10];
Now we can use number as keyword to declare integer data types and name
to declare character arrays of size 10.
3.6.6 Typecasting
Typecasting is making a variable of one type, such as a float, act like another
type, an int, for one single operation. To typecast something, simply put the
type of variable you want the actual variable to act as inside parantheses in
front of the actual variable. (char)a will make ‘a’ function as a char.
3.7 Exercise 15
There is explicit and implicit typecasting. In implicit typecasting (type
conversion) the compiler converts one data type to another where ever needed.
In explicit typecasting we have to tell the compiler to typecast a variable.
int a=10;
float b=2.5,c;
(char) a; // explicit
c=a/b; // here a is implicitly converted to float
3.7 Exercise
1. Identify which of the variable names are illegal and explain the reason.
(a) $num
(b) 12phone
(c) avg2
(d) date-of-birth
(e) time
(f) my,file
(g) break
(h) default
2. What are data types? How can they be classified?
3. char is often treated as an integer type. Why is it so?
4. What are the advantages and disadvantages of floating point numbers over
integers?
5. Differentiate between a structure and an array.
Chapter 4
Input/Output Operations
Most earlier programming languages had poor support for I/O. The designers of
C overcame this problem by having I/O operations done using library functions,
so that program designers can have tailored I/O. As C has evolved, a library
package known as the ‘Standard I/O Library’ or stdio, has evolved with it and
has proved to be both flexible and portable. This package has now become part
of the Standard.
In C everything is treated as a stream of bytes, whether it is a file or the
standard input or output. The file I/O has been reserved for a later chapter.
Now let’s see the basic Standard I/O.
printf() is the command that tells the compiler to print something on the
screen, and scanf() is the command that tells the compiler to read something
from the standard input device.
The functions can be illustrated with the following program:
/*
A program to explain the STANDARD I/O
*/
#include <stdio.h>
int main ()
{
int num;
char alph;
float x;
printf("Enter an integer , a character and a
floating point num: ");
scanf("%d,%c,%f" ,&num ,&alph ,&x);
printf("The integer is %d nThe character is %c
nThe floating point num is %f n",num ,alph ,x);
return 0;
}
Program 4.1: Standard I/O
You can compile the above program and check it’s output.
In the above program you can see a lot of weird characters like %d, &num etc.
The %d %f etc. are called conversion characters. The table below provides the
list of conversion characters.
The conversion characters can also be used to set the precision of the floating
16
4.1 The gets() and puts() 17
Conversion character Displays argument (variable’s contents) as
%c Single character
%d Signed decimal integer (int)
%e Signed floating point value in E notation
%f Signed floating point value (float)
%g Signed value in %e or %f format, whichever is
shorter
%i Signed decimal integer (int)
%o Unsigned octal (base 8) integer (int)
%s String of text
%u Unsigned decimal integer (int)
%x Unsigned hexadecimal (base 16) integer (int)
Table 4.1: Conversion Characters
point numbers. %0.2f gives a precision of up to 2 decimal places. The general
format is %x.yf, where x and y are numbers to denote the length.
Then there are escape sequences which help in formatting the output by
providing newline, tab etc. Table 4.2 provides the list of escape sequences in C.
Sequence Meaning
a Beeps the speaker
b Backspace (moves the cursor back, no erase)
f Form feed (ejects printer page; may clear the screen on
some computers)
n Newline, like pressing the Enter key
r Carriage return (moves the cursor to the beginning of
the line)
t Tab
v Vertical tab (moves the cursor down a line)
 The backslash character
’ The apostrophe
" The double-quote character
? The question mark
0 The “null” byte (that’s 0, not the letter O)
Onn A character value in octal (base 8)
xnnn A character value in hexadecimal (base 16)
Table 4.2: Escape Sequences
The printf() and scanf() are functions defined in stdio.h. We can also
input to and get output from a file. File I/O is a topic for a further chapter but
the reader should know from the beginning itself that the C compiler treats all
input and output devices and files as streams of bytes.
4.1 The gets() and puts()
The scanf() has a problem when handling strings, it will read only till the
blank space. It will not read after a blank space occurs so we can give as input
only a word. gets() and puts() are functions in the stdio.h header file. The
gets() is used for input and puts() is used for output of a string.
#include <stdio.h>
int main ()
18 4. Input/Output Operations
{
char msg [50];
printf("nEnter the message: ");
gets(msg);
printf("nThe message ist: ");
puts(msg);
printf("The message can also be printed:
%sn",msg);
return 0;
}
Program 4.2: gets() and puts()
4.2 Exercise
1. Write a program that accepts your name, age and occupation and prints
them as below.
Name : Vineeth
Age : 20
Occupation : Student
2. Write a program that prints the value of 𝜋(22/7) up to 4 decimal places.
(Hint: use %0.4f as conversion character)
Chapter 5
Operators
Every program will contain expressions. Expressions are a combination of op-
erators and operands. Eg. the + operator requires two operands and it acts on
the operands and produces the sum as the result.
In C the operators can be classified based on the number of operands it
operates on as:
1. Unary operators
2. Binary operators
3. Ternary operators
They are also classified based on type of operation as:
1. Arithmetic operators
2. Relational operators
3. Logical operators
4. Assignment operators
5. Increment and Decrement operators
6. Bitwise operators
7. Conditional operators
5.1 Binary Operators
5.1.1 Arithmetic Operators
All the basic arithmetic operations can be carried out in C. All the operators
have almost the same meaning as in other languages. Both unary and binary
operations are available in C language. Unary operations operate on a single
operand.
The operators are + (addition or unary +), − (subtraction or unary minus),
* (multiplication), / (division), % (modulo or the remainder operator—it gives
remainder of division between 2 numbers1
).
1The modulus operator cannot be applied for floating point numbers, it will be an error.
19
20 5. Operators
Eg. 5%2 = 1
Except the modulus operator all other operators are same for floating point
numbers.
5.1.2 Relational Operators
The relational operators used in C are:
<: less than
>: greater than
<=: less than or equal to
>=: greater than or equal to
==: equal to2
!=: not equal to
These operators always return the values as true or false (0,1).
5.1.3 Logical Operators
The logical operators are:
&&: Logical AND
This operator returns the value true only if both the subordinate expressions
are true.
Eg. (x>2) && (y<4)
||: Logical OR
This operator returns the value true if at least one of the subordinate expres-
sions is true. If the left term is true then right term is not evaluated at all.
Eg. (x>2) || (y<4)
!: Logical NOT
5.1.4 Assignment Operators
The = is the assignment operator used to assign values to variables. The variable
to which the value is to be stored should come on the left side and the value or
variable whose value is to be stored comes on the right side.
count = count + 1 can be written as count+=1. Similarly we can write
count-=5 for count = count - 5.
For multiplication, division and modulus also we can apply this rule.
5.1.5 Bitwise Operators
Normally we don’t have to use these operators. We only need to handle data in
bytes. But for programs like encryption, data compression etc. we will have to
handle data at the bit level.
Bitwise AND (&)
& operator is bitwise AND. The following is a chart that defines &, defining
AND on individual bits.
2Not to be confused with ‘=’ which is an assignment operator and not a comparison
operator
5.1 Binary Operators 21
x y x&y
0 0 0
0 1 0
1 0 0
1 1 1
Table 5.1: Bitwise AND
Bitwise OR (∣)
The ∣ operator is bitwise OR (it’s a single vertical bar). The following is a chart
that defines ∣, defining OR on individual bits.
x y x∣y
0 0 0
0 1 1
1 0 1
1 1 1
Table 5.2: Bitwise OR
Bitwise XOR
The ˆ operator is bitwise XOR. The usual bitwise OR operator is inclusive OR.
XOR is true only if exactly one of the two bits is true. The XOR operation is
quite interesting, but we defer talking about the interesting things you can do
with XOR until the next set of notes.
The following is a chart that defines ˆ, defining XOR on individual bits.
x y x ˆ y
0 0 0
0 1 1
1 0 1
1 1 0
Table 5.3: Bitwise XOR
Bitwise NOT
There’s only one unary bitwise operator, and that’s bitwise NOT. Bitwise NOT
flips all of the bits. There’s not that much to say about it, other than it’s not
the same operation as unary minus. The following is a chart that defines ˜,
Bitwise Shifts
There are two bitwise shift operators, namely shift left and shift right. They
are represented by the << and >> operators, respectively. These operations are
very simple, and do exactly what they say: shift bits to the left or to the right.
The syntax for a shift operation is as follows:
[integer] [operator] [number of places];
A statement of this form shifts the bits in [integer] by the number of
places indicated, in the direction specified by the operator. Probably the best
22 5. Operators
x ˜ x
0 1
1 0
Table 5.4: Bitwise NOT
way to visualize this is with an example. Take a look at the following code,
which demonstrates a shift left.
x = 0000 0110 1001 0011
x = x << 1;
x = 0000 1101 0010 0110
From this example, you should be able to see what’s going on. Every bit in x is
shifted to the left by one place. When you do this, the MSB (most significant
bit) of x is lost, because there isn’t another place to shift it to. Similarly, after
a shift left, the LSB of x will always be 0. There is no position to the right of
the LSB, and so there’s nothing to shift into the LSB, so it’s assigned a value
of 0.
5.2 Unary Operators
5.2.1 Unary plus and minus
It controls the sign of a numeric constant or variable. The operator is prefixed
to the constant or variable. It can also be used to change the sign of expressions
as a whole.
Eg. −5, +2, −𝑥, −(𝑥 + 𝑦)
5.2.2 Increment and Decrement Operators
The increment ++ and decrement −− operators, as the name suggests, are
used to increment and decrement the value of a variable. These operators can
be used in two forms when used in expressions:
1. Post fix norm: In this form the ++ comes after the variable as var name++
or var name--. In this form the value of the variable is first used in the
expression and then incremented.
2. Prefix norm: In this form the ++ or −− comes before the variable as
++var name or --var name. When used in this form the variable value is
first used in the expression and then incremented later.
The following program illustrates the effect of the above mentioned forms.
#include <stdio.h>
int main ()
{
int num1=3,num2;
num2 = num1 ++; //In the post fix form
printf("Num1 =%d nNum2 =%d n",num1 ,num2);
num2 = ++ num1; //In the prefix form
printf("Num1 =%d nNum2 =%d n",num1 ,num2);
5.3 Ternary Operators 23
}
Program 5.1: Increment and decrement operators
The output will be:
Num1=4
Num2=3
Num1=5
Num2=5
The same rule is applicable to the decrement operator also.
5.3 Ternary Operators
5.3.1 Conditional Operator
The operator (expression1)?(expression2):(expression3) is called the con-
ditional operator. It evaluates expression1 and if the result is true it returns
expression2, if result is false it returns expression3.
(x>y) ?x:y;
The above statement will check if x is greater than y and if so it will return x
or else it will return y.
5.3.2 Precedence and Associativity
Two operator characteristics determine how operands group with operators:
precedence and associativity. Precedence is the priority for grouping different
types of operators with their operands. Associativity is the left-to-right or right-
to-left order for grouping operands to operators that have the same precedence.
An operator’s precedence is meaningful only if other operators with higher or
lower precedence are present. Expressions with higher precedence operators are
evaluated first. The grouping of operands can be forced by using parentheses.
Table 5.5 lists the precedence and associativity of the operators we studied.
5.4 Exercises
1. Define precedence and associativity.
2. How are operators classified in C?
3. What is the output of the following statement: 4 + 5 ∗ 3 − 2%3?
4. Write the output of the following program:
#include <stdio.h>
int main ()
{
int a=0;
printf("n %d n %d n %d n",a,++a,a++);
return 0;
}
Program 5.2: Find the output
24 5. Operators
Operator Description Associativity
() Parentheses (function call) left-to-right
[] Brackets (array subscript)
. Member selection via object name
-> Member selection via pointer
++ -- Postfix increment/decrement
++ -- Prefix increment/decrement right-to-left
+ - Unary plus/minus
! ˜ Logical negation/bitwise complement
(type) Cast (change type)
* Dereference
& Address
sizeof Determine size in bytes
* / % Multiplication/Division/Modulus left-to-right
+ - Addition/Subtraction left-to-right
<< >> Bitwise shift left/Bitwise shift right left-to-right
< <= Relational less than/less than or equal to left-to-right
> >= Relational greater than/greater than or equal to
== != Relational is equal to/is not equal to left-to-right
& Bitwise AND left-to-right
ˆ Bitwise exclusive OR left-to-right
| Bitwise inclusive OR left-to-right
&& Logical AND left-to-right
|| Logical OR left-to-right
?: Ternary conditional right-to-left
= Assignment right-to-left
+= -= Addition/Subtraction assignment
*= /= Multiplication/Division assignment
%= &= Modulus/Bitwise AND assignment
ˆ= |= Bitwise exclusive/inclusive OR assignment
<<= >>= Bitwise shift left/right assignment
, Comma (separate expressions) left-to-right
Table 5.5: Precedence and Associativity
Chapter 6
Control Statements
A program consists of a number of statements which are usually executed in
sequence. Programs can be much more powerful if we can control the order in
which statements are run. Decision making is one of the crucial and essential
part of a program. We will encounter situations where we will have to make
a decision on how to proceed further. Decision making statements in C check
whether a given statement is true or false. The decision making statements in
C are if else and switch case.
6.1 if...else
The if statement has two forms:
if(expression) statement
if(expression)
{
statements ...
}
else
{
statements ...
}
The statements in the if block are executed if the expression is true and
statements in else block are executed if the expression is false. The if else
statements can also be used in the form of if else ladder or as nested if else.
The curly braces are not an essential part of the if statements if there is only a
single statement following it, but it’s always a good practice to use the braces.
// A program to find largest of two numbers
#include <stdio.h>
int main(int argc ,char argv [])
{
int num1 ,num2;
printf("Enter the first number: ");
scanf("%d" ,&num1);
printf("Enter the second number: ");
scanf("%d" ,&num2);
if(num1 >num2) printf("First number is largern");
25
26 6. Control Statements
else
printf("Second number is largern");
return 0;
}
Program 6.1: Largest of two numbers
6.1.1 Nested if else
if(expression)
{ statements }
else if(expression)
{ statements }
else
{ statements }
The ladder can be extended as long as required.
if (result >= 75)
printf(‘‘Passed: Grade An’’);
else if (result >=60)
printf(‘‘Passed: Grade Bn’’);
else if (result >=45)
printf(‘‘Passed: Grade Cn’’);
else
printf(‘‘Failedn’’);
Nesting can be done in the else tag also.
6.2 switch case
This is another form of the multi way decision. It can only be used in certain
cases where:
∙ Only one variable is tested, all branches must depend on the value of that
variable. The variable must be an integral type. (int or char).
∙ Each possible value of the variable can control a single branch. A final,
catch all, default branch may optionally be used to trap all unspecified
cases.
It’s syntax is
switch(choice)
{
case val1: statements; break;
case val2: statements; break;
default: statement; break;
}
Each interesting case is listed with a corresponding action. The break state-
ment prevents any further statements from being executed by leaving the switch.
Both if and switch constructs allow the programmer to make a selection
from a number of possible actions.
Let us see an example program.
6.3 Conditional Operator 27
// A program to display the day corresponding to a
number
#include <stdio.h>
int main(int argc ,char argv [])
{
int num;
printf("Enter a number: ");
scanf("%d" ,&num);
switch(num)
{
case 1: printf("nSunday n");
break;
case 2: printf("nMonday n");
break;
case 3: printf("nTuesday n");
break;
case 4: printf("nWednesday n");
break;
case 5: printf("nThursday n");
break;
case 6: printf("nFriday n");
break;
case 7: printf("nSaturday n");
break;
default: printf("Error");
break;
}
return 0;
}
Program 6.2: switch case
6.3 Conditional Operator
The conditional operator is similar to if else but nesting is not possible.
condition?statement1:statement2;
Here we check for the validity of the condition. If it’s true statement1 is
executed or else statement2 is executed.
6.4 Loops
The other main type of control statement is the loop1
. Loops allow a statement,
or a block of statements, to be repeated. Computers are very good at repeating
simple tasks many times, the loop is C’s way of achieving this. A looping
statement consists of an initializing statement, a validation statement and an
increment/decrement statement. There are two types of loops in C they are:
∙ Entry controlled loops
∙ Exit controlled loops
1Loops are also called iteration statements.
28 6. Control Statements
6.4.1 Entry Controlled Loops
Entry controlled loops are loops in which the expression is checked before the
loop is executed. Such loops are used when we have to execute loop only if
the validation expression is valid. The entry controlled loops in C are for and
while.
The for Loop
The syntax of for loop is
for(initializing statement; validation expression; increment/decrement)
{ loop body }
Basically a for loop can be written as simply as
for( ; ; )
{ loop body }
It’s only the semicolons within the parentheses that are important in a for loop.
The above loop will be executed infinitely and is called an infinite loop.
// A program to print first 10 natural numbers
#include <stdio.h>
int main(int argc ,char argv [])
{
int i=1;
for(i;i <=10;i++)
{
printf("n %d n",i);
}
return 0;
}
Program 6.3: for loop
For a loop body with a single statement, the { } can be avoided. In the
below program
for(int i=1;i <=10;i++)
{
printf(‘‘n %d n’’,i);
}
can be replaced by
for(int i=1;i <=10;i++)
printf(‘‘n %d n’’,i);
but it is always a good practice to use the braces, it makes the program more
readable and understandable.
The for loop can be used as a nested for loop.
The while Loop
while is another entry controlled loop that checks the validity of an expression
before executing the loop body. Unlike a for loop the while has the incremen-
t/decrement statement within the loop body.
6.4 Loops 29
The syntax of while loop is:
while(expression)
{ loop body }
We can rewrite the program for printing number 1–10 using the while loop.
#include <stdio.h>
int main(int argc ,char argv [])
{
int i;
i=1;
while(i <=10)
{
printf("n %d n",i);
i++;
}
return 0;
}
Program 6.4: while loop
6.4.2 Exit Controlled Loops
Exit controlled loops check the validity of the expression only after each itera-
tion.
The do...while Loop
The do while loop is an exit controlled loop because the expression is checked
for validity only after executing the loop body each time. Such loops are used
when we need the loop to be executed at least once.
The syntax of do while is
do
{ loop body }
while(expression);
The semicolon after while is important in the do while, it marks the end
of the loop.
The program to print numbers 1–10 can be done using do while loop, and
it is left as an exercise for the readers.
6.4.3 The break Statement
Sometimes while executing a loop it becomes desirable to skip a part of the
loop or quit the loop as soon as certain condition occurs, for example consider
searching a particular number in a set of 100 numbers, as soon as the search
number is found it is desirable to terminate the loop. C language permits a
jump from one statement to another within a loop as well as to jump out of
the loop. The break statement allows us to accomplish this task. A break
statement provides an early exit from for, while, do and switch constructs.
A break causes the innermost enclosing loop or switch to be exited immediately.
30 6. Control Statements
The syntax is
break;
6.4.4 The continue Statement
During loop operations it may be necessary to skip a part of the body of the
loop under certain conditions. Like the break statement C supports similar
statement called continue statement. The continue statement causes the loop
to be continued with the next iteration after skipping any statement in between.
The syntax is
continue;
6.5 Exercises
1. Write a program to accept length of 3 sides of a triangle and check if a
triangle can be formed with the given sides.
2. Write a program to calculate the total mark of a student for five subjects
and find out his grade such that if percentage of mark is
I. A => 80
II. B => 70
III. C => 60
IV. D => 50
V. F for failed
Also print the mark list along with student name, roll number, class, year,
percentage and grade in a well formatted manner.
3. Write a program to print the letters of your name in a lower triangular
form.
The name Vineeth should be printed as
V
Vi
Vin
Vine
Vinee
Vineet
Vineeth
4. Write a program to print the Fibonacci series (0,1,1,2,3,5,. . . the next num-
ber is sum of the previous two numbers).
5. Write a program to check if a given number is a prime number.
6. Write a program to generate the mathematical tables up to a given limit.
Chapter 7
Structured Data Types
For a large class of problems in computing, it is the data and not the algorithms
that are the most interesting. If the initial design gets it’s data structures
right, the rest of the effort in putting a program together is often quite small.
However, you need help from the language. If there is no support for structured
data types other than arrays, writing programs becomes both less convenient
and also more prone to errors. It is the job of a good language to do more than
just allow you to do something; it must actively help as well.
C offers arrays, structures and unions as it’s contribution to data structuring.
They have proved to be entirely adequate for most users’ needs over the years
and remain essentially unchanged by the Standard.
In this chapter we will discuss the three basic structured data types used in
C.
1. Arrays
2. Structures
3. Unions
There are other structured data types in C like enums and bitfields.
7.1 Arrays
An array is a list of objects all of the same type. The objects comprising an array
are called elements. The dimensions of an array describe how many elements an
array contains and how it’s elements are arranged in memory. Each element is
identified by an index. Giving the relative position of the element within the list,
the first element has the index 0. A one-dimensional array arranges elements
in a linear list whereas a two-dimensional array arranges elements like elements
in a matrix. Arrays of higher dimensions are also possible. The elements of an
array are arranged contiguously in memory. For two and higher dimensional
arrays the elements are stored in row major order (in a matrix X after X[m][n],
X[m][n+1] is stored.).
An array can be for both in-built and user defined data types.
data type arrayname[size ][ size ];
31
32 7. Structured Data Types
Arrays can be initialized only with constant values and not with variables.
The following example shows how to initialize a two-dimensional array.
int sample [2][2]={{1 ,2 ,3} ,{4 ,5 ,6} ,{7 ,8 ,9}};
You can omit the size within the brackets of the last array dimension when you
include an initializer for the array.
7.2 Structures
Arrays allow for a named collection of identical objects. This is suitable for
a number of tasks, but isn’t really very flexible. Most real data objects are
complicated things with an inherent structure that does not fit well on to array
style storage. Let’s use a concrete example.
Imagine we have to collect the data of all students in a college. Each student
will have certain data associated with him like name, class, roll number, marks
etc. So we have to group all these data together as single piece for one student
and repeat the same for all the other students. In such a situation we use
structures. Structures are user defined data types that are a collection of several
other user defined or primary data types. Let’s look at a code snippet
struct student
{
int rollno , marks , avg;
char name [20], class [6];
};
In the above example, student is called the tag or the structure name and
within the braces we’ve declared the variables that the structure student should
hold. Structures do not occupy any memory unless associated with an instance.
The size of a structure is the total size of all the individual elements it contains.
Structure instances cannot be declared without defining the structure.
Once the structure is defined it can be treated just like other data types in
C. We can call it in a function or the main program and access each element of
the structure, we can even create an array with the created structure. Let’s see
a program:
#include <stdio.h>
struct student
{
int rollno ,marks;
char name [20], class [6];
} stud1 ={1 ,450 ,"xyz","ee"},stud2; //A variable can
be declared like this :-)
int main ()
{
struct student s;
// struct student s[10]; An array can also be
declared with student as datatype
printf("Enter the name of the student: ");
scanf("%s" ,&s.name);
7.2 Structures 33
printf("nThe name of the student is: %s
n",s.name);
stud2=s; // Assigning one variable to another
printf("nThe name of the student is: %s
n",stud2.name);
return 0;
}
Program 7.1: Structure
The above example has a lot of treasure in it, let’s dig it all out :-)
∙ We see that right after the definition body of the structure an instance
has been declared, this is one way of declaring instances for the created
structures.
∙ The semicolon that appears right after that is compulsory even if the
instance wasn’t declared. It denotes the end of the structure definition so
missing out the semicolon will result in syntax error.
∙ The instance of the particular structure is defined as a primary data type.
Even an array can be declared and sometimes we use these structures
inside others which we will see soon.
∙ The most important question is, how to access each element of the struc-
ture? The answer is a simple . The . is called a dot operator. It’s syntax
is instance.member name, this will be clear from the above example where
s.name shows how the dot operator functions.
∙ The assignment operator or the = can also be used with structures but
no other operator can be used. We can assign the values of one structure
instance to another instance of the same structure.
∙ The next question is about initializing the instance. The instance de-
clared can be initialized by giving the values of each element within the
{} separated by a comma.
Well that should explain almost the whole of structures. Now there are some
points that I have left out and I have done it intentionally. These are:
∙ What happens if while initialization we input values which are less than
the number of the elements i.e. in the above example student contains 4
elements then what will happen to a statement
struct student a={1,2,‘‘ab’’};
∙ Can we assign only a particular element of one structure variable to an-
other structure variable?
∙ All other questions and possibilities that you can think about have been
left out as an exercise for the reader, after all what thrill is there if you
are provided with all the information. The thrill lies in discovering things
and thats how we c :-)
7.2.1 Nested Structures
Structures can be nested, that is one structure can be used as a data type in
another structure.
34 7. Structured Data Types
struct employee
{
int id ,salary;
char name [20];
}
struct manager
{
struct employee x;
char grpcharge [20];
}
In the above code we can see that the structure employee is nested within
the structure manager because a manager is also an employee with additional
characteristics. So both structures have some common traits. So we can avoid
duplicating of code (some people call it reusability of code).
7.2.2 Unnamed Structures
Structures can also be created without a name, but such structures cannot be
used for later references. We have to create instances of the structure at the
same time when we define the structure.
struct
{
char bookname [10];
int isbn_no;
} book1 , book2 , book3;
With the above code we use the variables book1, book2, book3 but we
cannot write the statement to create a new variable because we do not have a
tag to identify the structure.
7.3 Unions
Unions are user defined data types that are a collection of several other user
defined or primary data types. Does this definition seem familiar! Well it is
because we defined the structures in the same way. So actually then what is
the difference of a union? The difference of a union and a structure lies in it’s
memory allocation. Let’s look at the following code.
struct strdate
{
int year ,dat;
char month [10];
} var1;
union dateunion
{
int year ,dat;
char month [10];
} var2;
In the above example we have declared a union and a structure to hold the
date.
A structure variable var1 will have the memory size of 14 bytes (2 bytes for
year, 2 bytes for dat, 10 bytes for month).
7.4 Exercises 35
But the union instance var2 will have the size of 10 bytes only (the size
required for the largest element). So that’s how a union is different from a
structure. It can accept only the value for one of the elements at a time that
belongs to it. You can picture a union as a chunk of memory that is used to
store variables of different types. Once a new value is assigned to a field, the
existing data is wiped over with the new data.
Unions are used in situations where we need to use only one element of a
structure at a time and thus we can reduce the wastage of space.
The method to access union elements is the same as that for structures.
Now the question is how to initialize an instance of the union. We know that
an instance of a union can hold value to only one of it’s variables.
Let’s see how to do this:
union dob
{
int year ,date;
char month [10];
} var1 ={1990} , var2 ={. date =15};
This is how to initialize a union instance. We can use only one value and
that value will be assigned to the first element. If we are specific about the
element it should be specified as is done for var2 (the . is very important, do
not omit it).
7.4 Exercises
1. Write a program to find the sum of two matrices.
2. Write a program to find product of two matrices (two matrices of order
𝑚 ∗ 𝑛 and 𝑝 ∗ 𝑞 can be multiplied only if 𝑛 = 𝑝).
3. Write a program that will accept an array and then sort elements of the
array in ascending order and display the elements.
4. Write a program that has a structure that contains all details of employees
in a firm. Create structure for a normal employee and for the manager.
And display the details when requested.
5. Write a program to compare two given words (ignore case sensitivity).
Chapter 8
Functions
The divide and conquer is the most often used technique in programming large
programs. Programs are divided into smaller modules and finally they are joined
together. This helps in understanding and debugging the code. A function in
C is a block of code that performs a specific task. It has a name and it can
be executed from as many different parts in a program as required. It also
optionally returns a value to the calling program, we have already seen the
main() function.
So function in a C program has some properties discussed below.
∙ Every function has a unique name. This name is used to call function
from anywhere in the code.
∙ A function is independent and it can perform it’s task without intervention
from or interfering with other parts of the program.
∙ A function performs a specific task. A task is a distinct job that your
program must perform as a part of it’s overall operation, such as adding
two or more integers, sorting an array into numerical order, or calculating
a cube root etc.
∙ A function returns a value to the calling program. This is optional and
depends upon the task your function is going to accomplish. Suppose you
want to just show few lines through function then it is not necessary to
return a value. But if you are calculating area of a rectangle and wanted to
use the result somewhere in program then you have to send back (return)
value to the calling function.
C language is collection of various in-built functions. If you have written a pro-
gram in C then it is evident that you have used C’s in-built functions. printf,
scanf, clrscr etc. all are C’s in-built functions. You cannot imagine a C
program without function. There are three steps in using functions, they are
1. Function declaration (function prototype): The syntax for function
declaration is
type name(arguments);
2. Function definition: The syntax for this is
type name(arguments){statements}
3. Function calling
36
8.1 Passing Values to Arguments 37
The function declaration and definition can be made together. The function
declaration should be made before calling the function. But function definition
need not be defined before calling it can be done even after calling. Let’s see a
small code:
/**A program to find area of square **/
#include <stdio.h>
double find_area(double);
int main ()
{
double side ,area;
printf("nEnter the length: ");
scanf("%f" ,&side);
area=find_area(side);
printf("nThe area of the square is: %f n",area);
return 0;
}
double find_area(double leng)
{
return(leng*leng);
}
Program 8.1: Area of Square
The above code displays some features.
∙ At first we see that the function find area() is declared if not the com-
piler will show an error.
∙ Then you can see that the argument list in the function declaration consist
only of the data type of variable used and not the variable name used. The
variable name is not necessary in the argument list during declaration but
it is compulsory in the argument list of function definition.
∙ We have also seen how the function returns a data and so it can be used
in expressions.
∙ The variable leng is called the formal argument and side is called actual
argument. We can say that formal arguments are the arguments that we
define in function declaration and actual arguments are arguments that
we pass to the function during function call.
8.1 Passing Values to Arguments
In the previous example we saw that the length of the square was given as
an argument to the function find area(), the function used this argument for
further calculation.
The argument list can contain as many arguments as required, it can even
be zero. The data type of each argument should be given separately even if they
all are of the same type. In case there are arguments then we should learn how
the values we give as input is passed to the arguments in the function.
The arguments are passed to the functions by
1. Pass by value
2. Pass by reference using pointer method
38 8. Functions
The pointer method will be dealt with in a later chapter.
8.1.1 Pass by Value
In this method we make a copy of the original variable and the function operates
on that copy, so the original variable is not affected.
8.1.2 Pass by Reference
In this method we refer to the function the original address where the variable
is stored and the function operates directly on that variable, so changes that
the function brings about on the variable is reflected on the value stored in the
variable itself. There are two methods to do this.
∙ Using reference variables - C does not support this method
∙ Using pointers
You may find several sources with arguments on this topic, some say that C
does not support pass by reference at all, and that the pointer method cannot
be called a pass by reference method, but this does not matter because all we
need is a program to work as we wish.
8.2 The return Statement
We have seen that a function itself has a data type, this indicates what type of
value the function will return after it’s execution, so all functions except the one
with void as data type should have at least one return statement. During the
execution of a function only the first return statement will be executed because
a function exits as soon as it encounters a return statement.
int my_fun(int a,int b)
{
if(a>b)
return a;
else
return b;
}
In the above code the function returns the greatest of the two values passed
to it, as soon as it meets one return statement the function execution is over.
For functions with void as data type the closing braces (}) acts as an automatic
return statement.
8.3 Functions with Variable Argument List
Perhaps you would like to have a function that will accept any number of values
and then return the average. You don’t know how many arguments will be
passed into the function. One way you could make the function would be to
accept a pointer to an array.
8.3 Functions with Variable Argument List 39
Functions in C can also have an argument list that varies in length, for that
we use an operator called ellipsis which consists of three (.) without any space
between them. The function prototype will be
int fun(int num , ...);
Indeed, some library functions can accept a variable list of arguments (such
as printf—I bet you’ve been wondering how that works!).
Whenever a function is declared to have an intermediate number of argu-
ments, in place of the last argument you should place an ellipsis (which looks
like ‘. . . ’), so,
int a_function(int x, ...);
would tell the compiler the function should accept however many arguments
that the programmer uses, as long as it is equal to at least one, the one being
the first, x.
To use these functions, we need a variable capable of storing a variable-
length argument list—this variable will be of type va list. va list is like any
other type.
va start is a macro which accepts two arguments, a va list and the name
of the variable that directly precedes the ellipsis (“. . . ”). So in the function
a function, to initialize list with va start, you would write va start(list,
x);
int a_function(int x, ...)
{
va_list list;
va_start(list , x);
}
va arg takes a va list and a variable type, and returns the next argument
in the list in the form of whatever variable type it is told. It then moves down the
list to the next argument. For example, va arg(a list, double) will return
the next argument, assuming it exists, in the form of a double. The next time
it is called, it will return the argument following the last returned number, if
one exists. Not that you need to know the type of each argument—that’s part
of why printf requires a format string! Once you’re done, use va end to clean
up the list: va end(a list);
To show how each of the parts work, take an example function:
#include <stdarg.h>
#include <stdio.h>
float average(int num , ...)
{
va_list arg;
float sum =0;
int x;
/* Initializing arguments to store all values
after num */
va_start(arg ,num);
/* Sum all the inputs; we still rely on the
function caller to tell us how many there are */
40 8. Functions
for(x=0;x<num;x++)
{
sum += va_arg(arg ,float);
}
va_end(arg); // Cleans up the list
return sum/num;
}
int main ()
{
printf("%fn",average (3, 12.2, 22.3, 4.5));
printf("%fn",average (5, 3.3, 2.2, 1.1, 5.5, 3.3));
}
Program 8.2: Variable argument list
In the variable-length part of variable-length argument lists, the old “default
argument promotions” apply: arguments of type float are always promoted
(widened) to type double, and types char and short int are promoted to int.
Therefore, it is never correct to invoke va arg(argp,float); instead you should
always use va arg(argp,double) Similarly, use va arg(argp,int) to retrieve
arguments which were originally char, short or int. (For analogous reasons,
the last “fixed” argument, as handed to va start, should not be widenable,
either.)
It isn’t necessarily a good idea to use a variable argument list at all times;
the potential exists for assuming a value is of one type, while it is in fact another,
such as a null pointer being assumed to be an integer. Consequently, variable
argument lists should be used sparingly.
8.4 Scope of a Function
The scope of a function shows in what parts of a program code the function
is available. If a function is defined within main() then that function can be
used only in the main() of that code. Usually functions are declared outside
the main().
If we use the type qualifier static then the function is available only in the
source code where it’s definition is made. By default the type qualifier for a
function is extern. This shows that the function can be defined in some other
source file.
Also global variables are accessible by all functions but a variable declared
within a function is accessible only by that function. Any source file needing to
use a function in another source file should declare it.
8.5 Arrays as Arguments
Arrays can also be used as arguments to a function. In this case during function
declaration or definition the size of array may or may not be specified. Also
we’ve seen earlier that the name of an array also denotes the address of the
array so array arguments acts much like pointer arguments which we will see
in the coming chapter. The effect is that any change that we bring to array is
reflected because here the arguments are not passed by value i.e. the compiler
doesn’t pass the copies of the arguments but it passes the arguments itself. The
8.6 Recursive Functions 41
reason that the size of array is irrelevant in the function declaration is because
the array name is treated as an address location and the memory from that
location onwards is monitored by the function, but the programmer should take
care that the memory being accessed does not contain garbage values.
#include <stdio.h>
void fun(int arr[],int len)
{
int i;
for(i=0;i<len;i++)
{
printf("n%dn",arr[i]);
}
}
int main ()
{
int a[]={1 ,2 ,3 ,4 ,5};
fun(a,5);
return 0;
}
Program 8.3: Arrays as arguments
The above program prints out the elements in an integer array. Here the
programmer has to give size of array in the main() or else the function will not
know till when to read and it might read out some garbage values.
8.6 Recursive Functions
Recursion is a method where the solution to a problem depends on solutions
to smaller instances of the same problem. Recursion is a method used in Com-
puter Science to breakdown larger problems into smaller ones, there are a lot
of mathematical problems that use recursion. The factorial, Fibonacci series
etc. . . . all can be implemented by recursion. As the name suggests recursive
functions are functions that repeat in loop until terminated by some condition.
These are functions that refer back to themselves so they go on being executed.
In a programming language, recursive functions are an inefficient means of solv-
ing problems in terms of run times but are interesting to study, they simulate
the effect of using a stack. The property of a stack can be understood by con-
sidering a pile of books. When we place a new book to the pile (This is called
pop) it goes on top and the book that was on top first is pushed one position
down, while removing a book (This is called push) from that pile we move the
topmost or we use the LIFO (Last In First Out). Let’s see a program that finds
the factorial of a given number.
#include <stdio.h>
int fact(int num)
{
if(num <=1)
return 1;
else
{
return(num*fact(num -1));
}
}
int main ()
42 8. Functions
{
int result ,num;
printf("nEnter the number: ");
scanf("%d" ,&num);
result=fact(num);
printf("nThe result is %d n",result);
return 0;
}
Program 8.4: Factorial
In the above program the function fact() calls itself (This is called imme-
diate recursion) and thus it goes on till the variable num=1. Suppose the input
was three,
∙ In the first stage we get 3*fact(2)
∙ Then we gave 2*fact(1)
∙ fact(1) will return 1 so going back to the top we get 1*2
∙ This is returned to the outer fact() and we get 3*(1*2). Thus the
factorial of 3 was obtained.
All recursive functions can be rewritten with loops but making recursive func-
tions saves a lot of code. But care has to be taken that the recursive function
exits at some point of it’s execution and that it does not fall into an infinite
loop. Sometimes recursive functions are a bit tricky to understand even for a
well experienced programmer.
Tower of Hanoi
Almost every textbook that speaks about recursion in programming mentions
this famous puzzle. The Tower of Hanoi is a mathematical game or puzzle. It
consists of three rods, and a number of disks of different sizes which can slide
onto any rod. The puzzle starts with the disks in a neat stack in ascending
order of size on one rod, the smallest at the top, thus making a conical shape.
Figure 8.1: Tower of Hanoi
The objective of the puzzle is to move the entire stack to another rod, obeying
the following rules.
∙ Only one disk may be moved at a time.
8.7 Command Line Arguments 43
∙ Each move consists of taking the upper disk from one of the rods and
sliding it onto another rod, on top of the other disks that may already be
present on that rod.
∙ No disk may be placed on top of a smaller disk.
A key to solving this puzzle is to recognize that it can be solved by breaking the
problem down into a collection of smaller problems and further breaking those
problems down into even smaller problems until a solution is reached.
8.7 Command Line Arguments
It has already been mentioned that main() is also a function, this function also
has three arguments, the original form of the main() function is:
int main(int argc , char *argv[], char envp []);
The function main() has a return type of int and the exit code is the value
that the main() function returns. This is a number that is used by the OS to
detect whether the function exited properly or if there was any error. Usually
we return zero to denote a success in execution.
Before I explain the arguments let’s once again look at how we execute a
program from the shell.
Let the program name be prog, then at the terminal we type:
$ ./prog
($ symbol shows the command prompt, it is not to be typed). We can provide
values to the arguments right after the program name. Let copy be a program
to copy contents of one file to another then the program will be executed by
issuing the following command.
$ ./copy file1 file2
Here file1 and file2 are two arguments passed to the program copy. Now
let’s discuss the arguments in the main().
∙ int argc: This is the argument that keeps count of the number of words
appearing on the command line that invokes the program and the count
includes your program name also. In the above example, the value in
argc will be 3 (copy, file1, file2). The argc value will be at least
one because it counts the program name.
∙ char argv[]: This is a character array that contains the words including
the program name. In the above example the array will be
argv[]={copy,file1,file2}.
∙ The last variable is environment variable which contains details about
the environment in which the program is being executed, it lists out the
environment variables.
The argument argc and argv are conventional names, we can use any other
name.
Let us now see a program that elaborates on the command line arguments.
44 8. Functions
#include <stdio.h>
int main(int argc ,char *argv [])
{
int i;
printf("n The number of arguments is: %d
n" ,(argc -1)); /* argc contains count of
program name also */
printf("nnnaaaaaaThe arguments are: n");
for(i=0;i<argc;i++)
{
printf("%s",argv[i]);
}
printf("nn");
return 0;
}
Program 8.5: Command line arguments
The readers can now write a program to list out the environment variables.
There are a lot of environment variables and when you execute the program
you will see that there is a big list of variable being displayed, at present these
variables are not of much importance but you can search the Internet to learn
more about the shell and the environment variables. Some of the simplest
environment variables are those which contain the path of the current working
directory, path of the home folder etc.
8.8 Exercises
1. Write a function using recursion to print numbers from 𝑛 to 0.
2. Write a function using recursion to enter and display a string in reverse and
state whether the string contains any spaces. Don’t use arrays/strings.
3. Write a function using recursion to check if a number 𝑛 is prime. (You
have to check whether 𝑛 is divisible by any number below 𝑛.)
4. Write a function using recursion to enter characters one by one until a
space is encountered. The function should return the depth at which the
space was encountered.
5. Write a function that accepts two matrices and returns the product if they
can be multiplied.
6. Write a program that takes argument from command line and returns the
number of upper case letters used.
Chapter 9
Pointers
Pointers are the most important and most powerful concept of C. An experienced
C programmer can handle pointers easily whereas it makes programming a
nightmare for beginners. The reason is that beginners fail to grasp the concept
of pointers and related fields like dynamic memory allocation etc.
The pointer is another type of variable which stores the address of a variable,
a pointer is a variable that points to the memory location of a variable of a
particular type. The pointer variable can store address of an int, float,
char, structure or even of a pointer variable itself. We can also declare a
pointer with void data type. A pointer variable is declared as:
type *variablename;
The * is what distinguishes a normal variable from a pointer variable. Some
examples for pointer declaration are:
int *mypoint;
float *charpoint;
We know that an integer variable has 2 bytes length, a float has 4 bytes
and a character variable has 1 byte length. The pointer variable for all data
types has 1 byte memory. All that a pointer variable does is that it stores the
address of a variable so it has only 1 byte memory. In C the name of an array is
actually a pointer to the address of the first element of the array. The process
of reading the value stored at a particular memory address in a pointer is called
dereferencing. We have used the & in the scanf(), have you ever wondered
what the symbol stands for, it is used to denote the address of the variable,
suppose you have a normal integer variable called var and you want its address
then we use &var to denote it’s address. It is actually the address of the variable
that we pass to the scanf().
int a=10,b, *point;
point =&a;
b=* point;
In the above code we declared two normal integer variables and a pointer to
integer variable. In the second statement we stored the address of the integer
variable to the pointer variable. The next statement is called dereferencing, the
value stored at the address denoted by point is being retrieved. It is to be
noted that we use the asterix itself to dereference a pointer variable.
45
46 9. Pointers
9.1 Pointer Arithmetic
The pointer variable can be incremented, decremented and value in the pointer
variable can be assigned to another variable. These are the only arithmetic
operations that can be performed on the pointer variables. The pointer of same
data types can be compared.
#include <stdio.h>
int main ()
{
int a=10,* point;
point =&a;
printf("n %d: ",point);
printf("n %d: " ,*point);
printf("n %d: " ,++(* point));
point ++;
printf("n %d: n" ,*point);
return 0;
}
Program 9.1: Pointer Arithmetic
In the above program let’s assume the address of the variable a is 100. In
the first printf statement the address 100 is printed, in the second printf
statement the pointer is dereferenced and the value 10 stored in it is displayed.
In the third statement the value stored at location 100 is incremented and
printed, and finally the point++ increments the address value. The question
is by how much does the address increase? If your answer is that it increases
from 100 to 101 then it’s wrong, the address value in point increases by 2 bytes
because the integer data type is of 2 bytes size. The same is applicable for the
decrement operator also. The statement
printf(‘‘n %d:’’,*point ++);
In this statement the value at location point is dereferenced and then the
address in point is incremented.
9.2 Call By Reference
We have seen that when we pass arguments to functions only copies are passed
and not the real variables themselves, this is called pass by value. Pass by
reference is a method in which we pass the original variables themselves therefore
if the function brings about a change in the value of the variable this value is
reflected in the original variable itself. We know that a function can return only
one value, it can have only one return statement. But we can use the concept
of pass by reference to return more than one value from the function.
#include <stdio.h>
int div(int a,int *rem)
{
int var1;
var1 =*rem;
*rem=a%var1;
return(a/var1);
}
int main ()
9.3 Pointer to Function 47
{
int a=5,b=2,c;
c=div(a,&b);
printf("nQuotient =%d nRemainder =%d n",c,b);
return 0;
}
Program 9.2: Call by reference
In the above program we have defined a function div() such that it returns
the quotient after division of two numbers and the remainder is returned by
call by reference method because the second number to be divided is passed by
reference and the remainder is stored in it. As the second argument we pass
address of the variable b.
9.3 Pointer to Function
We know that functions return values corresponding to the data type of the
function. Functions can also return pointers. In such a case the function decla-
ration will be as below:
data type *function_name(<arguments >);
Obviously the return statement of the function should return an address.
But this is not the pointer to function concept and readers should not confuse
themselves. A pointer to function declaration is as follows:
data type (* function_name)(<arguments >);
Function pointers provide some extremely interesting, efficient and elegant
programming techniques. You can use them to replace switch/if statements.
Function pointers are pointers, i.e. variables, which point to the address of a
function. You must keep in mind, that a running program gets a certain space
in the main memory. Both the executable compiled program code and the
used variables are put inside this memory. Thus a function in the program
code, is like character field, nothing else than an address. It is only important
how your compiler/processor interpret the memory a pointer points to. The
function pointer can be used to store that address and that pointer can be
used to dereference and call the function. A function pointer invokes a function,
passing it zero or more arguments just like a normal function. Function pointers
can be used to simplify code by providing a simple way to select a function to
execute based on run-time values.
#include <stdio.h>
float Plus(float a,float b) // Function to add
{ return a+b; }
float Minus(float a,float b) // Function to minus
{ return a-b; }
float Multiply(float a,float b) // Function to
multiply
{ return a*b; }
float Divide(float a,float b) // Function to divide
{ return a/b; }
// Function with pointer to function as argument
48 9. Pointers
void calculator(float a,float
b,float (* point)(float ,float))
{
float res=point(a,b); // Call using function
pointer
printf("The result is: %f n",res);
}
int main ()
{
calculator (2,5,& Minus);
return 0;
}
Program 9.3: Pointer to function
The & in &Minus is not compulsory, we can write that statement as
calculator (2,5, Minus);
In the above program the function calculator() accepts two floating point
numbers and a pointer to the function Minus(). In the function calculator()
the pointer is used to call the corresponding function and the floating point
numbers are used as arguments of that function and the result is printed. The
function pointer does not increase speed of calling function but it makes a
function similar to a variable and it can be passed to another function as an
argument, it can be assigned to another pointer variable etc. The function can
almost be treated as a normal variable.
9.4 Pointers and Arrays
We have already discussed that the name of an array refers to the memory
location of the first element of the array. The other members are accessed by
incrementing the memory address from there as we saw in pointer arithmetic.
We can also declare an array of pointers which will contain a collection of the
address values.
int num [10] ,*p,a,* parray [10];
p=num; // Valid statement as both contain address
a=p; // Invalid statement
Here the name num references to the location of integer stored in num[0], so
the value of num can be assigned to the pointer variable p. If the argument list of
a function contains a pointer variable of a type, then during function call we can
pass an array of the same type to the function. The use of pointer arguments
instead of arrays can simplify the code, but in order to handle pointers you
should be well versed with it.
Strings are also arrays of characters. We can access strings using pointers
just as we did for a normal array because a string is also a normal array but the
end of a string is indicated by the NULL character 0. We can use this idea to
detect end of a string.
#include <stdio.h>
void readstr(char *msg)
{
int i;
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C
Thats How We C

Recommandé

The C Preprocessor par
The C PreprocessorThe C Preprocessor
The C Preprocessoriuui
3K vues78 diapositives
tutorial.pdf par
tutorial.pdftutorial.pdf
tutorial.pdfSandeepSinha80
82 vues163 diapositives
Notes of 8051 Micro Controller for BCA, MCA, MSC (CS), MSC (IT) & AMIE IEI- b... par
Notes of 8051 Micro Controller for BCA, MCA, MSC (CS), MSC (IT) & AMIE IEI- b...Notes of 8051 Micro Controller for BCA, MCA, MSC (CS), MSC (IT) & AMIE IEI- b...
Notes of 8051 Micro Controller for BCA, MCA, MSC (CS), MSC (IT) & AMIE IEI- b...ssuserd6b1fd
137 vues133 diapositives
Introduction to Programming Using Java v. 7 - David J Eck - Inglês par
Introduction to Programming Using Java v. 7 - David J Eck - InglêsIntroduction to Programming Using Java v. 7 - David J Eck - Inglês
Introduction to Programming Using Java v. 7 - David J Eck - InglêsMarcelo Negreiros
804 vues755 diapositives
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 1 of 5 by... par
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 1 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 1 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 1 of 5 by...ssuserd6b1fd
280 vues100 diapositives
Notes and Description for Xcos Scilab Block Simulation with Suitable Examples... par
Notes and Description for Xcos Scilab Block Simulation with Suitable Examples...Notes and Description for Xcos Scilab Block Simulation with Suitable Examples...
Notes and Description for Xcos Scilab Block Simulation with Suitable Examples...ssuserd6b1fd
1.1K vues152 diapositives

Contenu connexe

Tendances

Java Programming Notes for Beginners by Arun Umrao par
Java Programming Notes for Beginners by Arun UmraoJava Programming Notes for Beginners by Arun Umrao
Java Programming Notes for Beginners by Arun Umraossuserd6b1fd
139 vues74 diapositives
Modlica an introduction by Arun Umrao par
Modlica an introduction by Arun UmraoModlica an introduction by Arun Umrao
Modlica an introduction by Arun Umraossuserd6b1fd
91 vues48 diapositives
c programming par
c programmingc programming
c programmingArun Umrao
6.4K vues150 diapositives
Advanced cardiovascular exercites par
Advanced cardiovascular exercitesAdvanced cardiovascular exercites
Advanced cardiovascular exercitesMaria Lopez
27 vues243 diapositives
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ... par
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...ssuserd6b1fd
171 vues180 diapositives
I do like cfd vol 1 2ed_v2p2 par
I do like cfd vol 1 2ed_v2p2I do like cfd vol 1 2ed_v2p2
I do like cfd vol 1 2ed_v2p2NovoConsult S.A.C
979 vues299 diapositives

Tendances(16)

Java Programming Notes for Beginners by Arun Umrao par ssuserd6b1fd
Java Programming Notes for Beginners by Arun UmraoJava Programming Notes for Beginners by Arun Umrao
Java Programming Notes for Beginners by Arun Umrao
ssuserd6b1fd139 vues
Modlica an introduction by Arun Umrao par ssuserd6b1fd
Modlica an introduction by Arun UmraoModlica an introduction by Arun Umrao
Modlica an introduction by Arun Umrao
ssuserd6b1fd91 vues
Advanced cardiovascular exercites par Maria Lopez
Advanced cardiovascular exercitesAdvanced cardiovascular exercites
Advanced cardiovascular exercites
Maria Lopez27 vues
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ... par ssuserd6b1fd
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
ssuserd6b1fd171 vues
Lecture notes on hybrid systems par AOERA
Lecture notes on hybrid systemsLecture notes on hybrid systems
Lecture notes on hybrid systems
AOERA653 vues
Assembly Codes in C Programmes - A Short Notes by Arun Umrao par ssuserd6b1fd
Assembly Codes in C Programmes - A Short Notes by Arun UmraoAssembly Codes in C Programmes - A Short Notes by Arun Umrao
Assembly Codes in C Programmes - A Short Notes by Arun Umrao
ssuserd6b1fd133 vues
Ric walter (auth.) numerical methods and optimization a consumer guide-sprin... par valentincivil
Ric walter (auth.) numerical methods and optimization  a consumer guide-sprin...Ric walter (auth.) numerical methods and optimization  a consumer guide-sprin...
Ric walter (auth.) numerical methods and optimization a consumer guide-sprin...
valentincivil829 vues
Reading Materials for Operational Research par Derbew Tesfa
Reading Materials for Operational Research Reading Materials for Operational Research
Reading Materials for Operational Research
Derbew Tesfa58 vues
Coding interview preparation par SrinevethaAR
Coding interview preparationCoding interview preparation
Coding interview preparation
SrinevethaAR303 vues

Similaire à Thats How We C

A Practical Introduction To Python Programming par
A Practical Introduction To Python ProgrammingA Practical Introduction To Python Programming
A Practical Introduction To Python ProgrammingNat Rice
10 vues263 diapositives
A practical introduction_to_python_programming_heinold par
A practical introduction_to_python_programming_heinoldA practical introduction_to_python_programming_heinold
A practical introduction_to_python_programming_heinoldthe_matrix
187 vues263 diapositives
A practical introduction_to_python_programming_heinold par
A practical introduction_to_python_programming_heinoldA practical introduction_to_python_programming_heinold
A practical introduction_to_python_programming_heinoldFaruqolayinkaSalako
175 vues263 diapositives
A_Practical_Introduction_to_Python_Programming_Heinold.pdf par
A_Practical_Introduction_to_Python_Programming_Heinold.pdfA_Practical_Introduction_to_Python_Programming_Heinold.pdf
A_Practical_Introduction_to_Python_Programming_Heinold.pdfTariqSaeed80
4 vues263 diapositives
thinkcspy3.pdf par
thinkcspy3.pdfthinkcspy3.pdf
thinkcspy3.pdfssuser244a2a
7 vues421 diapositives
Haltermanpythonbook.pdf par
Haltermanpythonbook.pdfHaltermanpythonbook.pdf
Haltermanpythonbook.pdfnebulaa2
21 vues283 diapositives

Similaire à Thats How We C(20)

A Practical Introduction To Python Programming par Nat Rice
A Practical Introduction To Python ProgrammingA Practical Introduction To Python Programming
A Practical Introduction To Python Programming
Nat Rice10 vues
A practical introduction_to_python_programming_heinold par the_matrix
A practical introduction_to_python_programming_heinoldA practical introduction_to_python_programming_heinold
A practical introduction_to_python_programming_heinold
the_matrix187 vues
A practical introduction_to_python_programming_heinold par FaruqolayinkaSalako
A practical introduction_to_python_programming_heinoldA practical introduction_to_python_programming_heinold
A practical introduction_to_python_programming_heinold
A_Practical_Introduction_to_Python_Programming_Heinold.pdf par TariqSaeed80
A_Practical_Introduction_to_Python_Programming_Heinold.pdfA_Practical_Introduction_to_Python_Programming_Heinold.pdf
A_Practical_Introduction_to_Python_Programming_Heinold.pdf
TariqSaeed804 vues
Haltermanpythonbook.pdf par nebulaa2
Haltermanpythonbook.pdfHaltermanpythonbook.pdf
Haltermanpythonbook.pdf
nebulaa221 vues
Algorithmic Problem Solving with Python.pdf par Emily Smith
Algorithmic Problem Solving with Python.pdfAlgorithmic Problem Solving with Python.pdf
Algorithmic Problem Solving with Python.pdf
Emily Smith14 vues
javanotes5.pdf par kmspega
javanotes5.pdfjavanotes5.pdf
javanotes5.pdf
kmspega62 vues
Francois fleuret -_c++_lecture_notes par hamza239523
Francois fleuret -_c++_lecture_notesFrancois fleuret -_c++_lecture_notes
Francois fleuret -_c++_lecture_notes
hamza239523205 vues
Python_Programming_and_Numerical_Methods_A_Guide_for_Engineers_and.pdf par jankoabel2022
Python_Programming_and_Numerical_Methods_A_Guide_for_Engineers_and.pdfPython_Programming_and_Numerical_Methods_A_Guide_for_Engineers_and.pdf
Python_Programming_and_Numerical_Methods_A_Guide_for_Engineers_and.pdf
jankoabel20223 vues

Dernier

JRN 362 - Lecture Twenty-Two par
JRN 362 - Lecture Twenty-TwoJRN 362 - Lecture Twenty-Two
JRN 362 - Lecture Twenty-TwoRich Hanley
39 vues157 diapositives
11.30.23A Poverty and Inequality in America.pptx par
11.30.23A Poverty and Inequality in America.pptx11.30.23A Poverty and Inequality in America.pptx
11.30.23A Poverty and Inequality in America.pptxmary850239
228 vues18 diapositives
Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab... par
Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab...Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab...
Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab...RAHUL PAL
45 vues26 diapositives
Education of marginalized and socially disadvantages segments.pptx par
Education of marginalized and socially disadvantages segments.pptxEducation of marginalized and socially disadvantages segments.pptx
Education of marginalized and socially disadvantages segments.pptxGarimaBhati5
52 vues36 diapositives
NodeJS and ExpressJS.pdf par
NodeJS and ExpressJS.pdfNodeJS and ExpressJS.pdf
NodeJS and ExpressJS.pdfArthyR3
53 vues17 diapositives
Gross Anatomy of the Liver par
Gross Anatomy of the LiverGross Anatomy of the Liver
Gross Anatomy of the Liverobaje godwin sunday
100 vues12 diapositives

Dernier(20)

JRN 362 - Lecture Twenty-Two par Rich Hanley
JRN 362 - Lecture Twenty-TwoJRN 362 - Lecture Twenty-Two
JRN 362 - Lecture Twenty-Two
Rich Hanley39 vues
11.30.23A Poverty and Inequality in America.pptx par mary850239
11.30.23A Poverty and Inequality in America.pptx11.30.23A Poverty and Inequality in America.pptx
11.30.23A Poverty and Inequality in America.pptx
mary850239228 vues
Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab... par RAHUL PAL
Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab...Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab...
Research Methodology (M. Pharm, IIIrd Sem.)_UNIT_IV_CPCSEA Guidelines for Lab...
RAHUL PAL45 vues
Education of marginalized and socially disadvantages segments.pptx par GarimaBhati5
Education of marginalized and socially disadvantages segments.pptxEducation of marginalized and socially disadvantages segments.pptx
Education of marginalized and socially disadvantages segments.pptx
GarimaBhati552 vues
NodeJS and ExpressJS.pdf par ArthyR3
NodeJS and ExpressJS.pdfNodeJS and ExpressJS.pdf
NodeJS and ExpressJS.pdf
ArthyR353 vues
GSoC 2024 .pdf par ShabNaz2
GSoC 2024 .pdfGSoC 2024 .pdf
GSoC 2024 .pdf
ShabNaz245 vues
OOPs - JAVA Quick Reference.pdf par ArthyR3
OOPs - JAVA Quick Reference.pdfOOPs - JAVA Quick Reference.pdf
OOPs - JAVA Quick Reference.pdf
ArthyR376 vues
Introduction to AERO Supply Chain - #BEAERO Trainning program par Guennoun Wajih
Introduction to AERO Supply Chain  - #BEAERO Trainning programIntroduction to AERO Supply Chain  - #BEAERO Trainning program
Introduction to AERO Supply Chain - #BEAERO Trainning program
Guennoun Wajih135 vues
JRN 362 - Lecture Twenty-Three (Epilogue) par Rich Hanley
JRN 362 - Lecture Twenty-Three (Epilogue)JRN 362 - Lecture Twenty-Three (Epilogue)
JRN 362 - Lecture Twenty-Three (Epilogue)
Rich Hanley44 vues
Creative Restart 2023: Christophe Wechsler - From the Inside Out: Cultivating... par Taste
Creative Restart 2023: Christophe Wechsler - From the Inside Out: Cultivating...Creative Restart 2023: Christophe Wechsler - From the Inside Out: Cultivating...
Creative Restart 2023: Christophe Wechsler - From the Inside Out: Cultivating...
Taste39 vues
Guidelines & Identification of Early Sepsis DR. NN CHAVAN 02122023.pptx par Niranjan Chavan
Guidelines & Identification of Early Sepsis DR. NN CHAVAN 02122023.pptxGuidelines & Identification of Early Sepsis DR. NN CHAVAN 02122023.pptx
Guidelines & Identification of Early Sepsis DR. NN CHAVAN 02122023.pptx
Niranjan Chavan43 vues
11.21.23 Economic Precarity and Global Economic Forces.pptx par mary850239
11.21.23 Economic Precarity and Global Economic Forces.pptx11.21.23 Economic Precarity and Global Economic Forces.pptx
11.21.23 Economic Precarity and Global Economic Forces.pptx
mary85023994 vues
Interaction of microorganisms with vascular plants.pptx par MicrobiologyMicro
Interaction of microorganisms with vascular plants.pptxInteraction of microorganisms with vascular plants.pptx
Interaction of microorganisms with vascular plants.pptx
UNIT NO 13 ORGANISMS AND POPULATION.pptx par Madhuri Bhande
UNIT NO 13 ORGANISMS AND POPULATION.pptxUNIT NO 13 ORGANISMS AND POPULATION.pptx
UNIT NO 13 ORGANISMS AND POPULATION.pptx
Madhuri Bhande48 vues
ANGULARJS.pdf par ArthyR3
ANGULARJS.pdfANGULARJS.pdf
ANGULARJS.pdf
ArthyR354 vues

Thats How We C

  • 2. Thats How We C Vineeth Kartha
  • 4. This work is licensed under the Creative Commons Attribution-NonCommercial- ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. The design and artwork on the cover page of this book was done by Mr. Vishnu Sivadas, and the artwork from openclipart.org was used. www.openclipart.org. This book has been typeset in LATEX You are free to share, copy or distribute this book
  • 6. Dedicated to my Parents & My dear friends of GECB EEE(2008-2012) A Tribute to Dennis M. Ritchie (1941-2011)
  • 8. Contents Preface xiii 1 Introduction 1 2 Basic Concepts 4 2.1 Assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 Compilers and Compiled Language . . . . . . . . . . . . . . . . . 5 2.3 Structure of a Compiler . . . . . . . . . . . . . . . . . . . . . . . 5 2.4 Interpreters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.5 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3 Identifiers and Data Types 9 3.1 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.1.1 Keywords in C . . . . . . . . . . . . . . . . . . . . . . . . 9 3.2 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3 The Basic Data Types . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3.1 Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3.2 Floating Point . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3.3 Character . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.4 The Data Type Specifiers . . . . . . . . . . . . . . . . . . . . . . 12 3.4.1 signed or unsigned . . . . . . . . . . . . . . . . . . . . . 12 3.4.2 long or short . . . . . . . . . . . . . . . . . . . . . . . . 12 3.4.3 const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.4.4 volatile . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.5 The Storage Class . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.5.1 Automatic variables (auto) . . . . . . . . . . . . . . . . . 12 3.5.2 Static variables (static) . . . . . . . . . . . . . . . . . . 13 3.5.3 External variables (extern) . . . . . . . . . . . . . . . . . 13 3.5.4 Register variables (register) . . . . . . . . . . . . . . . . 13 3.6 User Defined Data Types . . . . . . . . . . . . . . . . . . . . . . 13 3.6.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.6.2 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.6.3 Union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.6.4 Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.6.5 Typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.6.6 Typecasting . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.7 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4 Input/Output Operations 16 4.1 The gets() and puts() . . . . . . . . . . . . . . . . . . . . . . . 17 4.2 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 vii
  • 9. viii Contents 5 Operators 19 5.1 Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.1.1 Arithmetic Operators . . . . . . . . . . . . . . . . . . . . 19 5.1.2 Relational Operators . . . . . . . . . . . . . . . . . . . . . 20 5.1.3 Logical Operators . . . . . . . . . . . . . . . . . . . . . . 20 5.1.4 Assignment Operators . . . . . . . . . . . . . . . . . . . . 20 5.1.5 Bitwise Operators . . . . . . . . . . . . . . . . . . . . . . 20 5.2 Unary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.2.1 Unary plus and minus . . . . . . . . . . . . . . . . . . . . 22 5.2.2 Increment and Decrement Operators . . . . . . . . . . . . 22 5.3 Ternary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.3.1 Conditional Operator . . . . . . . . . . . . . . . . . . . . 23 5.3.2 Precedence and Associativity . . . . . . . . . . . . . . . . 23 5.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 6 Control Statements 25 6.1 if...else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 6.1.1 Nested if else . . . . . . . . . . . . . . . . . . . . . . . . 26 6.2 switch case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 6.3 Conditional Operator . . . . . . . . . . . . . . . . . . . . . . . . 27 6.4 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 6.4.1 Entry Controlled Loops . . . . . . . . . . . . . . . . . . . 28 6.4.2 Exit Controlled Loops . . . . . . . . . . . . . . . . . . . . 29 6.4.3 The break Statement . . . . . . . . . . . . . . . . . . . . 29 6.4.4 The continue Statement . . . . . . . . . . . . . . . . . . 30 6.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 7 Structured Data Types 31 7.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 7.2 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 7.2.1 Nested Structures . . . . . . . . . . . . . . . . . . . . . . 33 7.2.2 Unnamed Structures . . . . . . . . . . . . . . . . . . . . . 34 7.3 Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 7.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 8 Functions 36 8.1 Passing Values to Arguments . . . . . . . . . . . . . . . . . . . . 37 8.1.1 Pass by Value . . . . . . . . . . . . . . . . . . . . . . . . . 38 8.1.2 Pass by Reference . . . . . . . . . . . . . . . . . . . . . . 38 8.2 The return Statement . . . . . . . . . . . . . . . . . . . . . . . . 38 8.3 Functions with Variable Argument List . . . . . . . . . . . . . . 38 8.4 Scope of a Function . . . . . . . . . . . . . . . . . . . . . . . . . 40 8.5 Arrays as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . 40 8.6 Recursive Functions . . . . . . . . . . . . . . . . . . . . . . . . . 41 8.7 Command Line Arguments . . . . . . . . . . . . . . . . . . . . . 43 8.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 9 Pointers 45 9.1 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . 46 9.2 Call By Reference . . . . . . . . . . . . . . . . . . . . . . . . . . 46 9.3 Pointer to Function . . . . . . . . . . . . . . . . . . . . . . . . . . 47 9.4 Pointers and Arrays . . . . . . . . . . . . . . . . . . . . . . . . . 48 9.5 Structure Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . 49 9.6 Dynamic Memory Allocation . . . . . . . . . . . . . . . . . . . . 50 9.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
  • 10. Contents ix 10 Advanced Data Structures 53 10.1 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 10.2 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 10.2.1 Implementation of Queues . . . . . . . . . . . . . . . . . . 58 11 File Handling in C 62 11.1 File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 11.1.1 Reading from a file . . . . . . . . . . . . . . . . . . . . . . 63 11.1.2 Writing to Files . . . . . . . . . . . . . . . . . . . . . . . . 64 11.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 12 Sorting Algorithms 66 12.1 Bubble Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 12.2 Selection Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 12.3 Insertion Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 13 The Preprocessor 68 13.1 #define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 13.2 Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 13.3 #undef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 13.4 #include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 13.5 #if—Conditional Inclusion . . . . . . . . . . . . . . . . . . . . . 70 14 Numerical Techniques: A Brief Introduction 71 14.1 Solution of Linear Equations . . . . . . . . . . . . . . . . . . . . 71 14.1.1 Gauss Elimination . . . . . . . . . . . . . . . . . . . . . . 71 14.1.2 Gauss Jordan . . . . . . . . . . . . . . . . . . . . . . . . . 73 14.2 Solving Transcendental Equations . . . . . . . . . . . . . . . . . . 75 14.2.1 Bisection Method . . . . . . . . . . . . . . . . . . . . . . . 75 14.2.2 Newton Raphson Method . . . . . . . . . . . . . . . . . . 77 14.3 Numerical Integration . . . . . . . . . . . . . . . . . . . . . . . . 79 14.3.1 Trapezoidal Method . . . . . . . . . . . . . . . . . . . . . 79 14.3.2 Simpson’s 1/3𝑟𝑑 Rule . . . . . . . . . . . . . . . . . . . . 80 14.4 Numerical Solution of Ordinary and Partial Differential Equations 82 14.4.1 Euler’s Method . . . . . . . . . . . . . . . . . . . . . . . . 82 14.4.2 Runge-Kutta Method . . . . . . . . . . . . . . . . . . . . 83 14.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 A ISO C Headers and Some Functions 86 B GCC 89 Bibliography 90
  • 11. List of Tables 3.1 List of keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2 int data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3 float data type . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4.1 Conversion Characters . . . . . . . . . . . . . . . . . . . . . . . . 17 4.2 Escape Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.1 Bitwise AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.2 Bitwise OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.3 Bitwise XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.4 Bitwise NOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.5 Precedence and Associativity . . . . . . . . . . . . . . . . . . . . 24 List of Figures 2.1 Life Cycle of a Program . . . . . . . . . . . . . . . . . . . . . . . 7 3.1 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 8.1 Tower of Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 10.1 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 10.2 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 x
  • 12. List of Programs 4.1 Standard I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.2 gets() and puts() . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.1 Increment and decrement operators . . . . . . . . . . . . . . . . . 22 5.2 Find the output . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 6.1 Largest of two numbers . . . . . . . . . . . . . . . . . . . . . . . 25 6.2 switch case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 6.3 for loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 6.4 while loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 7.1 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 8.1 Area of Square . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 8.2 Variable argument list . . . . . . . . . . . . . . . . . . . . . . . . 39 8.3 Arrays as arguments . . . . . . . . . . . . . . . . . . . . . . . . . 41 8.4 Factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 8.5 Command line arguments . . . . . . . . . . . . . . . . . . . . . . 44 9.1 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . 46 9.2 Call by reference . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 9.3 Pointer to function . . . . . . . . . . . . . . . . . . . . . . . . . . 47 9.4 Detect end of string . . . . . . . . . . . . . . . . . . . . . . . . . 48 9.5 Structure Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . 49 9.6 Dynamic Memory Allocation . . . . . . . . . . . . . . . . . . . . 51 10.1 Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 10.2 Pointer Implementation of Stack . . . . . . . . . . . . . . . . . . 55 10.3 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 11.1 Reading from a file . . . . . . . . . . . . . . . . . . . . . . . . . . 63 11.2 Writing to a file . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 14.1 Gauss Elimination . . . . . . . . . . . . . . . . . . . . . . . . . . 72 14.2 Gauss Jordan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 14.3 Determinant of a Matrix . . . . . . . . . . . . . . . . . . . . . . . 74 14.4 Bisection Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 14.5 Newton Raphson Method . . . . . . . . . . . . . . . . . . . . . . 78 14.6 Trapezoidal Method . . . . . . . . . . . . . . . . . . . . . . . . . 80 14.7 Simpson’s 1/3𝑟𝑑 Rule . . . . . . . . . . . . . . . . . . . . . . . . . 81 14.8 Euler’s Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 14.9 Runge-Kutta Method . . . . . . . . . . . . . . . . . . . . . . . . 84 xi
  • 14. Preface Programming can be a nightmare for many, the reason is that they don’t have an understanding of what they are handling. Programming can be made in- teresting and fun. It is actually even more interesting and easy than all other sciences because all we need to do an experiment with a programming language is the computer and software. Thanks to the free software movement, almost all program compilers and IDEs are available as free software. I do not claim this book to be a masterpiece compared to many other books that are avail- able today, but I do know that it will help someone someday. I hope this book will be of help to at least some of the readers. I’m open to all criticisms and appreciations. I wrote this book using free software tools—Open Office Writer, Open Office Draw, Gimp and LATEX. All the example programs have been tested using gcc- 4.4.5. This book is being released under the Creative Commons License. I would like to express my gratitude to Mr. Vishnu Sivadas for his sincere effort in designing the cover page, proof reading the book and typesetting it. Finally I request the readers to pardon me for any errors that might have crawled in irrespective of all efforts to avoid them. You can contact me at vineeth.kartha@gmail.com. Vineeth Kartha xiii
  • 16. Chapter 1 Introduction “Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.” Donald E. Knuth Almost everyone has his own notion about programming. For most of the beginners programming is a herculean task which is accomplished only by geeks and they look at and approach the programming languages with such an idea and as a result they fail to enjoy it. Before we start we should have a clear answer to two basic questions. 1. What is programming? 2. What is software? Let’s answer the first question. We spent a lot of money and time in buying our computers. We take care in choosing the processor, the accessories, the memory capacity and all other such aspects, but despite all this our computers are the stupidest things in the world. We have to tell it very precisely what, when and how to do things, our computers cannot think. The only advantage is that it acts fast and it is a very obedient slave. So it will do exactly (it will even destroy itself if your command says so). So the process of telling our computers what to do is called programming. Programming is also explained as the breaking of a task into small steps. Programming is actually a step by step approach in solving a larger problem. Suppose we are given the task to sort out students in a class according to their marks, we look for the top mark first and we proceed so on till we have sorted out each student, this is programming, our brain has been programmed through our experiences and we act accordingly. Unfortunately our computers aren’t smart enough. So we have to tell it. The second question, what is software? Most often the answer will be, a program executed on the computer! A program is merely a set of instructions that a computer executes. Software is much more than that. Software is the collection of 1. Instructions that we call as programs 1
  • 17. 2 1. Introduction 2. Data structures that we used to handle data in the program 3. Documentation that includes all hard copy and soft copies that describes the use and operation of the program Today all software can be classified in 7 domains: 1. System Software: A collections of programs written to service other programs, some process deterministic data (text editors, compilers etc.), others process indeterministic data (OS, drivers etc.). It is characterized by heavy interaction with hardware. It requires principles of scheduling, resource sharing, memory management, complex data structures etc. 2. Application Software: Stand alone programs that solve a specific busi- ness need. Applications in this area process business or technical data in a way that facilitates business operation or management/technical decision making used to control business in real time. 3. Engineering/Scientific Software: These are tools that help engineers to analyse and interpret data obtained from experiments. 4. Embedded Software: This is a software that resides within a product or system and is used to implement and control feature and function for end user. 5. Product-line Software: Designed to provide specific capability for use by many different customers. 6. Web Applications: These are network centric software, category spans a wide array of applications found on the internet today. 7. Artificial Intelligence: Makes non-numerical algorithms to solve com- plex problems that are not amenable to computation or straight forward analysis. Applications within this area include robotics, expert system, pattern recognition, artificial neural networks, game playing etc. Now, as we are clear about what programming and software is, let’s see how we can become a good programmer. To be a good programmer you should be able to think in a simple and unnatural way. The characteristics of a good programmer are: a. Logical thinking b. Patience c. Perceptive d. Faces a challenge with joy Programming is something to have fun, tackle a problem head on and get involved in it until solved. That will make you the best programmer. Also try to learn a few languages through and out, it’s always better to know one language completely than to know several languages and yet not being able to use all it’s features. By now the reader should have some idea about whether programming is his/her cup of tea. If it is, let’s move on and learn one of the most beautiful and mostly used programming language, C.
  • 18. 3 In the early days of computer development, there were two levels of program- ming, the machine level and the assembly level. Programming and debugging using these two methods was tedious and time consuming. The programmer had to manage the hardware components himself. He had to consider every aspect of the hardware before he can write a program. Later on when computers became more common, another class of languages called high level languages developed. Fortran, Cobol, Basic, C were all such high level languages. These languages could be written in the human under- standable form. These languages made the underlying hardware invisible to the programmers and made the syntax easier. It was in the 1970s along with the development of UNIX that the concept of system programming languages, having attributes of both “low level” and “high level” languages also developed. System programming languages have the advantages of high level languages and also help in taking control of underlying hardware itself. C was developed as a system programming language by Brian W. Kerning- han and Dennis M. Ritchie at Bell Labs. Two earlier versions were named A and B. Though C was developed for implementing system software, later on it was used for application software and soon C became a general purpose language. C can be used in many places where assembly language played major role. Today even microcontroller programming is done in C. The first version which is known as K & R C (named after it’s inventors) remained a standard till 1983 when “The American National Standards Insti- tute” formed a committee to establish a standard specification of C. In 1989, the standard was ratified as ANSI X3. 159-1989 “Programming Language C”. This version of the language is often known as ANSI C, Standard C or some- times C89. In 1990 ANSI C was adopted by ISO as ISO/IEC 9899:1990 which is called C90. In the late 1990s again revision was made incorporating inline functions, data types like long long int and complex to represent complex numbers, variable length arrays and also support for one line comment. C has directly and indirectly influenced many of the major languages avail- able today. So learning C can make you master of almost all programming languages. The concepts are almost the same. References 1. “The C Programming Language”, K & R. 2. “Development of C Language”, Dennis M. Ritchie. 3. “Software Engineering: A Practitioner’s Approach”, Roger S. Pressman.
  • 19. Chapter 2 Basic Concepts Let us look into detail a few points mentioned in the previous chapter. We learned that a program can be written in machine language which is nothing but just 1s and 0s, assembly language where we use shorter words but still lengthy steps to do even the simplest task. For both these two methods the programmer should thoroughly know the architecture1 of the microprocessor they are programming on. These programs will be platform dependent, i.e., a program written for the Intel Pentium IV processor will not work on a Core 2 Duo or the latest i7 processors. Then we have the high level programming which is much easier to learn and practice and it helps in making faster, platform dependent programs. Let us look at a simple statement to add 2 numbers. In most high level languages we will write c = a+b; where result of a+b is stored in c. This is quite well understood even by a person who doesn’t know programming. Now let’s look at the assembly code for an Intel 8085 processor. MVI A, value ADD B The statements are almost understood (ADD B tells us that we are adding value in B). But we don’t really understand what is being added. Here one of the number should be in the accumulator and the value in register B should be added to it. This might seem confusing to those who are new to assembly programming and this itself is the disadvantage of assembly programming. The machine code will contain a series of 1s and 0s which is not possible to by-heart and so we see how high level languages made programming easy. But there is a catch in that, machines understand only machine code, and, this is the lowest level at which a program can be written as it is directly understood by the machine. But we have just seen the practical difficulties associated with it. 1It is the conceptual design and fundamental operational structure of a computer system, it’s a functional description of requirements and design implementation for various parts of a computer. 4
  • 20. 2.1 Assembler 5 Both assembly language and high level language programs need to be con- verted to machine code before they can be executed. 2.1 Assembler A utility program called assembler translates the assembly language codes to machine code. It creates an object code as it’s output which can be executed by the machine. The object code generated will be specific to each micropro- cessor, or microcontroller. There are various assemblers like TASM, NASM etc. Though studying assembly language is difficult, learning it gets you more closer to your hardware. And also C is a system level programming language and so C has several features to include assembly programs of which we will see later on. When we deal with translation of high level languages to machine code, we come across two terms, compiled and interpreted languages. 2.2 Compilers and Compiled Language Compilers itself are programs that transform a program in high level language to an executable program. C is defined to be a compiled language that means the source code is given to a compiler which converts it to the executable form. Early compilers were written in assembly language. Some compilers gener- ate an object code (executable file) that can run on various platforms. Such a compiler is called cross-compiler. Later on compilers were written in the respec- tive languages itself. It was called self hosting compiling and was first created for LISP at MIT in 1962. But then arouse the ‘chicken & egg problem’. How can we have a chicken without an egg and how can we have an egg without a chicken? Suppose we have written a compiler for language X in X itself then how will we compile it first? Most often an interpreter or compiler written in Y is used first. This method is called bootstrapping. The advantages of bootstrapping are 1. It’s a non-trivial test of language being compiled. 2. Compiler developers need to know only that particular language. 2.3 Structure of a Compiler A compiler consists of → Front End: Where it checks the language semantics, displays errors and generates the IR (Intermediate Representation). → Middle End: Here code is optimized, useless code is removed and con- stants are identified and propagated. → Back End: Here finally the IR is converted to assembly code.
  • 21. 6 2. Basic Concepts 2.4 Interpreters These are also programs used to convert source code to object code. It may be a program 1. that executes instructions directly 2. translates source code into some efficient intermediate representation and immediately executes this 3. expilcitly executes stored precompiled code made by a compiler The most commonly used compilers for C are CC (C Compiler) and GCC (GNU Compiler Collection). These two are used in Unix and Linux operating systems. ∗ mingw32 is an extension to GCC that does cross compilation. ∗ TURBO C is a compiler for Windows. TURBO C is not only a compiler but an Integrated Development Envi- ronment. Now let’s move on to the language itself. We will first have a look at the basic program. #include <stdio.h> int main () { printf("Hello World"); // Prints Hello World return 0; } The first line of the program, the #include is called the preprocessor and stdio.h is called header file. Header files are files that contain some predefined functions, in our program the printf() is used to print a text Hello World on the screen and this function is defined in the header file stdio.h. A header file is different from a library file and most often people confuse them. Header files merely contain declaration of functions but the library functions contain the actual implementation of the functions. Library files are binary files. ∗ Another feature of the C program is the function main(). Anything that has to be executed should lie in the main(). ∗ Each and every instruction in the program is called statements and state- ments should terminate with a semicolon (;). ∗ You might have noticed a sentence starting with //. This is called com- ments. Comments are used for easy understanding of the code and for writing explanations on the code. A commented part will not be executed by the compiler, so this feature can be used to deactivate a certain part of the code than deleting it. Comments are of two types, a. Single line: It starts with //(two forward slashes), and it should lie in one line. b. Multi-line: It starts with /* followed by multiple lines of comments and it should be terminated by */.
  • 22. 2.4 Interpreters 7 ∗ The statements in main() are one block of statements as such. It should be contained within opening and closing braces {}. ∗ And finally we have the return 0; statement. This statement tells the compiler that on end of the program the number zero should be returned to the operating system by the main(). These return statements are quite useful in proper termination of programs especially when a program crashes. This statement will be explained in detail in the chapter on functions. Now we have seen some common features of a C program. We have just scratched the surface of a vast topic. We will see in detail all these concepts in the coming chapters. The life cycle of a program is shown in Figure 2.1. Figure 2.1: Life Cycle of a Program Now we will see how to convert our Hello World program to an executable. Open notepad and save the above program as hello.c. Then open the ‘Terminal’ in ‘Applications’ and type cc hello.c Make sure you were in the same folder as the hello.c file. Now type ./a.out You should see Hello World on your screen or else check the error messages and check your program. a.out is the output file generated. In a TURBO C compiler, on the menu bar there will be compile command and a run command. Another point for TURBO C users is that the output screen will not be visible because the program executed and terminated. So to hold the output for some time, before the return 0; insert a getch();, now the screen will wait till a key on keyboard is pressed. Again for cc and gcc we can name the output file by any name we want. For that compile as follows gcc -o name file.c Now to execute you type ./name The switch -o means output. There are several more switches, see appendix for more details on GCC.
  • 23. 8 2. Basic Concepts Now the reader must have had an idea about the basic requirements and procedures in making a program. 2.5 Exercise 1. Write a short note on the life cycle of a program. 2. Write a brief note on C programming. 3. Write short notes on compiled and interpreted languages with example. 4. Write advantages of interpreted languages. 5. What is bootstrapping? References 1. “Microprocessor and its Applications”, B. Ram. 2. “Microprocessor and its Applications”, Gaonkar. 3. K & R C. 4. “C Programming in Unix”, John Vally.
  • 24. Chapter 3 Identifiers and Data Types 3.1 Identifiers Throughout our program we will have to use variables to store different types of data. Variables are like containers that contain a value assigned to it, we can use this variable name instead of that particular value throughout the program depending on it’s visibility1 . There are certain rules to be remembered while naming variables: ∙ The name should start with an alphabet. ∙ The name should not be any reserved keywords like int, float, volatile etc. ∙ The names are case sensitive. AVG and avg are different variables. ∙ The name should not contain special characters like $, #, ! but it can contain (underscores). ∙ The name can contain alphabets from a–z, A–Z and 0–9. ∙ The name should not start with a number. ∙ The name should not contain spaces. ∙ The name can start with an underscore but usually such variables are used by the system. So it is better to avoid such a situation. When naming a variable it is always advisable to ∙ Name the variable depending on what it represents. ∙ Keep them as short as you can but they should be understandable about what they represent. 3.1.1 Keywords in C Table 3.1 shows the list of keywords in C. 1A variable can be made available throughout the program or only in a particular part of the code. We will discuss in detail about this in the coming chapters. 9
  • 25. 10 3. Identifiers and Data Types auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while Table 3.1: List of keywords 3.2 Data Types Data types in C can be classified as shown in Figure 3.1 below. Figure 3.1: Data types 3.3 The Basic Data Types 3.3.1 Integer An integer is a numeric item that can contain a positive or negative whole number. int varname; We can also declare many variables in a single line and even initialize their values. int var1 , var2 , var3 =5; When an integer data type is declared the compiler allocates 2 or 4 bytes of space, depending on the operating system. The Unix and Linux environments
  • 26. 3.3 The Basic Data Types 11 provide a 4 byte memory whereas it is 2 bytes long in the MS-DOS environment. Type modifiers can be used to get a desired size irrespective of the OS. Usually an integer can contain a value between −32, 768 to 32,767. We can use the type modifier unsigned to limit the range to only the positive side. The following table shows the size and limit of the int data type with different type modifiers. Declared Length in bytes Value Range int 2 or 4 At least −32, 768 to 32,767 long int 4 −2, 147, 483, 647 to 2,147,483,648 short int 2 −32, 768 to 32,767 unsigned int 2 or 4 At least 0 to 65,535 unsigned short 2 0 to 65,535 unsigned long 4 0 to 4,294,967,295 Table 3.2: int data type 3.3.2 Floating Point A floating point is a class of numeric variables that allow the storage of fractions and exponents to very precise values. A floating point number has a sign, an integer part and a fractional or exponential part. float var1 , var2 =1.2; E.g. 3.2435𝐸 + 03 is the same as 3243.5 Normally floating point number are 4 bytes long, the data type double can be used to make an 8 byte long floating point number. The floating point numbers can be set with the precision of how many digits to be displayed after the decimal point. Declared Length in bytes Limits of positive values float 4 8.43𝐸 − 37 to 3.37𝐸 + 38 double 8 2.225074𝐸 − 308 to 1.797693𝐸 + 308 long double 10 2.225074𝐸 − 308 to 1.797693𝐸 + 308 Table 3.3: float data type The float data type allows signed values, so using unsigned along with float or double will cause a compiler error. 3.3.3 Character A character is a single byte containing any character in ASCII code. It can be alphabets, numbers2 , special characters, newline, form feed etc. A char data type occupies one byte of memory. They are stored in their ASCII form. char a, b=‘c’, c=‘1’; 2We can represent numbers with the char data type but we cannot treat them as numbers and cannot be used for calculations.
  • 27. 12 3. Identifiers and Data Types A character string can be declared only as an array. char a[10]; These data types can be further modified using the data type modifiers and storage class specifiers. 3.4 The Data Type Specifiers 3.4.1 signed or unsigned unsigned data items are used for positive values. But signed data items can have values ranging from a minimum negative value to a maximum positive value. 3.4.2 long or short The short type is used for saving memory. It has half length of long type. 3.4.3 const The keyword const is used along with a variable name to make it a constant. Throughout the scope of the variable it’s value will remain a constant and any attempt to modify the value during runtime will result in an error. 3.4.4 volatile When a variable is declared as volatile, we are telling the compiler that the value of the variable might be changed at any time—without any action being taken by the code the compiler finds nearby. 3.5 The Storage Class The storage class specifier specifies the segments of the program where the variable is recognized, and how long the storage of the value of variable will last. The storage class specifiers are: 3.5.1 Automatic variables (auto) This is the storage class that a compiler uses by default. A variable declared with auto as the storage specifier is stored in the memory and it is local to the function in which it is declared. Auto variables declared in different functions even though having the same name are independent. The life cycle of such variables are till the function which contains them are executed. auto int a;
  • 28. 3.6 User Defined Data Types 13 3.5.2 Static variables (static) These variable contain the value zero by default when created or we can say that they are initialized with zero, unless we give a value. These variables are local to the function but they exist till termination of the program. So the value of the static variable unlike the auto variable is not lost once the function is over, it exists till the end of the program. And so if the function is called for a second time somewhere else in the program then the variable uses the previously stored value. Such variables can be used as counters. static int a; 3.5.3 External variables (extern) The scope of such variables are global, i.e., they are available all over the pro- gram. Sometimes a single program may contain several files linked, a variable with storage specifier extern is available everywhere. So it is accessible by all the functions in the program. If a function contains a local variable with the same name as an extern variable then in the function preference will go first to the local variable. This is a point to be kept in mind. extern int a; 3.5.4 Register variables (register) Register variables are similar to auto variables, the only difference is that the auto variables are stored in the memory whereas the register variables are stored in the registers of the CPU. We use the register variables because the CPU registers respond much faster than the memory. Register variables maybe of 2 or 4 bytes and so most suitable for integer and character data types, also the CPU registers are needed for other processes of the system so they should be used only when necessary. We should not use too many register variables. register int a; 3.6 User Defined Data Types 3.6.1 Arrays Arrays are a collection of the same data type. There are one-dimensional and multi-dimensional arrays in C. Eg. a character array can be used to store a word, sentence or even a paragraph depending upon the size of the array. int num [20]; This is an array with space for 20 integers. The first element of an array is located at num[0], the next one at num[1] and so on. The last element is at num[19]. In general, an array of size 𝑛 has first element at arrayname[0] and last element at arrayname[n-1]. We can create arrays for any data type, even
  • 29. 14 3. Identifiers and Data Types for the user defined data types that we will see shortly. A multi-dimensional array can be considered as an array of arrays. We can represent a matrix as a two-dimensional array. For a character array of size 𝑛, we can store only 𝑛 − 2 characters because the last ((𝑛−1)𝑡ℎ ) position is occupied by the null character 0 which represents the termination of the string. 3.6.2 Structure An array can contain only values of same data type. Suppose we want to group the details of a student like roll number, name, marks, rank etc., we have to create a structure. A structure can be considered as a group of different data types. We will study in detail about structures and unions in a later chapter. 3.6.3 Union Union is similar to structure . The only difference is that a structure occupies a memory equivalent to the sum of lengths of all elements present in it whereas the size of a union is equal to the size of the largest element present in it. 3.6.4 Enumerations Enumerations are nothing but just assigning names to numbers. enum{sun ,mon ,tue ,wed ,thur ,fri ,sat} With the above declaration we can use sun to represent 0, mon to represent 1 and so on. We can also change the values. enum{sun=1,mon ,tue ,wed ,thur ,fri ,sat} Then the numbering starts from 1 and goes on increasing by 1. 3.6.5 Typedef Typedef cannot be considered as a pure data type because all it does is to rename an existing data type to a new one. Eg. typedef int number; typedef char name [10]; Now we can use number as keyword to declare integer data types and name to declare character arrays of size 10. 3.6.6 Typecasting Typecasting is making a variable of one type, such as a float, act like another type, an int, for one single operation. To typecast something, simply put the type of variable you want the actual variable to act as inside parantheses in front of the actual variable. (char)a will make ‘a’ function as a char.
  • 30. 3.7 Exercise 15 There is explicit and implicit typecasting. In implicit typecasting (type conversion) the compiler converts one data type to another where ever needed. In explicit typecasting we have to tell the compiler to typecast a variable. int a=10; float b=2.5,c; (char) a; // explicit c=a/b; // here a is implicitly converted to float 3.7 Exercise 1. Identify which of the variable names are illegal and explain the reason. (a) $num (b) 12phone (c) avg2 (d) date-of-birth (e) time (f) my,file (g) break (h) default 2. What are data types? How can they be classified? 3. char is often treated as an integer type. Why is it so? 4. What are the advantages and disadvantages of floating point numbers over integers? 5. Differentiate between a structure and an array.
  • 31. Chapter 4 Input/Output Operations Most earlier programming languages had poor support for I/O. The designers of C overcame this problem by having I/O operations done using library functions, so that program designers can have tailored I/O. As C has evolved, a library package known as the ‘Standard I/O Library’ or stdio, has evolved with it and has proved to be both flexible and portable. This package has now become part of the Standard. In C everything is treated as a stream of bytes, whether it is a file or the standard input or output. The file I/O has been reserved for a later chapter. Now let’s see the basic Standard I/O. printf() is the command that tells the compiler to print something on the screen, and scanf() is the command that tells the compiler to read something from the standard input device. The functions can be illustrated with the following program: /* A program to explain the STANDARD I/O */ #include <stdio.h> int main () { int num; char alph; float x; printf("Enter an integer , a character and a floating point num: "); scanf("%d,%c,%f" ,&num ,&alph ,&x); printf("The integer is %d nThe character is %c nThe floating point num is %f n",num ,alph ,x); return 0; } Program 4.1: Standard I/O You can compile the above program and check it’s output. In the above program you can see a lot of weird characters like %d, &num etc. The %d %f etc. are called conversion characters. The table below provides the list of conversion characters. The conversion characters can also be used to set the precision of the floating 16
  • 32. 4.1 The gets() and puts() 17 Conversion character Displays argument (variable’s contents) as %c Single character %d Signed decimal integer (int) %e Signed floating point value in E notation %f Signed floating point value (float) %g Signed value in %e or %f format, whichever is shorter %i Signed decimal integer (int) %o Unsigned octal (base 8) integer (int) %s String of text %u Unsigned decimal integer (int) %x Unsigned hexadecimal (base 16) integer (int) Table 4.1: Conversion Characters point numbers. %0.2f gives a precision of up to 2 decimal places. The general format is %x.yf, where x and y are numbers to denote the length. Then there are escape sequences which help in formatting the output by providing newline, tab etc. Table 4.2 provides the list of escape sequences in C. Sequence Meaning a Beeps the speaker b Backspace (moves the cursor back, no erase) f Form feed (ejects printer page; may clear the screen on some computers) n Newline, like pressing the Enter key r Carriage return (moves the cursor to the beginning of the line) t Tab v Vertical tab (moves the cursor down a line) The backslash character ’ The apostrophe " The double-quote character ? The question mark 0 The “null” byte (that’s 0, not the letter O) Onn A character value in octal (base 8) xnnn A character value in hexadecimal (base 16) Table 4.2: Escape Sequences The printf() and scanf() are functions defined in stdio.h. We can also input to and get output from a file. File I/O is a topic for a further chapter but the reader should know from the beginning itself that the C compiler treats all input and output devices and files as streams of bytes. 4.1 The gets() and puts() The scanf() has a problem when handling strings, it will read only till the blank space. It will not read after a blank space occurs so we can give as input only a word. gets() and puts() are functions in the stdio.h header file. The gets() is used for input and puts() is used for output of a string. #include <stdio.h> int main ()
  • 33. 18 4. Input/Output Operations { char msg [50]; printf("nEnter the message: "); gets(msg); printf("nThe message ist: "); puts(msg); printf("The message can also be printed: %sn",msg); return 0; } Program 4.2: gets() and puts() 4.2 Exercise 1. Write a program that accepts your name, age and occupation and prints them as below. Name : Vineeth Age : 20 Occupation : Student 2. Write a program that prints the value of 𝜋(22/7) up to 4 decimal places. (Hint: use %0.4f as conversion character)
  • 34. Chapter 5 Operators Every program will contain expressions. Expressions are a combination of op- erators and operands. Eg. the + operator requires two operands and it acts on the operands and produces the sum as the result. In C the operators can be classified based on the number of operands it operates on as: 1. Unary operators 2. Binary operators 3. Ternary operators They are also classified based on type of operation as: 1. Arithmetic operators 2. Relational operators 3. Logical operators 4. Assignment operators 5. Increment and Decrement operators 6. Bitwise operators 7. Conditional operators 5.1 Binary Operators 5.1.1 Arithmetic Operators All the basic arithmetic operations can be carried out in C. All the operators have almost the same meaning as in other languages. Both unary and binary operations are available in C language. Unary operations operate on a single operand. The operators are + (addition or unary +), − (subtraction or unary minus), * (multiplication), / (division), % (modulo or the remainder operator—it gives remainder of division between 2 numbers1 ). 1The modulus operator cannot be applied for floating point numbers, it will be an error. 19
  • 35. 20 5. Operators Eg. 5%2 = 1 Except the modulus operator all other operators are same for floating point numbers. 5.1.2 Relational Operators The relational operators used in C are: <: less than >: greater than <=: less than or equal to >=: greater than or equal to ==: equal to2 !=: not equal to These operators always return the values as true or false (0,1). 5.1.3 Logical Operators The logical operators are: &&: Logical AND This operator returns the value true only if both the subordinate expressions are true. Eg. (x>2) && (y<4) ||: Logical OR This operator returns the value true if at least one of the subordinate expres- sions is true. If the left term is true then right term is not evaluated at all. Eg. (x>2) || (y<4) !: Logical NOT 5.1.4 Assignment Operators The = is the assignment operator used to assign values to variables. The variable to which the value is to be stored should come on the left side and the value or variable whose value is to be stored comes on the right side. count = count + 1 can be written as count+=1. Similarly we can write count-=5 for count = count - 5. For multiplication, division and modulus also we can apply this rule. 5.1.5 Bitwise Operators Normally we don’t have to use these operators. We only need to handle data in bytes. But for programs like encryption, data compression etc. we will have to handle data at the bit level. Bitwise AND (&) & operator is bitwise AND. The following is a chart that defines &, defining AND on individual bits. 2Not to be confused with ‘=’ which is an assignment operator and not a comparison operator
  • 36. 5.1 Binary Operators 21 x y x&y 0 0 0 0 1 0 1 0 0 1 1 1 Table 5.1: Bitwise AND Bitwise OR (∣) The ∣ operator is bitwise OR (it’s a single vertical bar). The following is a chart that defines ∣, defining OR on individual bits. x y x∣y 0 0 0 0 1 1 1 0 1 1 1 1 Table 5.2: Bitwise OR Bitwise XOR The ˆ operator is bitwise XOR. The usual bitwise OR operator is inclusive OR. XOR is true only if exactly one of the two bits is true. The XOR operation is quite interesting, but we defer talking about the interesting things you can do with XOR until the next set of notes. The following is a chart that defines ˆ, defining XOR on individual bits. x y x ˆ y 0 0 0 0 1 1 1 0 1 1 1 0 Table 5.3: Bitwise XOR Bitwise NOT There’s only one unary bitwise operator, and that’s bitwise NOT. Bitwise NOT flips all of the bits. There’s not that much to say about it, other than it’s not the same operation as unary minus. The following is a chart that defines ˜, Bitwise Shifts There are two bitwise shift operators, namely shift left and shift right. They are represented by the << and >> operators, respectively. These operations are very simple, and do exactly what they say: shift bits to the left or to the right. The syntax for a shift operation is as follows: [integer] [operator] [number of places]; A statement of this form shifts the bits in [integer] by the number of places indicated, in the direction specified by the operator. Probably the best
  • 37. 22 5. Operators x ˜ x 0 1 1 0 Table 5.4: Bitwise NOT way to visualize this is with an example. Take a look at the following code, which demonstrates a shift left. x = 0000 0110 1001 0011 x = x << 1; x = 0000 1101 0010 0110 From this example, you should be able to see what’s going on. Every bit in x is shifted to the left by one place. When you do this, the MSB (most significant bit) of x is lost, because there isn’t another place to shift it to. Similarly, after a shift left, the LSB of x will always be 0. There is no position to the right of the LSB, and so there’s nothing to shift into the LSB, so it’s assigned a value of 0. 5.2 Unary Operators 5.2.1 Unary plus and minus It controls the sign of a numeric constant or variable. The operator is prefixed to the constant or variable. It can also be used to change the sign of expressions as a whole. Eg. −5, +2, −𝑥, −(𝑥 + 𝑦) 5.2.2 Increment and Decrement Operators The increment ++ and decrement −− operators, as the name suggests, are used to increment and decrement the value of a variable. These operators can be used in two forms when used in expressions: 1. Post fix norm: In this form the ++ comes after the variable as var name++ or var name--. In this form the value of the variable is first used in the expression and then incremented. 2. Prefix norm: In this form the ++ or −− comes before the variable as ++var name or --var name. When used in this form the variable value is first used in the expression and then incremented later. The following program illustrates the effect of the above mentioned forms. #include <stdio.h> int main () { int num1=3,num2; num2 = num1 ++; //In the post fix form printf("Num1 =%d nNum2 =%d n",num1 ,num2); num2 = ++ num1; //In the prefix form printf("Num1 =%d nNum2 =%d n",num1 ,num2);
  • 38. 5.3 Ternary Operators 23 } Program 5.1: Increment and decrement operators The output will be: Num1=4 Num2=3 Num1=5 Num2=5 The same rule is applicable to the decrement operator also. 5.3 Ternary Operators 5.3.1 Conditional Operator The operator (expression1)?(expression2):(expression3) is called the con- ditional operator. It evaluates expression1 and if the result is true it returns expression2, if result is false it returns expression3. (x>y) ?x:y; The above statement will check if x is greater than y and if so it will return x or else it will return y. 5.3.2 Precedence and Associativity Two operator characteristics determine how operands group with operators: precedence and associativity. Precedence is the priority for grouping different types of operators with their operands. Associativity is the left-to-right or right- to-left order for grouping operands to operators that have the same precedence. An operator’s precedence is meaningful only if other operators with higher or lower precedence are present. Expressions with higher precedence operators are evaluated first. The grouping of operands can be forced by using parentheses. Table 5.5 lists the precedence and associativity of the operators we studied. 5.4 Exercises 1. Define precedence and associativity. 2. How are operators classified in C? 3. What is the output of the following statement: 4 + 5 ∗ 3 − 2%3? 4. Write the output of the following program: #include <stdio.h> int main () { int a=0; printf("n %d n %d n %d n",a,++a,a++); return 0; } Program 5.2: Find the output
  • 39. 24 5. Operators Operator Description Associativity () Parentheses (function call) left-to-right [] Brackets (array subscript) . Member selection via object name -> Member selection via pointer ++ -- Postfix increment/decrement ++ -- Prefix increment/decrement right-to-left + - Unary plus/minus ! ˜ Logical negation/bitwise complement (type) Cast (change type) * Dereference & Address sizeof Determine size in bytes * / % Multiplication/Division/Modulus left-to-right + - Addition/Subtraction left-to-right << >> Bitwise shift left/Bitwise shift right left-to-right < <= Relational less than/less than or equal to left-to-right > >= Relational greater than/greater than or equal to == != Relational is equal to/is not equal to left-to-right & Bitwise AND left-to-right ˆ Bitwise exclusive OR left-to-right | Bitwise inclusive OR left-to-right && Logical AND left-to-right || Logical OR left-to-right ?: Ternary conditional right-to-left = Assignment right-to-left += -= Addition/Subtraction assignment *= /= Multiplication/Division assignment %= &= Modulus/Bitwise AND assignment ˆ= |= Bitwise exclusive/inclusive OR assignment <<= >>= Bitwise shift left/right assignment , Comma (separate expressions) left-to-right Table 5.5: Precedence and Associativity
  • 40. Chapter 6 Control Statements A program consists of a number of statements which are usually executed in sequence. Programs can be much more powerful if we can control the order in which statements are run. Decision making is one of the crucial and essential part of a program. We will encounter situations where we will have to make a decision on how to proceed further. Decision making statements in C check whether a given statement is true or false. The decision making statements in C are if else and switch case. 6.1 if...else The if statement has two forms: if(expression) statement if(expression) { statements ... } else { statements ... } The statements in the if block are executed if the expression is true and statements in else block are executed if the expression is false. The if else statements can also be used in the form of if else ladder or as nested if else. The curly braces are not an essential part of the if statements if there is only a single statement following it, but it’s always a good practice to use the braces. // A program to find largest of two numbers #include <stdio.h> int main(int argc ,char argv []) { int num1 ,num2; printf("Enter the first number: "); scanf("%d" ,&num1); printf("Enter the second number: "); scanf("%d" ,&num2); if(num1 >num2) printf("First number is largern"); 25
  • 41. 26 6. Control Statements else printf("Second number is largern"); return 0; } Program 6.1: Largest of two numbers 6.1.1 Nested if else if(expression) { statements } else if(expression) { statements } else { statements } The ladder can be extended as long as required. if (result >= 75) printf(‘‘Passed: Grade An’’); else if (result >=60) printf(‘‘Passed: Grade Bn’’); else if (result >=45) printf(‘‘Passed: Grade Cn’’); else printf(‘‘Failedn’’); Nesting can be done in the else tag also. 6.2 switch case This is another form of the multi way decision. It can only be used in certain cases where: ∙ Only one variable is tested, all branches must depend on the value of that variable. The variable must be an integral type. (int or char). ∙ Each possible value of the variable can control a single branch. A final, catch all, default branch may optionally be used to trap all unspecified cases. It’s syntax is switch(choice) { case val1: statements; break; case val2: statements; break; default: statement; break; } Each interesting case is listed with a corresponding action. The break state- ment prevents any further statements from being executed by leaving the switch. Both if and switch constructs allow the programmer to make a selection from a number of possible actions. Let us see an example program.
  • 42. 6.3 Conditional Operator 27 // A program to display the day corresponding to a number #include <stdio.h> int main(int argc ,char argv []) { int num; printf("Enter a number: "); scanf("%d" ,&num); switch(num) { case 1: printf("nSunday n"); break; case 2: printf("nMonday n"); break; case 3: printf("nTuesday n"); break; case 4: printf("nWednesday n"); break; case 5: printf("nThursday n"); break; case 6: printf("nFriday n"); break; case 7: printf("nSaturday n"); break; default: printf("Error"); break; } return 0; } Program 6.2: switch case 6.3 Conditional Operator The conditional operator is similar to if else but nesting is not possible. condition?statement1:statement2; Here we check for the validity of the condition. If it’s true statement1 is executed or else statement2 is executed. 6.4 Loops The other main type of control statement is the loop1 . Loops allow a statement, or a block of statements, to be repeated. Computers are very good at repeating simple tasks many times, the loop is C’s way of achieving this. A looping statement consists of an initializing statement, a validation statement and an increment/decrement statement. There are two types of loops in C they are: ∙ Entry controlled loops ∙ Exit controlled loops 1Loops are also called iteration statements.
  • 43. 28 6. Control Statements 6.4.1 Entry Controlled Loops Entry controlled loops are loops in which the expression is checked before the loop is executed. Such loops are used when we have to execute loop only if the validation expression is valid. The entry controlled loops in C are for and while. The for Loop The syntax of for loop is for(initializing statement; validation expression; increment/decrement) { loop body } Basically a for loop can be written as simply as for( ; ; ) { loop body } It’s only the semicolons within the parentheses that are important in a for loop. The above loop will be executed infinitely and is called an infinite loop. // A program to print first 10 natural numbers #include <stdio.h> int main(int argc ,char argv []) { int i=1; for(i;i <=10;i++) { printf("n %d n",i); } return 0; } Program 6.3: for loop For a loop body with a single statement, the { } can be avoided. In the below program for(int i=1;i <=10;i++) { printf(‘‘n %d n’’,i); } can be replaced by for(int i=1;i <=10;i++) printf(‘‘n %d n’’,i); but it is always a good practice to use the braces, it makes the program more readable and understandable. The for loop can be used as a nested for loop. The while Loop while is another entry controlled loop that checks the validity of an expression before executing the loop body. Unlike a for loop the while has the incremen- t/decrement statement within the loop body.
  • 44. 6.4 Loops 29 The syntax of while loop is: while(expression) { loop body } We can rewrite the program for printing number 1–10 using the while loop. #include <stdio.h> int main(int argc ,char argv []) { int i; i=1; while(i <=10) { printf("n %d n",i); i++; } return 0; } Program 6.4: while loop 6.4.2 Exit Controlled Loops Exit controlled loops check the validity of the expression only after each itera- tion. The do...while Loop The do while loop is an exit controlled loop because the expression is checked for validity only after executing the loop body each time. Such loops are used when we need the loop to be executed at least once. The syntax of do while is do { loop body } while(expression); The semicolon after while is important in the do while, it marks the end of the loop. The program to print numbers 1–10 can be done using do while loop, and it is left as an exercise for the readers. 6.4.3 The break Statement Sometimes while executing a loop it becomes desirable to skip a part of the loop or quit the loop as soon as certain condition occurs, for example consider searching a particular number in a set of 100 numbers, as soon as the search number is found it is desirable to terminate the loop. C language permits a jump from one statement to another within a loop as well as to jump out of the loop. The break statement allows us to accomplish this task. A break statement provides an early exit from for, while, do and switch constructs. A break causes the innermost enclosing loop or switch to be exited immediately.
  • 45. 30 6. Control Statements The syntax is break; 6.4.4 The continue Statement During loop operations it may be necessary to skip a part of the body of the loop under certain conditions. Like the break statement C supports similar statement called continue statement. The continue statement causes the loop to be continued with the next iteration after skipping any statement in between. The syntax is continue; 6.5 Exercises 1. Write a program to accept length of 3 sides of a triangle and check if a triangle can be formed with the given sides. 2. Write a program to calculate the total mark of a student for five subjects and find out his grade such that if percentage of mark is I. A => 80 II. B => 70 III. C => 60 IV. D => 50 V. F for failed Also print the mark list along with student name, roll number, class, year, percentage and grade in a well formatted manner. 3. Write a program to print the letters of your name in a lower triangular form. The name Vineeth should be printed as V Vi Vin Vine Vinee Vineet Vineeth 4. Write a program to print the Fibonacci series (0,1,1,2,3,5,. . . the next num- ber is sum of the previous two numbers). 5. Write a program to check if a given number is a prime number. 6. Write a program to generate the mathematical tables up to a given limit.
  • 46. Chapter 7 Structured Data Types For a large class of problems in computing, it is the data and not the algorithms that are the most interesting. If the initial design gets it’s data structures right, the rest of the effort in putting a program together is often quite small. However, you need help from the language. If there is no support for structured data types other than arrays, writing programs becomes both less convenient and also more prone to errors. It is the job of a good language to do more than just allow you to do something; it must actively help as well. C offers arrays, structures and unions as it’s contribution to data structuring. They have proved to be entirely adequate for most users’ needs over the years and remain essentially unchanged by the Standard. In this chapter we will discuss the three basic structured data types used in C. 1. Arrays 2. Structures 3. Unions There are other structured data types in C like enums and bitfields. 7.1 Arrays An array is a list of objects all of the same type. The objects comprising an array are called elements. The dimensions of an array describe how many elements an array contains and how it’s elements are arranged in memory. Each element is identified by an index. Giving the relative position of the element within the list, the first element has the index 0. A one-dimensional array arranges elements in a linear list whereas a two-dimensional array arranges elements like elements in a matrix. Arrays of higher dimensions are also possible. The elements of an array are arranged contiguously in memory. For two and higher dimensional arrays the elements are stored in row major order (in a matrix X after X[m][n], X[m][n+1] is stored.). An array can be for both in-built and user defined data types. data type arrayname[size ][ size ]; 31
  • 47. 32 7. Structured Data Types Arrays can be initialized only with constant values and not with variables. The following example shows how to initialize a two-dimensional array. int sample [2][2]={{1 ,2 ,3} ,{4 ,5 ,6} ,{7 ,8 ,9}}; You can omit the size within the brackets of the last array dimension when you include an initializer for the array. 7.2 Structures Arrays allow for a named collection of identical objects. This is suitable for a number of tasks, but isn’t really very flexible. Most real data objects are complicated things with an inherent structure that does not fit well on to array style storage. Let’s use a concrete example. Imagine we have to collect the data of all students in a college. Each student will have certain data associated with him like name, class, roll number, marks etc. So we have to group all these data together as single piece for one student and repeat the same for all the other students. In such a situation we use structures. Structures are user defined data types that are a collection of several other user defined or primary data types. Let’s look at a code snippet struct student { int rollno , marks , avg; char name [20], class [6]; }; In the above example, student is called the tag or the structure name and within the braces we’ve declared the variables that the structure student should hold. Structures do not occupy any memory unless associated with an instance. The size of a structure is the total size of all the individual elements it contains. Structure instances cannot be declared without defining the structure. Once the structure is defined it can be treated just like other data types in C. We can call it in a function or the main program and access each element of the structure, we can even create an array with the created structure. Let’s see a program: #include <stdio.h> struct student { int rollno ,marks; char name [20], class [6]; } stud1 ={1 ,450 ,"xyz","ee"},stud2; //A variable can be declared like this :-) int main () { struct student s; // struct student s[10]; An array can also be declared with student as datatype printf("Enter the name of the student: "); scanf("%s" ,&s.name);
  • 48. 7.2 Structures 33 printf("nThe name of the student is: %s n",s.name); stud2=s; // Assigning one variable to another printf("nThe name of the student is: %s n",stud2.name); return 0; } Program 7.1: Structure The above example has a lot of treasure in it, let’s dig it all out :-) ∙ We see that right after the definition body of the structure an instance has been declared, this is one way of declaring instances for the created structures. ∙ The semicolon that appears right after that is compulsory even if the instance wasn’t declared. It denotes the end of the structure definition so missing out the semicolon will result in syntax error. ∙ The instance of the particular structure is defined as a primary data type. Even an array can be declared and sometimes we use these structures inside others which we will see soon. ∙ The most important question is, how to access each element of the struc- ture? The answer is a simple . The . is called a dot operator. It’s syntax is instance.member name, this will be clear from the above example where s.name shows how the dot operator functions. ∙ The assignment operator or the = can also be used with structures but no other operator can be used. We can assign the values of one structure instance to another instance of the same structure. ∙ The next question is about initializing the instance. The instance de- clared can be initialized by giving the values of each element within the {} separated by a comma. Well that should explain almost the whole of structures. Now there are some points that I have left out and I have done it intentionally. These are: ∙ What happens if while initialization we input values which are less than the number of the elements i.e. in the above example student contains 4 elements then what will happen to a statement struct student a={1,2,‘‘ab’’}; ∙ Can we assign only a particular element of one structure variable to an- other structure variable? ∙ All other questions and possibilities that you can think about have been left out as an exercise for the reader, after all what thrill is there if you are provided with all the information. The thrill lies in discovering things and thats how we c :-) 7.2.1 Nested Structures Structures can be nested, that is one structure can be used as a data type in another structure.
  • 49. 34 7. Structured Data Types struct employee { int id ,salary; char name [20]; } struct manager { struct employee x; char grpcharge [20]; } In the above code we can see that the structure employee is nested within the structure manager because a manager is also an employee with additional characteristics. So both structures have some common traits. So we can avoid duplicating of code (some people call it reusability of code). 7.2.2 Unnamed Structures Structures can also be created without a name, but such structures cannot be used for later references. We have to create instances of the structure at the same time when we define the structure. struct { char bookname [10]; int isbn_no; } book1 , book2 , book3; With the above code we use the variables book1, book2, book3 but we cannot write the statement to create a new variable because we do not have a tag to identify the structure. 7.3 Unions Unions are user defined data types that are a collection of several other user defined or primary data types. Does this definition seem familiar! Well it is because we defined the structures in the same way. So actually then what is the difference of a union? The difference of a union and a structure lies in it’s memory allocation. Let’s look at the following code. struct strdate { int year ,dat; char month [10]; } var1; union dateunion { int year ,dat; char month [10]; } var2; In the above example we have declared a union and a structure to hold the date. A structure variable var1 will have the memory size of 14 bytes (2 bytes for year, 2 bytes for dat, 10 bytes for month).
  • 50. 7.4 Exercises 35 But the union instance var2 will have the size of 10 bytes only (the size required for the largest element). So that’s how a union is different from a structure. It can accept only the value for one of the elements at a time that belongs to it. You can picture a union as a chunk of memory that is used to store variables of different types. Once a new value is assigned to a field, the existing data is wiped over with the new data. Unions are used in situations where we need to use only one element of a structure at a time and thus we can reduce the wastage of space. The method to access union elements is the same as that for structures. Now the question is how to initialize an instance of the union. We know that an instance of a union can hold value to only one of it’s variables. Let’s see how to do this: union dob { int year ,date; char month [10]; } var1 ={1990} , var2 ={. date =15}; This is how to initialize a union instance. We can use only one value and that value will be assigned to the first element. If we are specific about the element it should be specified as is done for var2 (the . is very important, do not omit it). 7.4 Exercises 1. Write a program to find the sum of two matrices. 2. Write a program to find product of two matrices (two matrices of order 𝑚 ∗ 𝑛 and 𝑝 ∗ 𝑞 can be multiplied only if 𝑛 = 𝑝). 3. Write a program that will accept an array and then sort elements of the array in ascending order and display the elements. 4. Write a program that has a structure that contains all details of employees in a firm. Create structure for a normal employee and for the manager. And display the details when requested. 5. Write a program to compare two given words (ignore case sensitivity).
  • 51. Chapter 8 Functions The divide and conquer is the most often used technique in programming large programs. Programs are divided into smaller modules and finally they are joined together. This helps in understanding and debugging the code. A function in C is a block of code that performs a specific task. It has a name and it can be executed from as many different parts in a program as required. It also optionally returns a value to the calling program, we have already seen the main() function. So function in a C program has some properties discussed below. ∙ Every function has a unique name. This name is used to call function from anywhere in the code. ∙ A function is independent and it can perform it’s task without intervention from or interfering with other parts of the program. ∙ A function performs a specific task. A task is a distinct job that your program must perform as a part of it’s overall operation, such as adding two or more integers, sorting an array into numerical order, or calculating a cube root etc. ∙ A function returns a value to the calling program. This is optional and depends upon the task your function is going to accomplish. Suppose you want to just show few lines through function then it is not necessary to return a value. But if you are calculating area of a rectangle and wanted to use the result somewhere in program then you have to send back (return) value to the calling function. C language is collection of various in-built functions. If you have written a pro- gram in C then it is evident that you have used C’s in-built functions. printf, scanf, clrscr etc. all are C’s in-built functions. You cannot imagine a C program without function. There are three steps in using functions, they are 1. Function declaration (function prototype): The syntax for function declaration is type name(arguments); 2. Function definition: The syntax for this is type name(arguments){statements} 3. Function calling 36
  • 52. 8.1 Passing Values to Arguments 37 The function declaration and definition can be made together. The function declaration should be made before calling the function. But function definition need not be defined before calling it can be done even after calling. Let’s see a small code: /**A program to find area of square **/ #include <stdio.h> double find_area(double); int main () { double side ,area; printf("nEnter the length: "); scanf("%f" ,&side); area=find_area(side); printf("nThe area of the square is: %f n",area); return 0; } double find_area(double leng) { return(leng*leng); } Program 8.1: Area of Square The above code displays some features. ∙ At first we see that the function find area() is declared if not the com- piler will show an error. ∙ Then you can see that the argument list in the function declaration consist only of the data type of variable used and not the variable name used. The variable name is not necessary in the argument list during declaration but it is compulsory in the argument list of function definition. ∙ We have also seen how the function returns a data and so it can be used in expressions. ∙ The variable leng is called the formal argument and side is called actual argument. We can say that formal arguments are the arguments that we define in function declaration and actual arguments are arguments that we pass to the function during function call. 8.1 Passing Values to Arguments In the previous example we saw that the length of the square was given as an argument to the function find area(), the function used this argument for further calculation. The argument list can contain as many arguments as required, it can even be zero. The data type of each argument should be given separately even if they all are of the same type. In case there are arguments then we should learn how the values we give as input is passed to the arguments in the function. The arguments are passed to the functions by 1. Pass by value 2. Pass by reference using pointer method
  • 53. 38 8. Functions The pointer method will be dealt with in a later chapter. 8.1.1 Pass by Value In this method we make a copy of the original variable and the function operates on that copy, so the original variable is not affected. 8.1.2 Pass by Reference In this method we refer to the function the original address where the variable is stored and the function operates directly on that variable, so changes that the function brings about on the variable is reflected on the value stored in the variable itself. There are two methods to do this. ∙ Using reference variables - C does not support this method ∙ Using pointers You may find several sources with arguments on this topic, some say that C does not support pass by reference at all, and that the pointer method cannot be called a pass by reference method, but this does not matter because all we need is a program to work as we wish. 8.2 The return Statement We have seen that a function itself has a data type, this indicates what type of value the function will return after it’s execution, so all functions except the one with void as data type should have at least one return statement. During the execution of a function only the first return statement will be executed because a function exits as soon as it encounters a return statement. int my_fun(int a,int b) { if(a>b) return a; else return b; } In the above code the function returns the greatest of the two values passed to it, as soon as it meets one return statement the function execution is over. For functions with void as data type the closing braces (}) acts as an automatic return statement. 8.3 Functions with Variable Argument List Perhaps you would like to have a function that will accept any number of values and then return the average. You don’t know how many arguments will be passed into the function. One way you could make the function would be to accept a pointer to an array.
  • 54. 8.3 Functions with Variable Argument List 39 Functions in C can also have an argument list that varies in length, for that we use an operator called ellipsis which consists of three (.) without any space between them. The function prototype will be int fun(int num , ...); Indeed, some library functions can accept a variable list of arguments (such as printf—I bet you’ve been wondering how that works!). Whenever a function is declared to have an intermediate number of argu- ments, in place of the last argument you should place an ellipsis (which looks like ‘. . . ’), so, int a_function(int x, ...); would tell the compiler the function should accept however many arguments that the programmer uses, as long as it is equal to at least one, the one being the first, x. To use these functions, we need a variable capable of storing a variable- length argument list—this variable will be of type va list. va list is like any other type. va start is a macro which accepts two arguments, a va list and the name of the variable that directly precedes the ellipsis (“. . . ”). So in the function a function, to initialize list with va start, you would write va start(list, x); int a_function(int x, ...) { va_list list; va_start(list , x); } va arg takes a va list and a variable type, and returns the next argument in the list in the form of whatever variable type it is told. It then moves down the list to the next argument. For example, va arg(a list, double) will return the next argument, assuming it exists, in the form of a double. The next time it is called, it will return the argument following the last returned number, if one exists. Not that you need to know the type of each argument—that’s part of why printf requires a format string! Once you’re done, use va end to clean up the list: va end(a list); To show how each of the parts work, take an example function: #include <stdarg.h> #include <stdio.h> float average(int num , ...) { va_list arg; float sum =0; int x; /* Initializing arguments to store all values after num */ va_start(arg ,num); /* Sum all the inputs; we still rely on the function caller to tell us how many there are */
  • 55. 40 8. Functions for(x=0;x<num;x++) { sum += va_arg(arg ,float); } va_end(arg); // Cleans up the list return sum/num; } int main () { printf("%fn",average (3, 12.2, 22.3, 4.5)); printf("%fn",average (5, 3.3, 2.2, 1.1, 5.5, 3.3)); } Program 8.2: Variable argument list In the variable-length part of variable-length argument lists, the old “default argument promotions” apply: arguments of type float are always promoted (widened) to type double, and types char and short int are promoted to int. Therefore, it is never correct to invoke va arg(argp,float); instead you should always use va arg(argp,double) Similarly, use va arg(argp,int) to retrieve arguments which were originally char, short or int. (For analogous reasons, the last “fixed” argument, as handed to va start, should not be widenable, either.) It isn’t necessarily a good idea to use a variable argument list at all times; the potential exists for assuming a value is of one type, while it is in fact another, such as a null pointer being assumed to be an integer. Consequently, variable argument lists should be used sparingly. 8.4 Scope of a Function The scope of a function shows in what parts of a program code the function is available. If a function is defined within main() then that function can be used only in the main() of that code. Usually functions are declared outside the main(). If we use the type qualifier static then the function is available only in the source code where it’s definition is made. By default the type qualifier for a function is extern. This shows that the function can be defined in some other source file. Also global variables are accessible by all functions but a variable declared within a function is accessible only by that function. Any source file needing to use a function in another source file should declare it. 8.5 Arrays as Arguments Arrays can also be used as arguments to a function. In this case during function declaration or definition the size of array may or may not be specified. Also we’ve seen earlier that the name of an array also denotes the address of the array so array arguments acts much like pointer arguments which we will see in the coming chapter. The effect is that any change that we bring to array is reflected because here the arguments are not passed by value i.e. the compiler doesn’t pass the copies of the arguments but it passes the arguments itself. The
  • 56. 8.6 Recursive Functions 41 reason that the size of array is irrelevant in the function declaration is because the array name is treated as an address location and the memory from that location onwards is monitored by the function, but the programmer should take care that the memory being accessed does not contain garbage values. #include <stdio.h> void fun(int arr[],int len) { int i; for(i=0;i<len;i++) { printf("n%dn",arr[i]); } } int main () { int a[]={1 ,2 ,3 ,4 ,5}; fun(a,5); return 0; } Program 8.3: Arrays as arguments The above program prints out the elements in an integer array. Here the programmer has to give size of array in the main() or else the function will not know till when to read and it might read out some garbage values. 8.6 Recursive Functions Recursion is a method where the solution to a problem depends on solutions to smaller instances of the same problem. Recursion is a method used in Com- puter Science to breakdown larger problems into smaller ones, there are a lot of mathematical problems that use recursion. The factorial, Fibonacci series etc. . . . all can be implemented by recursion. As the name suggests recursive functions are functions that repeat in loop until terminated by some condition. These are functions that refer back to themselves so they go on being executed. In a programming language, recursive functions are an inefficient means of solv- ing problems in terms of run times but are interesting to study, they simulate the effect of using a stack. The property of a stack can be understood by con- sidering a pile of books. When we place a new book to the pile (This is called pop) it goes on top and the book that was on top first is pushed one position down, while removing a book (This is called push) from that pile we move the topmost or we use the LIFO (Last In First Out). Let’s see a program that finds the factorial of a given number. #include <stdio.h> int fact(int num) { if(num <=1) return 1; else { return(num*fact(num -1)); } } int main ()
  • 57. 42 8. Functions { int result ,num; printf("nEnter the number: "); scanf("%d" ,&num); result=fact(num); printf("nThe result is %d n",result); return 0; } Program 8.4: Factorial In the above program the function fact() calls itself (This is called imme- diate recursion) and thus it goes on till the variable num=1. Suppose the input was three, ∙ In the first stage we get 3*fact(2) ∙ Then we gave 2*fact(1) ∙ fact(1) will return 1 so going back to the top we get 1*2 ∙ This is returned to the outer fact() and we get 3*(1*2). Thus the factorial of 3 was obtained. All recursive functions can be rewritten with loops but making recursive func- tions saves a lot of code. But care has to be taken that the recursive function exits at some point of it’s execution and that it does not fall into an infinite loop. Sometimes recursive functions are a bit tricky to understand even for a well experienced programmer. Tower of Hanoi Almost every textbook that speaks about recursion in programming mentions this famous puzzle. The Tower of Hanoi is a mathematical game or puzzle. It consists of three rods, and a number of disks of different sizes which can slide onto any rod. The puzzle starts with the disks in a neat stack in ascending order of size on one rod, the smallest at the top, thus making a conical shape. Figure 8.1: Tower of Hanoi The objective of the puzzle is to move the entire stack to another rod, obeying the following rules. ∙ Only one disk may be moved at a time.
  • 58. 8.7 Command Line Arguments 43 ∙ Each move consists of taking the upper disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod. ∙ No disk may be placed on top of a smaller disk. A key to solving this puzzle is to recognize that it can be solved by breaking the problem down into a collection of smaller problems and further breaking those problems down into even smaller problems until a solution is reached. 8.7 Command Line Arguments It has already been mentioned that main() is also a function, this function also has three arguments, the original form of the main() function is: int main(int argc , char *argv[], char envp []); The function main() has a return type of int and the exit code is the value that the main() function returns. This is a number that is used by the OS to detect whether the function exited properly or if there was any error. Usually we return zero to denote a success in execution. Before I explain the arguments let’s once again look at how we execute a program from the shell. Let the program name be prog, then at the terminal we type: $ ./prog ($ symbol shows the command prompt, it is not to be typed). We can provide values to the arguments right after the program name. Let copy be a program to copy contents of one file to another then the program will be executed by issuing the following command. $ ./copy file1 file2 Here file1 and file2 are two arguments passed to the program copy. Now let’s discuss the arguments in the main(). ∙ int argc: This is the argument that keeps count of the number of words appearing on the command line that invokes the program and the count includes your program name also. In the above example, the value in argc will be 3 (copy, file1, file2). The argc value will be at least one because it counts the program name. ∙ char argv[]: This is a character array that contains the words including the program name. In the above example the array will be argv[]={copy,file1,file2}. ∙ The last variable is environment variable which contains details about the environment in which the program is being executed, it lists out the environment variables. The argument argc and argv are conventional names, we can use any other name. Let us now see a program that elaborates on the command line arguments.
  • 59. 44 8. Functions #include <stdio.h> int main(int argc ,char *argv []) { int i; printf("n The number of arguments is: %d n" ,(argc -1)); /* argc contains count of program name also */ printf("nnnaaaaaaThe arguments are: n"); for(i=0;i<argc;i++) { printf("%s",argv[i]); } printf("nn"); return 0; } Program 8.5: Command line arguments The readers can now write a program to list out the environment variables. There are a lot of environment variables and when you execute the program you will see that there is a big list of variable being displayed, at present these variables are not of much importance but you can search the Internet to learn more about the shell and the environment variables. Some of the simplest environment variables are those which contain the path of the current working directory, path of the home folder etc. 8.8 Exercises 1. Write a function using recursion to print numbers from 𝑛 to 0. 2. Write a function using recursion to enter and display a string in reverse and state whether the string contains any spaces. Don’t use arrays/strings. 3. Write a function using recursion to check if a number 𝑛 is prime. (You have to check whether 𝑛 is divisible by any number below 𝑛.) 4. Write a function using recursion to enter characters one by one until a space is encountered. The function should return the depth at which the space was encountered. 5. Write a function that accepts two matrices and returns the product if they can be multiplied. 6. Write a program that takes argument from command line and returns the number of upper case letters used.
  • 60. Chapter 9 Pointers Pointers are the most important and most powerful concept of C. An experienced C programmer can handle pointers easily whereas it makes programming a nightmare for beginners. The reason is that beginners fail to grasp the concept of pointers and related fields like dynamic memory allocation etc. The pointer is another type of variable which stores the address of a variable, a pointer is a variable that points to the memory location of a variable of a particular type. The pointer variable can store address of an int, float, char, structure or even of a pointer variable itself. We can also declare a pointer with void data type. A pointer variable is declared as: type *variablename; The * is what distinguishes a normal variable from a pointer variable. Some examples for pointer declaration are: int *mypoint; float *charpoint; We know that an integer variable has 2 bytes length, a float has 4 bytes and a character variable has 1 byte length. The pointer variable for all data types has 1 byte memory. All that a pointer variable does is that it stores the address of a variable so it has only 1 byte memory. In C the name of an array is actually a pointer to the address of the first element of the array. The process of reading the value stored at a particular memory address in a pointer is called dereferencing. We have used the & in the scanf(), have you ever wondered what the symbol stands for, it is used to denote the address of the variable, suppose you have a normal integer variable called var and you want its address then we use &var to denote it’s address. It is actually the address of the variable that we pass to the scanf(). int a=10,b, *point; point =&a; b=* point; In the above code we declared two normal integer variables and a pointer to integer variable. In the second statement we stored the address of the integer variable to the pointer variable. The next statement is called dereferencing, the value stored at the address denoted by point is being retrieved. It is to be noted that we use the asterix itself to dereference a pointer variable. 45
  • 61. 46 9. Pointers 9.1 Pointer Arithmetic The pointer variable can be incremented, decremented and value in the pointer variable can be assigned to another variable. These are the only arithmetic operations that can be performed on the pointer variables. The pointer of same data types can be compared. #include <stdio.h> int main () { int a=10,* point; point =&a; printf("n %d: ",point); printf("n %d: " ,*point); printf("n %d: " ,++(* point)); point ++; printf("n %d: n" ,*point); return 0; } Program 9.1: Pointer Arithmetic In the above program let’s assume the address of the variable a is 100. In the first printf statement the address 100 is printed, in the second printf statement the pointer is dereferenced and the value 10 stored in it is displayed. In the third statement the value stored at location 100 is incremented and printed, and finally the point++ increments the address value. The question is by how much does the address increase? If your answer is that it increases from 100 to 101 then it’s wrong, the address value in point increases by 2 bytes because the integer data type is of 2 bytes size. The same is applicable for the decrement operator also. The statement printf(‘‘n %d:’’,*point ++); In this statement the value at location point is dereferenced and then the address in point is incremented. 9.2 Call By Reference We have seen that when we pass arguments to functions only copies are passed and not the real variables themselves, this is called pass by value. Pass by reference is a method in which we pass the original variables themselves therefore if the function brings about a change in the value of the variable this value is reflected in the original variable itself. We know that a function can return only one value, it can have only one return statement. But we can use the concept of pass by reference to return more than one value from the function. #include <stdio.h> int div(int a,int *rem) { int var1; var1 =*rem; *rem=a%var1; return(a/var1); } int main ()
  • 62. 9.3 Pointer to Function 47 { int a=5,b=2,c; c=div(a,&b); printf("nQuotient =%d nRemainder =%d n",c,b); return 0; } Program 9.2: Call by reference In the above program we have defined a function div() such that it returns the quotient after division of two numbers and the remainder is returned by call by reference method because the second number to be divided is passed by reference and the remainder is stored in it. As the second argument we pass address of the variable b. 9.3 Pointer to Function We know that functions return values corresponding to the data type of the function. Functions can also return pointers. In such a case the function decla- ration will be as below: data type *function_name(<arguments >); Obviously the return statement of the function should return an address. But this is not the pointer to function concept and readers should not confuse themselves. A pointer to function declaration is as follows: data type (* function_name)(<arguments >); Function pointers provide some extremely interesting, efficient and elegant programming techniques. You can use them to replace switch/if statements. Function pointers are pointers, i.e. variables, which point to the address of a function. You must keep in mind, that a running program gets a certain space in the main memory. Both the executable compiled program code and the used variables are put inside this memory. Thus a function in the program code, is like character field, nothing else than an address. It is only important how your compiler/processor interpret the memory a pointer points to. The function pointer can be used to store that address and that pointer can be used to dereference and call the function. A function pointer invokes a function, passing it zero or more arguments just like a normal function. Function pointers can be used to simplify code by providing a simple way to select a function to execute based on run-time values. #include <stdio.h> float Plus(float a,float b) // Function to add { return a+b; } float Minus(float a,float b) // Function to minus { return a-b; } float Multiply(float a,float b) // Function to multiply { return a*b; } float Divide(float a,float b) // Function to divide { return a/b; } // Function with pointer to function as argument
  • 63. 48 9. Pointers void calculator(float a,float b,float (* point)(float ,float)) { float res=point(a,b); // Call using function pointer printf("The result is: %f n",res); } int main () { calculator (2,5,& Minus); return 0; } Program 9.3: Pointer to function The & in &Minus is not compulsory, we can write that statement as calculator (2,5, Minus); In the above program the function calculator() accepts two floating point numbers and a pointer to the function Minus(). In the function calculator() the pointer is used to call the corresponding function and the floating point numbers are used as arguments of that function and the result is printed. The function pointer does not increase speed of calling function but it makes a function similar to a variable and it can be passed to another function as an argument, it can be assigned to another pointer variable etc. The function can almost be treated as a normal variable. 9.4 Pointers and Arrays We have already discussed that the name of an array refers to the memory location of the first element of the array. The other members are accessed by incrementing the memory address from there as we saw in pointer arithmetic. We can also declare an array of pointers which will contain a collection of the address values. int num [10] ,*p,a,* parray [10]; p=num; // Valid statement as both contain address a=p; // Invalid statement Here the name num references to the location of integer stored in num[0], so the value of num can be assigned to the pointer variable p. If the argument list of a function contains a pointer variable of a type, then during function call we can pass an array of the same type to the function. The use of pointer arguments instead of arrays can simplify the code, but in order to handle pointers you should be well versed with it. Strings are also arrays of characters. We can access strings using pointers just as we did for a normal array because a string is also a normal array but the end of a string is indicated by the NULL character 0. We can use this idea to detect end of a string. #include <stdio.h> void readstr(char *msg) { int i;