0% found this document useful (0 votes)
33 views300 pages

MCA C Programming Course Overview

The document outlines the course structure for 'Programming with C' offered by Karnataka State Open University for the MCA Computer Science program. It includes details about the course design, committee members, and a comprehensive table of contents covering various units on C programming concepts. The preface emphasizes the importance of C as a programming language and its practical applications in software development.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views300 pages

MCA C Programming Course Overview

The document outlines the course structure for 'Programming with C' offered by Karnataka State Open University for the MCA Computer Science program. It includes details about the course design, committee members, and a comprehensive table of contents covering various units on C programming concepts. The preface emphasizes the importance of C as a programming language and its practical applications in software development.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Karnataka State Open University

Mukthagangotri, Mysore-570006

MCA Computer science


First Semester

PROGRAMMING WITH C

COURSE – MCADSC-1.1 BLOCK – 1-4


CREDIT PAGE

Programme Name: MCA-Computer Science Year/Semester: I Semester Block No:1-4

Course Name: Programming with C Credit: 4 Unit No: 1-16

Course Design Expert Committee

Dr. Sharanappa V Halase Chairman


Vice Chancellor
Karnataka State Open University, Mukthagangotri, Mysuru-570006.

Dr. N. Lakshmi Dean (Academic), Member


Karnataka State Open University, Mukthagangotri, Mysuru-70006.
Editorial Committee

Dr. Bhavya D.N., BE., MTech.,Ph.D. BOS Chairman


Dept Chairperson, Assistant Professor & Programme co-ordinator
(UG/BCA) DoS &R in Computer Science,
Karnataka State Open University, Mysuru-570 006.
Smt, Suneetha MSc. (PhD) Member
Associate, DoS & R Programme co-ordinator (UG/BSc-CS) in Computer
Science, Karnataka State Open University, Mysuru-570 006.
Dr. Sumati Ramakrishna Gowda BE., MTech., Ph.D. Member
Assistant Professor & Programme co-ordinator (PG/MCA) DoS&R in
Computer Science, Karnataka State Open University, Mysuru-570 006.
Dr. Mahesha D.M., MCA., Ph.D. Member
Assistant Professor & Programme co-ordinator (PG/MSc) DoS&R in
Computer Science, Karnataka State Open University, Mysuru-570 006.
Dr. Sharthkumar Y.H., [Link].D. Member
Professor,
DoS&R in information science
MIT Belawadi Srirangapatna Tq, Mandya
Name of Course Writer No of No of Name of Course No of
Blocks Units Editor Units
Dr. Poornima Y Dr. Natesh M 1-4
Asst, Professor Block-1 1-4 Associate Professor
Dos in Computer Science Department of Computer
Maharaja’s College- 5700021 Science, VVCE Mysore
Dr. Sharthkumar Y.H Santhosh K 8-16
Professor of IS Block-2 5-8 Assistant Professor
MIT Belavadi Srirangapatna Tq Department of Computer
Mandya Dist- 571477 Science, JSS women’s college
Saraswathipuram,Mysore
Dr. Basappa B kodada Block -3 9-12 Sri. Somashekar B M 9-12
Associate Professor and AIML BE, MTech. (PhD)
Canara Engineering College Assistant Professor,
Benjanapadavu Bantwal Department of Information
Mangalore Scince MIT, Naguvanahalli
post, Sriranganapatna, taluk-
Mandya -District 571438
Smt. Vasanthi Block-4 13-16 Smt. Sumanshree Y S 13-6
Asst, Professor Chairperson
Dos in Computer Science DoS in Computer Science
MIT Degree College (PG),JSS college of arts,
Vishweshwaranagar Science, Commerce Ooty
Mysore Road Mysore
Copy Right
Registrar,
Karnataka State Open University,
Mukthagantoghri, Mysore 570 006.

Developed by the Department of Studies and Research in Computer Science, under the guidance of
Dean (Academic), KSOU, Mysuru.
Karnataka State Open University, June -2024.
All rights reserved. No part of this work may be reproduced in any form or any other means, without
permission in writing from the Karnataka State Open University.
Further information on the Karnataka State Open University Programmes may be obtained from the
University’s Office at Mukthagangotri, Mysore – 570 006.

Printed and published on behalf of Karnataka State Open University, Mysore-570 006 by the Registrar
(Administration)- 2024
TABLE OF CONTENTS

BLOCK 1 INTRODUCTION TO C PROGRAMMING PAGE NO.


UNIT- 1 Introduction, Overview of the C Language, History and Features 1-17
UNIT-2 The C language and its advantages, Structure of A C program, Writing C program,C 18-35
tokens and identifiers, Data types and variables, Variable declaration in C, Constants
in C, Constant declaration in C
UNIT-3 Operators and expressions, Library functions, Type conversion in C 36-61
UNIT-4 Control structures, Goto statement, If statement and if-else statement, Nesting of if 62-81
statement, Switch statement, While and do-while loop,For loop, Break and
continue statement
BLOCK II FUNCTIONS
UNIT-5 Graphical Representation, The Need for a Function, Types of C Function, Prototype 82-106
of Function, Calling a Function
UNIT-6 Basics of Array, Pointer Declaration, The & and * Operators, Passing Pointers to a 107-124
Function, Operations on Pointers, Pointer Arithmetic, Pointers & Array
UNIT-7 125-133
Declaration and Initialization of String, Reading String from Terminal, Writing
String to screen, Arithmetic Operations on String, String Handling Function
UNIT-8 Structure and Unions, Structure Variable Declaration, Accessing Members of 134-153
Structure, Nested Structure, Structure and Functions, Union-Defining Structure,
Array of structure, Structure assignment, Structures as Function
Arguments,Pointers to structures, Typedefs, Unions, Bit fields
BLOCK III INPUT AND OUTPUT
UNIT-9 Input and output, The printf () function, The scanf () function, Getchar () and 154-177
Putchar() function, Gets() and puts() function, File handling in C
UNIT-10 Typedef and enumeration in c, Typedef in C, Enumeration in C 178- 194
UNIT-11 Bitwise operation, Bitwise operators 195-206

UNIT-12 Dynamic memory allocation, Malloc () method, Calloc () method, Free () method,
207-228
Realloc() method
BLOCKIV
LINKED LISTS
UNIT-13 Singly Linked list, Circular linked List, doubly linked list 229-258

UNIT-14 Stack, QUEUE, Implementation of Stack and QUEUE using array, Implementation 259-277
of stack and queue using linked list
UNIT-15 Recursion 278-283
UNIT-16 Structure, Union, function pointers, Handling errors and exceptions 284-310
Preface

This book is devoted to practical C programming. C is currently the premier


language for software developers. That’s because it’s widely distributed and standard.
Newer languages are available, such as C++, but these are still evolving. C is still the
language of choice for robust, portable programming. This book emphasizes the
skills you will need to do real-world programming. It teaches you not only the
mechanics of the C language, but the entire life cycle of a C program as well
(including the program’s conception, design, code, methods, debugging, release,
documentation, maintenance, and revision).

Good style is emphasized. To create a good program, you must do more than just type
in code. It is an art in which writing and programming skills blend themselves
together to form a masterpiece. True art can be created. A well-written program not
only functions correctly, but is simple and easy to understand. Comments allow the
programmer to include descriptive text inside the program. When clearly written, a
commented program is highly prized. A program should be as simple as possible. A
programmer should avoid clever tricks. This book stresses simple, practical rules. For
example, there are 15 operator precedence rules in C. These can be simplified into
two rules:
This book is written for people with no previous programming experience or
programmers who already know C and want to improve their style and reliability.
You should have access to a computer and know how to use the basic functions such
as a text editor and the filesystem. Specific instructions are given for producing and
running programs using the UNIX operating system with a generic cc compiler or the
Free Software Foundation’s gcc compiler. For MS- DOS/Windows users,
instructions are included for Borland C++, Turbo C++, and Microsoft Visual C++.
(These compilers compile both C and C++ code.) The book also gives examples of
using the programming utility make for automated program production.
UNIT-1

INTRODUCTION TO C PROGRAMMING
Structure:
1.0 Objectives
1.1 Introduction
1.2 Overview of the C Language, History and Features
1.3 Summary
1.4 Keywords
1.5 Questions for self-study
1.6 References

1.0 OBJECTIVES

After studying this unit, you will be able to

 Describe the Overview of the C Language,


 Analyze the History and Features

1.1 INTRODUCTION

A programming language is a set of symbols, grammars and rules (said to be syntax and
semantics of language). with the help of these, you will be able to translate algorithms to
programs that will be executed by the computer. The programmer communicates with a
machine using programming languages. Most of the programs have a highly structured set
of rules. The programming languages are classified in to machine language, assembly
language, high level language. Assembly language and high-level language programmes
are translated in to machine language using language translators: interpreter, assembler
and compiler. Algorithm and flowchart are used as aid to understand the program logic.

1
A computer or a system is operated by given a set of rules and instruction to perform some
tasks. These set of rules and instructions are able to control the working of computer or
any automated and/or manipulated machine. To control the computer system using these
sequential set of grammatical rules are known as programming language. A programming
language is a vocabulary and a set of grammatical rules for instructing a computer system
to perform any specific task. Hence, we can say that a programming language plays a very
important role to control and operate a computer system. The main classifications of
programming languages are:

o Machine Languages
o Assembly Languages
o High level Languages

 Machine Language:

Machine language is a collection of binary digits (bits) that the computer reads and
interprets. Machine language is the only language that computer understands. It is the
lowest level and named as first generation of programming language. It is a language that
supports the machine side of the programming but difficult for human being to write and
remember the bit’s pattern. It consists of (binary) zeros and ones. Each instruction in a
program is represented by a numeric code, and numerical addresses are used throughout
the program to refer to memory locations in the computer’s memory.
E.g.; 101100111 is considered as a machine language instruction.

 Advantages of machine level language:

o Machine level languages are directly interacting with computer system.

o There is no requirement of language translators.

o It takes very less time to execute a program, because there is no conversion take
place.

Disadvantages of machine language:

 Its machine dependent language i.e. individual program required for each machine.
2
 To develop a program in machine language, it’s too hard to understand and
program.
 Its time consuming to develop new programs.
 Debugging process is very hard because of finding errors process is typical.
 Machine language is not portable language.

Assembly language:

Assembly language is easier to use than machine language. It is a middle level and named
as second-generation programming language. An assembler is useful for detecting
programming errors. Programmers do not have the absolute address of data items.
Assembly language encourage modular programming. It uses mnemonic codes instead of
bit pattern for instructions. The programs written are machine dependent. Here assemblers
are used to translate assembly language code to machine language.
Example for assembly language program:

Move a,b Add c Store b


Advantages of Assembly language:
 It is easily understood by human because it uses statements instead of binary digits.
 To develop a program, it takes less time.
 Debugging is easy.
Disadvantages of Assembly language:
 It is a machine dependent language, hence the program designed for one machine is
not usable for another machine. Say the assembly code for microprocessor 8085 is
different from that of microprocessor 8086.
 Programmer should learn the mnemonic codes of each machine.

High level language:


High level language is a language that supports the human and the application sides of the
programming. It is known as third generation programming language. Here the
instructions are English like statements. Unlike assembly language, which is a machine
dependent language, High

3
level language programs are machine independent. A line in a high-level language can
execute powerful operations and corresponds to tens, or hundreds, of instructions at the
machine level. Examples of high-level languages are BASIC, FORTRAN, C, COBOL,
PASCAL, C ++, JAVA.

Advantages of high-level language:


 Its logic and structure are much easier to understand.
 Debugging is easier compare to other languages.

 Less time consuming to writing new programs.

 HLL are described as being portable language.


Disadvantages of high-level language:
 HLL programming language take more space compare to other MLL (machine
level language) and/or ALL (Assembly level language).
 This programming language execute slowly.

Example:
#include<stdio.h> Int a; Scanf(“%d”, &a);

STRUCTURED PROGRAMMING

It can be defined as a programming approach in which the program is made as a single structure. It is an
approach to writing programs that are easier to test, debug, modify and maintain by enforcing a modular
approach which breaks a large complex problem into sub- problems. It is also called as modular
programming. The languages that support Structured programming approach are:
C
C++
Java
C#
..etc

4
In the Assembly languages like Microprocessor 8085, etc., the statements do not get executed in a
structured manner. It allows jump statements like GOTO. So, the program flow might be random. The
structured program consists of well-structured and separated modules. But the entry and exit in a
Structured program is a single-time event. It means that the program uses single-entry and single-exit
elements. Therefore, a structured program is well maintained, neat and clean program. This is the reason
why the Structured Programming Approach is well accepted in the programming [Link] structured
program mainly consists of three types of elements:

Sequence Statements
Selection Statements
Iteration Statements
Sequence statements: Executes list of statements in order one after the other in sequence. It includes the
simple assignment statement, read and write statements.

Example:
Int a,b;
Scanf(“%d”,&a);
Printf(“a=%d”,a);
b=a;
Selection statements:
In this structure, given one or more blocks of statements, based on decision, branches to a

5
particular block of statements. This structure also follows single entry and single exit concept.

Example statements are: if-then, if-then-else statements, switch statement


Iteration statements:
Here the execution of certain statements will be repeated based on the value of the expression. Example: while,
do-while and for loop statements

Advantages of Structured Programming Approach:


1. Easier to read and understand
2. User Friendly
3. Easier to Maintain
4. Mainly problem based instead of being machine based
5. Development is easier as it requires less effort and time

6
6. Easier to Debug
7. Machine-Independent, mostly.

Disadvantages of Structured Programming Approach:


1. Since it is Machine-Independent, so it takes time to convert into machine code.
2. The converted machine code is not the same as for assembly language.
3. The program depends upon changeable factors like data-types. Therefore, it needs to
be updated with the need on the go.
4. Usually, the development in this approach takes longer time as it is language-
dependent. Whereas in the case of assembly language, the development takes lesser
time as it is fixed for the machine.

COMPILATION PROCESS

Compilation: The compiler program translates the instructions of a high-level language to a machine
level language. A separate compiler is required for every high-level language. High level language is
simply a programmer’s convenience and cannot be executed in their source. The actual high - level
program is called a source program. It is compiled (translated) to machine level language program called
object program for that machine by the compiler. Compiler compiles the full program and reports the
errors at the end of Compilation Process. Here we come across the terms source code, object code and
executable code.

Source code:
The input given to a compiler is called source code. Which is nothing but the user program written in high
level language.
Object code:
The output of the compiler is the machine level language code called object code readable by the machine.

Executable code : (also called the Binary) is the output of a linker after it processes the
object code. A machine code file can be immediately executable (i.e., runnable as a program),

7
or it might require linking with other object code files (e.g., libraries) to produce a complete executable
[Link] compilation and execution process of C program can be divided in to multiple steps:

Preprocessing: Using a Preprocessor program to convert C source code in expanded source code.
"#include" and "#define" statements will be processed and replaced actually source codesign this step.
Compilation: Using a Compiler program to convert C expanded source to assembly source code.
Assembly Using a Assembler program to convert assembly source code to object code. Linking Using
a Linker program to convert object code to executable code. Multiple units of object codes are linked
to together in this step.
Loading Using a Loader program to load the executable code into CPU for execution. Compilation

LINKERS AND LOADERS

Linking:
After all of the files are compiled, they must be "merged together" to produce a single executable file that
the user use to run the program. In C, most compiled programs produce results only with the help of
some standard programs, known as library files that reside in the

8
computer. This process is called linking. The result obtained after linking is called the executable file. The
linker′s primary function is to bind symbolic names to memory addresses. To do this, it first scans the
files and concatenates the related file sections to form one large file. Then, it makes a second pass on the
resulting file to bind symbol names to real memory [Link] are two types of linking: Static
linking and dynamic linking.

Static linking: It occurs at compilation time; Hence it occurs prior to loading a program. With static
linking the external symbols that are used by the program (e.g., function names) are resolved at compile
time.

Dynamic linking: It occurs at run time, so it occurs after or at the time of the loading of a program. With
dynamic linking the symbols are resolved either at loading time, or at run time when the symbol is
accessed.

Loader: It is a part of operating system and is responsible for loading executable files into memory and
execute them. It calculates the size of a program (instructions and data) and creates memory space for it.
It initializes various registers to initiate execution.

 Language Translators:
Assembler, interpreter and compilers are called language translators. They translate assembly and high-
level language programs to machine language. Assembler translates assembly language to machine
language. Interpreter and compiler translate high level language to machine language. The difference
between interpreter and compiler is that Interpreter translates high level language program to machine
language line by line. If an error occurs, an interpreter stops execution and reports it. whereas a compiler
reads the whole program even if it encounters several errors. The procedure for turning a program written
in C into machine Language. The process is presented in a straightforward, linear fashion but you should
recognize that these steps are repeated many times during development to correct errors and make
improvements to the code. The following are the four steps in this process.

1) Writing and editing the program


2) Compiling the program

9
3) Linking the program with the required modules
4) Executing the program

Sl. Phase Name of Code Tools File Extension


No.
1 TextEditor Source Code C Compilers .C
Edit, Notepad
Etc..,
2 Compiler Object Code C Compiler .OBJ
3 Linker Executable Code C Compiler .EXE
4 Runner Executable Code C Compiler .EXE

 Writing and Editing Programs


The software used to write programs is known as a text editor. A text editor helps us enter, change and
store character data. Once we write the program in the text editor, we save it using a filename stored with
an extension of. C. This file is referred as source code file. The Compiler which executes C programs is
called as C Compiler. Example Turbo C, Borland C, GC etc., The C Compiler is actually two separate
programs: The Preprocessor the Translator the Preprocessor reads the source code and prepares it for the
translator. While preparing the code, it scans for special instructions known as preprocessor commands.
These commands tell the preprocessor to look for special code libraries. The result of preprocessing is
called the translation unit. After the preprocessor has prepared the code for compilation, the translator
does the actual work of converting the program into machine language. The translator

10
reads the translation unit and writes the resulting object module to a file that can then be combined with
other precompiled units to form the final program. An object module is the code in the machine language.
The Linker assembles all functions, the program ‘s functions and system ‘s functions into one executable
program. To execute a program, we use an operating system command, such as run, to load the program
into primary memory and execute it.

ALGORITHM AND FLOWCHART

Algorithm is a finite sequence of instructions, each of which has a clear meaning and can be performed
with a finite amount of effort in a finite length of time. No matter what the input values may be, an
algorithm terminates after executing a finite number of instructions. We represent an algorithm using a
pseudo language that is a combination of the constructs of a programming language together with
informal English statements. The ordered set of instructions required to solve a problem is known as an
algorithm. The characteristics of a good algorithm are:
o Precision – the steps are precisely stated (defined).

o Uniqueness – results of each step are uniquely defined and only depend on the input and
the result of the preceding steps.

o Finiteness – the algorithm stops after a finite number of instructions are executed.

o Input – the algorithm receives input.

o Output – the algorithm produces output.

o Generality – the algorithm applies to a set of inputs.

Example Q. Write an algorithm to find out whether the given number is odd or even. Ans.

step 1 : start

step 2 : input number

11
step 3 : rem=number mod 2

step 4 : if rem=0 then print "number even" else print "number odd" endif step

5:stop

 FLOWCHART

Flowchart is a pictorial representation of logic of the program. Flowchart is very helpful in writing
program and explaining program to others. It uses several standard symbols in the diagram.

Symbols Used in Flowchart

Different symbols are used for different statements in flowchart, For example: Input/output and decision
making has different symbols. The table below describes all the symbols that are used in making
flowchart.

Symbol Purpose Description


Flow line Used to indicate the flow of logic by connecting
symbols.
Used to represent start and end of flowchart.
Terminal(Stop/Start)
Used for input and output operation.
Input/Output
Used for airthmetic operations and data-
manipulations.
Processing
Used to represent the operation in which there
Decision are two alternatives, true and false.
Used to join different flowline
On-page Connector
Used to connect flowchart portion on different
Off-page Connector page.
Used to represent a group of statements
performing one processing task. (for function
Predefined Process/Function description)

12
Example 1: Draw a flowchart to add two numbers entered by the user.

Example2: draw flowchart to find largest of three numbers entered by the user.

13
1.2 OVERVIEW OF THE C LANGUAGE, HISTORY AND FEATURES

C has played a pivotal role in shaping today’s technological landscape. It is one of the
most popular and oldest programming languages, known for its versatility, efficiency, and
speed. It was designed as the system programming language for Unix OS but gained
popularity due to its portability and flexibility. It is a portable language, meaning written
code can easily be compiled and run on other operating systems and platforms. It is the
language of technology and innovation, powering everything from the operating system
to smartphones. It contains the applications of video games, mobile applications, and
system software. The key strength of this language is to access and manipulate the
memory address. The syntax of c language is simple, so it allows efficient memory
management. Whether you are an aspiring developer or a computer science student,
understanding C is necessary for unlocking programming secrets.

14
History: C has often been termed as a "Pseudo high level language" or a "Middle level
language" by many programmers. This is not because of its lack of programming power
but because of its capability to access the system's low-level functions. In fact, C was
invented specifically to implement UNIX. C instructions are compiled to assembly code,
therefore, depending on the complexity of the code and on the compiler optimization
capabilities, C code may run as fast as assembly. Ken Thompson created the B language
in 1969 from Martin Richard's BCPL (Basic Combined Programming Language). He
used assembly language and B to produce the initial versions of the UNIX operating
system. BCPL and B were type less languages in which variables were simply words in
memory. Dennis Ritchie of Bell Laboratories later converted B into C by retaining most
of B's syntax in 1972 and wrote the first compiler. This was implemented on DEC's PDP
11 and it was first used as the system's language for rewriting the UNIX operating
system. Later on, UNIX, its tools and C grew simultaneously. In 1978, Kernighan and
Ritchie wrote a book entitled 'The C Programming Language' that became the language
definition for almost a decade. Beginning in 1983, the ANSI X3J11 committee was asked
to standardize the C language. The result was ANSI C, a standard which was adopted in
1988. It is not forced upon any programmer, but since it is so widely accepted, it would be
economically unwise for any systems programmer or compiler writer not to conform to
the standard.

Features of C Language · C is a procedure-based programming language. This means


the program is viewed as a means to solve a problem. Various functions modules or code
blocks are thus, written to solve this problem. · C functions can accept parameters and
return values and perform variety of tasks like input from the user, displaying the
information, etc. · C is simple and easy to learn and use. The main components like built-in
functions, operators, keywords are small in number. · In C, errors are checked only at
compile time. The compiled code though has no safety checks for bad type casts, bad array
indices, or bad pointers. C works best for small projects where performance is important. ·
C contains the capability of assembly language with the features of high-level language
which can be used for creating software packages, system software etc. · C is highly
portable. C programs written on one computer can run on other computer without making
any changes in the program.

15
1.3 SUMMARY

In this unit, you have studied the C is a powerful, general-purpose, and procedural
programming language developed by Dennis Ritchie at Bell Labs in the early 1970s. It
was initially designed for developing the UNIX operating system and has since become a
foundational language in computer science and History and Features

1.4 KEYWORDS

 Overview
 C Language
 History
 Features

1.5 QUESTIONS FOR SELF STUDY

1. Explain Overview of the C Language, History and Features


2. Explain different levels of language.
3. Write the advantages and disadvantages of different levels of languages.
4. Write a note on language translators.
5. Distinguish between compiler and interpreter.
6. Define algorithm. Explain its characteristics.
7. Write an algorithm to find largest of three numbers.
8. Define flowchart. Explain the symbols used in writing flowchart.
9. Explain the steps in execution of C language program.

1.6 REFERENCES

 Programming In ANSI C by E Balagurusamy


 The C Programming Language (Ansi C Version) by Brian W. Kernighan,
Dennis M. Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Programming in C - Gottfried B.S., TMH

16
UNIT-2

C LANGUAGE FUNDAMENTALS
Structure:
2.0 Objectives
2.1 Introduction
2.2 The C language and its advantages
2.3 Structure of A C program
2.4 Writing C program
2.5 C tokens and identifiers
2.6 Data types and variables
2.7 Variable declaration in C
2.8 Constants in C
2.9 Constant declaration in C
2.10 Summary
2.11 Keywords
2.12 Questions for self-study
2.13 References

2.0 OBJECTIVES
After studying this unit, you will be able to

 Understand the advantages of C language.


 Explain the structure of C program

2.1 INTRODUCTION

C was developed by Dennis Ritchie at Bell Laboratories in 1972. Most of its principles and ideas were
taken from the earlier language B, BCPL and CPL. CPL was developed jointly between the Mathematical
Laboratory at the University of Cambridge and the University of London Computer Unit in 1960s. CPL
(Combined Programming Language) was developed with the purpose of creating a language that was
capable of both machine independent programming and would allow the programmer to control the
behavior of individual bits of information.

17
But the CPL was too large for use in many applications. In 1967, BCPL (Basic Combined Programming
Language) was created as a scaled down version of CPL while still retaining its basic features. This process
was continued by Ken Thompson. He made B Language during working at Bell Labs. B Language was a scaled
down version of BCPL. B Language was written for the systems programming. In 1972, a co-worker of Ken
Thompson, Dennis Ritchie developed C Language by taking some of the generality found in BCPL to the B
language. The original PDP-11 version of the UNIX system was developed in assembly language. In 1973, C
language had become powerful enough that most of the UNIX kernel was rewritten in C. This was one of the
first operating system kernels implemented in a language other than assembly. During the rest of the 1970's, C
spread throughout many colleges and universities because of its close ties to UNIX and the availability of C
compilers. Soon, many different organizations began using their own versions of C Language. This was
causing great compatibility problems. In 1983, the American National Standards Institute (ANSI) formed a
committee to establish a standard definition of C Language. That is known as ANSI Standard C. Today C is
the most widely used System Programming Language.

2.0 THE C LANGUAGE AND ITS ADVANTAGES


C is the most popular programming language, C has many advantages
1. Modularity.
2. Portability.
3. Extendibility.
4. Speed.
5. Flexibility

18
Modularity: Ability to breakdown a large module into manageable sub modules called as modularity,
which is an important feature of structured programming languages.
Advantages:
 Projects can be completed in time.
 Debugging will be easier and faster.
Portability: The ability to port i.e., to install the software in different platform is called portability.
Highest degree of portability: ‘C’ language offers highest degree of portability i.e., percentage of changes
to be made to the sources code is at minimum when the software is to be loaded in another platform.
Percentage of changes to the source code is minimum. The software that is 100% portable is also called as
platform independent software or architecture neutral software. E.g.: Java.
Extendibility: Ability to extend the existing software by adding new features is called as extendibility.
SPEED:‘C’ is also called as middle level language because programs written in ‘c’ language run at the
speeds matching to that of the same programs written in assembly language so ‘c’ language has both the
merits of high level and middle level language and because if this featureit is mainly used in developing
system software.
Flexibility: Key words or reverse words
ANSI C has 32 reverse words
‘C’ language has right number of reverse words which allows the programmers to have complete control on the
language.
‘C’ is also called as programmer’s language since it allows programmers to induce creativeness into the
programmers.

2.1 STRUCTURE OF A C PROGRAM


C language is very popular language among all the languages. The structure of a C program is a protocol
(rules) to the programmer, while writing a C program. The general basic structure of C program is shown
in the figure below. The whole program is controlled within main ( ) along with left brace denoted by “{”
and right braces denoted by “}”. If you need to declare local variables and executable program structures
are enclosed within “{” and “}” is called the body ofthe main

19
function. The main ( ) function can be preceded by documentation, preprocessorstatements and global
declarations.

Documentations
The documentation section consist of a set of comment lines giving the name of the program, another name
and other details, which the programmer would like to use later.
Preprocessor Statements

The preprocessor statements begin with # symbol and are also called the preprocessor directive. These
statements instruct the compiler to include C preprocessors such as header files and symbolic constants
before compiling the C program. Some of the preprocessor statements are listed below.

20
Global Declarations
The variables are declared before the main ( ) function as well as user defined functions are called global
variables. These global variables can be accessed by all the user defined functions including main ( )
function.

The main ( ) function


Each and Every C program should contain only one main ( ). The C program execution starts with main ( )
function. No C program is executed without the main function. The main ( ) function should be written in
small (lowercase) letters and it should not be terminated bysemicolon. Main ( ) executes user defined
program statements, library functions and user definedfunctions and all these statements should be
enclosed within left and right braces.

Braces
Every C program should have a pair of curly braces ({, }). The left braces indicates thebeginning of the
main ( ) function and the right braces indicates the end of the main ( ) function. These braces can also be
used to indicate the user-defined functions beginning and ending. Thesetwo braces can also be used in
compound statements.

Local Declarations
The variable declaration is a part of C program and all the variables are used in main ( ) function should
be declared in the local declaration section is called local variables. Not only variables, we can also
declare arrays, functions, pointers etc. These variables can also be initialized with basic data types.

21
For Example

Main ( )
{
int sum = 0; int
x;
float y;
}

Here, the variable sum is declared as integer variable and it is initialized to zero. Other variables declared as int
and float and these variables inside any function are called local variables.

 Program statements
These statements are building blocks of a program. They represent instructions to the computer to
perform a specific task (operations). An instruction may contain an input-output statements, arithmetic
statements, control statements, simple assignment statements and any other statements and it also includes
comments that are enclosed within /* and */. The comment statements are not compiled and executed
and each executable statement should be terminated with semicolon.

 User defined functions


These are subprograms, generally, a subprogram is a function and these functions are written by the user
are called user; defined functions. These functions are performed by user specific tasks and this also
contains set of program statements. They may be written before or after a main () function and called
within main () function. This is an optional to the programmer.

2.2 WRITING C PROGRAMS


Here is your first c program. Write carefully because C Language is a case sensitive language. #include
<stdio.h>
void main()
{
printf("Hello World\n Welcome to C Programming");
}

Press ALT+F9 to compile your program. If you have any error in your program, you will get the message,
remove your errors and then execute your program you will got the output.
Hello World
Welcome to C Programming

22
Some other sample C programs
/*Display Current date and time*/ /* addition of 2 numbers */
#include <stdio.h> #include<stdio.h>
#include <time.h> #include<conio.h>
void main() void main()
{ {
time_t t; int a, b,c;
time(&t); c=0;
clrscr(); a=3;
printf("Today's date and time : s",ctime(&t)); b=4;
getch(); c = a + b:
} printf(“result of addition = %d”,c);
}
2.3 C TOKENS AND IDENTIFIERS

Every word in C language is a keyword or an identifier/variable. Keywords in C language cannot be used


as a variable name. They are specifically used by the compiler for its own purpose and they serve as
building blocks of a c program.A C program consists of various tokens and a token is either a
keyword, an identifier, a constant, a string literal, or a symbol. C tokens are the basic buildings
blocks in C language which are constructed together to write a C program. Each and every smallest
individual unit in a C program is known as C tokens. C tokens are of six types. They are

Keywords (eg: int, while),


Identifiers (eg: main, total),
Constants (eg: 10, 20),
Strings (eg: ―total‖, ―hello‖),
Special symbols (eg: (), {}),
Operators (eg: +, /,-,*)

For example, the following C statement consists of five tokens:

Printf (“Hello, world! \n”)

23
The individual tokens are:

Printf (“Hello, World! \n”);


Semicolons;

In C program, the semicolon is a statement terminator. That is, each individual statement must be ended with a
semicolon. It indicates the end of one logical [Link] example, following are two different statements:

Printf (“Hello, World! \n”);


Return ();

Comments

Comments are like helping text in your C program and they are ignored by the compiler. They start with
/* and terminates with the characters */ as shown below:

/* my first program in C*/

You cannot have comments within comments and they do not occur within a string or character literals.

Identifiers
o Identifiers are the names given to variables, classes, methods and interfaces.
o It must be a whole word and starts with either an alphabet or an underscore.
o They are case sensitive.
o No commas or blanks are allowed in it
o No special symbol other than an underscore can be used in it.
Ex.: marks gracesem1_rollno alpha
Keywords
o Keywords are words that have special meaning to the C compiler.
o An identifier cannot have the same spelling and case as a C keyword.
o C makes use of only 32 keywords or reserved words which combine withthe formal
syntax to the form the C programming language.
o All keywords in C are written in lower case.
o A keyword may not be used as a variable name.

Whitespace means characters that exist in a file but appear blank in a printed listing of a file (or
traditionally did appear blank, several decades ago). The C language requires whitespace in order to

24
separate two consecutive identifiers, or to separate an identifier from a numeric constant. Other than that,
and a few special situations described later, whitespace is optional; you can put it in when you wish, to
make the code easier to [Link] and tab in C code are treated as whitespace characters. So are line
breaks. You can represent a line break with the newline character (also called linefeed or LF), CR
(carriage return), or the CRLF sequence (two characters: carriage return followed by a newline character).

The formfeed character, Control-L, was traditionally used to divide a file into pages. It is still used this
way in source code, and the tools that generate nice printouts of source code still start a new page after
each “formfeed” character. Dividing code into pages separated by formfeed characters is a good way to
break it up into comprehensible pieces and show other programmers where they start and end. The vertical
tab character, Control-K, was traditionally used to make printing advance down to the next section of a
page. We know of no particular reason to use it in source code, but it is still accepted as whitespace in
[Link] are also syntactically equivalent to whitespace. Adding a whitespace character in a scanf()
function causes it to read elements and ignore all the whitespaces as much as it can and search for a
non-whitespace character to proceed.

scanf("%d ");
scanf(" %d");
scanf("%d\n"); This is different
from scanf("%d"); function.
Example 1: The scanf function after reading the number starts reading further until it finds a non-
whitespace character on the input and prints the first number that was typed.
Adding whitespace or "\n" after format specifier in scanf function
scanf("%d ");
or
scanf("%d\n", );

25
2.4 DATA TYPES AND VARIABLES
The area of the program where that variable is valid, the amount of time that a variable is retained, as well
as where it can be accessed from, depends on its specified location and type. The life span of the
variable, i.e., the length of time that the variable remains in memory. The programmer has to be very
much aware of the type of the variable he/she going to use. Each and every sort of scenario requires
different type of scope. For example, suppose the variable which should remain constant and also required
by external functions then it is not good practice to declare same variable again and again instead of that it
may be called as a global variable.

On the other hand, for the sake security reason some variable has be visible in only one function can be
treated and declared as static variable. This section of the unit will be discussing thoroughly in forth
coming units when we introduce storage class and different types of variables. The basic data structure
used in C programs is a number. C provides for two types of numbers - integers and floating point.
Computer operations that involve text (characters, words or strings) still manipulate numbers. Each data
item used by a program must have a data type. The basic data types provided by C are shown in Table 1.
Each data type represents a different kind of number. You must choose an appropriate type for the kind of
number you need in the variable declaration section of the program.

o In c, there are three types of data-primary, derived and user-defined


o In C language the system has to know before-hand, the type of numbers or characters
being used in the program. These are called data types. There are many data types in C
language.
o A C programmer has to use appropriate data type as per his requirement.
C language data types can be broadly classified as
a) Primary data type-int, char, float, double
b) Derived data type(secondary)- array, function, pointer, structure, union
c) User-defined data type-typedef, Enum

26
Primary Data types:
char: The most basic data type in C. It stores a single character and requires a single byte of
memory in almost all compilers.
int: As the name suggests, an int variable is used to store an integer.
float: It is used to store decimal numbers (numbers with floating point value) with single precision.
double: It is used to store decimal numbers (numbers with floating point value) with double
precision.
Integer Data Type
 Integers are numbers without decimal point
 Integers are whole numbers with a range of values, range of values are machine
dependent.
 Generally, an integer occupies 2 bytes memory space and its value range limited to
- 32768 to +32767 (that is, -215 to +215-1).
The following table provides the details of standard integer types with their storage sizesand value
ranges –

Type Storage size Value range

-32,768 to 32,767 or -2,147,483,648 to


Int 2 or 4 bytes
2,147,483,647

unsigned int 2 or 4 bytes 0 to 65,535 or 0 to 4,294,967,295

Short 2 bytes -32,768 to 32,767

unsigned short 2 bytes 0 to 65,535

Long 8 bytes or (4bytes for 32 bit -9223372036854775808 to


OS) 9223372036854775807

27
unsigned long 8 bytes 0 to 18446744073709551615
Format specifier for Int is %d.
For long int - %ld.
for short int-%hd.
Float and double data types: Real numbers are stored with the data type float and double.

Type Storage size Value range Precision

Float 4 bytes 1.2E-38 to 3.4E+38 6 decimal places

Double 8 bytes 2.3E-308 to 1.7E+308 15 decimal places

long double 10 bytes 3.4E-4932 to 1.1E+4932 19 decimal places

The format specifier and the number of bytes occupied by the data types of real number are as shown in
table:

Data Type Memory (bytes) Format Specifier

float 4 %f

double 8 %lf

long double
16 %Lf

Character data type: Keyword char is used for declaring character type variables. For example,

Char test = ‘h’;

The size of the character variable is 1 byte. Format specifier for char type data is %c.

28
2.7 VARIABLE DECLARATION IN C

A variable is nothing but a name given to a storage area that our programs can manipulate. Each
variable in C has a specific type, which determines the size and layout of the variable's memory; the
range of values that can be stored within that memory; and the set of operations that can be applied to
the variable.

 Rules to form the variable name:


The name of a variable can be composed of letters, digits, and the underscore character. It must
begin with either a letter or an underscore. Upper and lowercase letters are distinct because C is case-
sensitive. There will be following basic variable types –

Type Description
char Typically, a single octet (one byte). This is an integer type.
int The most natural size of integer for the machine.
float A single-precision floating point value.
double A double-precision floating point value.
void Represents the absence of type.

 Variable Declaration in C

A variable declaration provides assurance to the compiler that there exists a variable with the
given type and name so that the compiler can proceed for further compilation without requiring
the complete detail about the variable. A variable definition has its meaning at the time of
compilation only; the compiler needs actual variable definition at the time of linking the
program. A variable declaration is useful when multiple files are used. The syntax for declaration
of variable is as follows:

 type variable list;


Here, type must be a valid C data type including char, int, float, double, bool, or any user-
defined object; and variable list may consist of one or more identifier names separated by
commas. Some valid declarations are shown here −

int i, j, k;
char c, ch;

29
float f, salary;
double d;

The line int i, j, k; declares and defines the variables i, j, and k; which instruct the compiler to create
variables named i, j and k of type [Link] will use extern keyword to declare a variable at any place. Though
you can declare a variable multiple times in your C program but it can be defined only once in a file, a
function ora block of code.

 Example
Try following example, where variables have been declared at the top, but they have been defined and
initialized inside the main function:

#include <stdio.h>

// Variable declaration:
extern int a, b;
extern int c;
extern float f;

int main ()
{
/* variable definition: */ int a, b;
int c; float
f;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
printf("value of c : %d \n", c); f =
70.0/3.0;

printf("value of f : %f \n", f);

return 0;

30
When the above code is compiled and executed, it produces the following result:

value of c : 30
value of f : 23.333334

Same concept applies on function declaration where you provide a function name at the time of its
declaration and its actual definition can be given anywhere else. For example:

// function declaration
int func();
int main()
{
// function call int i
= func();
}
// function definition int
func()
{
return 0;
}

Variables can be initialized (assigned an initial value) in their declaration. The initializer consists of an
equal sign followed by a constant expression as follows –
type variable_name = value; Some
examples are –
extern int d = 3, f = 5; // declaration of d and f.
int d = 3, f = 5; // definition and initializing d and f. byte z =
22; // definition and initializes z.
char x = 'x'; // the variable x has the value 'x'.

31
For definition without an initializer: variables with static storage duration are implicitly initialized with
NULL (all bytes have the value 0); the initial value of all other variables is undefined.

2.8 CONSTANTS IN C
A constant value is the one which does not change during the execution of a program. C supports several types
of constants.
1. Integer Constants
2. Real Constants
3. Single Character Constants
4. String Constants
Integer Constants
An integer constant is a sequence of digits. There are 3 types of integers namely decimal integer, octal
integers and hexadecimal integer.

Decimal Integers consists of a set of digits 0 to 9 preceded by an optional + or - sign. Spaces, commas and
non digit characters are not permitted between digits.
Example for valid decimal integer constants are
123, -3, 0, 562321, + 78
Some examples for invalid integer constants are
15 750, 20,000, Rs. 1000
Octal Integers constant consists of any combination of digits from 0 through 7 with a O at the beginning.
Some examples of octal integers are
O26, O, O347, O676
Hexadecimal integer constant is preceded by OX or Ox, they may contain alphabets from A to F or a to f.
The alphabets A to F refers to 10 to 15 in decimal digits.
Example of valid hexadecimal integers are
OX2, OX8C, OXbcd, Ox
1. Real Constants
Real Constants consists of a fractional part in their representation. Integer constants are inadequate to
represent quantities that vary continuously. These quantities are represented by numbers containing
fractional parts like 26.083.

32
Example of real constants are
0.0026, -0.97, 435.29, +487.0
Real Numbers can also be represented by exponential notation. The general form for exponential notation
is mantissa exponent. The mantissa is either a real number expressed in decimal notation or an integer.
The exponent is an integer number with an optional plus or minus sign.

 Single Character Constants


A Single Character constant represent a single character which is enclosed in a pair of quotation symbols.
Example for character constants are 8

'5', 'x', ';', ' '


All character constants have an equivalent integer value which is called ASCII Values.

 String Constants
String constant is a set of characters enclosed in double quotation marks. The characters in a string
constant sequence may be an alphabet, number, special character and blank space.
Example of string constants are
"VISHAL", "1234", "God Bless", "!. ......... ?"

2.9 CONSTANT DECLARATION IN C

The names given to constants must conform to the rules for the formation of identifiers as defined above.
The following constant declaration
const int days_in_year = 365;
defines an integer constant day_in_year which has the value 365. Later in the program the identifier
days_in_year can be used instead of the integer 365, making the program far more [Link] general
form of a constant declaration is:

const type constant-identifier = value;


type is the type of the constant, constant-identifier is the identifier chosen for the constant, which must be
distinct from all identifiers for variables, and value is an expression involving only constant quantities that
gives the constant its value. It is not possible to declare a constant without giving it an initial value.

33
Constant definitions are, by convention, usually placed before variable declarations. There is no limit on
how many constant declarations can be used in a program. Several constant identifiers of the same type
can be declared in the same constant declaration by separating each declaration by a comma. Thus
const int days_in_year = 365,
days_in_leap_year = 366;

2.10 SUMMARY

At the end of this unit, we have discussed about the basic concepts of C programming viz., c tokens:
Identifiers, Keywords, Variables and constants. Data types are mainly classified in to three groups: primary,
derived and user-defined datatypes. In the group primary data type, we have int, float, double and char. All
these data types are combined with signed/unsigned and short/long modifiers.

2.11 KEYWORDS

 Identifier
 Variable
 Keyword
 int, float

2.12 QUESTIONS FOR SELF STUDY

1. Explain the terms variable, keyword, constant and constant which are supported in C
programming.
2. Briefly describe the variable declaration in C program.
3. Discuss about the data type supported in C language.
4. Distinguish between local and global declaration.

34
2.13 REFERENCES

 Programming In ANSI C by E Balagurusamy


 The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Programming in C - Gottfried B.S., TMH
 Programming in ANSI C - Balaguruswami, TMH
 C The Complete Reference - [Link], TMH
 Let us C - [Link], BPB Publications
 A Structured Programming Approach using C – B.A. Forouzan& R.F. Gillberg,
THOMSON Indian Edition
 Computer fundamentals and programming in C – PradipDey&Manas Ghosh, OXFORD
 P. K. Sinha &PritiSinha , “Computer Fundamentals”, BPB Publications, 2007.
 Dr. Anita Goel, Computer Fundamentals, Pearson Education, 2010

35
UNIT-3

OPERATORS AND EXPRESSIONS

Structure:
3.0 Objectives
3.1 Introduction

3.2 Assignment statement


3.3 operators and their precedence rule
3.3.1 Unary operators
3.3.2 arithmetic operators
3.3.3 relational operators
3.3.4 logical operators
3.3.5 bitwise operators
3.3.6 assignment operators
3.3.7 increment and decrement operators
3.3.8 conditional operator
3.3.9 size of () operator
3.3.10 special operator
3.3.11 Expression
3.3.12 Operators’ precedence rule
3.4 Library functions
3.5 Type conversion in C
3.6 Summary
3.7 Keywords
3.8 Questions for self-study
3.9 References

3.0 OBJECTIVES
After studying this unit, you will be able to
 Explain the rich set of operators supported by C
 Explain the operator’s precedence rule
 Explain Expression in C

36
3.1 INTRODUCTION

In this unit, you are going to study the rich set of operators available in C, formation of expressions using
arithmetic operators, logical operators. In an expression, if more than one type of operator is appearing
then their order of evaluation will be learned in this unit. Assignment statement is the simple statement
which assigns the value of the expression/ value present on right hand side of the = sign to the variable
present on left hand side of equal sign. The necessary condition is that the date type of the value should be
same as that of the variable declared in declaration section. If the data type does not match, then type
casting is done.

In C, we have rich set of operators. An operator is a symbol that tells the compiler to perform specific
mathematical or logical functions and it is a symbol which operates on a variable or value. There are types
of operators like arithmetic, logical, conditional, relational, bitwise, assignment operators etc. Some
special types of operators are also present in C like size of(), Pointer operator, Reference operator etc.

3.2 ASSIGNMENT STATEMENT

In C programming, an assignment statement sets and/or re-sets the value stored in the storage location(s)
denoted by a variable name; in other words, it copies the value into the variable. In most imperative
programming languages, the assignment statement (or expression) is a fundamental construct.
Assignments typically allow a variable to hold different values at different times during its life-span and
scope. However, some languages (primarily strictly functional) do not allow that kind of "destructive"
reassignment, as it might imply changes of non-local state. The purpose is to enforce referential
transparency, i.e. functions that do not depend on the state of some variable(s), but produce the same
results for a given set of parametric inputs at any point in time. Assignment statement is a simple
statement having the following form: variable = expression
The expression to the right of the assignment operator is evaluated and the result is stored to the
variable on the left. Here are some rules:

37
 The expression is evaluated first with the rules discussed
 If the type of the expression is identical to that of the variable, the result is saved in the
variable.
 Otherwise, the result is converted to the type of the variable and saved there.
o If the type of the variable is INTEGER while the type of the result is REAL, the
fractional part, including the decimal point, is removed making it an integer result.
o If the type of the variable is REAL while the type of the result is INTEGER, then
a decimal point is appended to the integer making it a real number.
 Once the variable receives a new value, the original one disappears and is no more
available.

Examples:

 The program segment below declares three INTEGER variables. The first assignment
statement saves an integer value to variable Unit. The second saves a real number 100.99
into variable Amount. However, since Amount is an INTEGER variable, the real value
100.99 is converted to an integer, 100, and saved into Amount. Thus, after the second assignment
completes variable Amount holds 100. The third assignment computes the single mode
expression, yielding a result 500 = 5*100. Thus, variable Total receives 500. int Total, Amount,
Unit;
Unit = 5;
Amount = 100.99;
Total = Unit * Amount;
 INT A = 3, B = 5, C;
C = A;
A = B;
B = C;
The following swaps the values in A and B, with the help of C. That is, after completing the
following three assignment statements, A and B have 5 and 3, respectively.

38
Initially, A and B are initialized to 3 and 5, respectively, while C is uninitialized. The first
assignment statement puts A's value into C, making A=3, B=5 and C=3.
The second assignment statements put B's value into A. This destroys A's original value
2. After this, A = 5, B = 5 and C = 3.
The third assignment statement puts C's value into B. This makes A=5, B=3 and C=3. Therefore,
the values in A and B are exchanged.

3.3 OPERATORS AND THEIR PRECEDENCE RULE

C language offers many types of operators. They are,

1. Arithmetic operators
2. Assignment operators
3. Relational operators
4. Logical operators
5. Bit wise operators
6. Conditional operators (ternary operators)
7. Increment/decrement operators
8. Special operators

[Link] Types of Operators Description


1 Arithmetic_operators These are used to perform mathematical
calculations like addition, subtraction,
multiplication, division and modulus
2 Assignment_operators These are used to assign the values for the
variables in C programs.
3 Relational operators These operators are used to compare the value of
two variables.
4 Logical operators These operators are used to perform logical
operations on the given two variables.

5 Bit wise operators These operators are used to perform bit


operations on given two variables.
6 Conditional (ternary) Conditional operators return one value if
operators condition is true and returns another value
is condition is false.

39
7 Increment/decrement These operators are used to either increase
operators or decrease the value of the variable by
one.
8 Special operators &, *, sizeof( ) and ternary operators.

3.3.1 UNARY OPERATOR


These are the type of operators that act upon just a single operand for producing a new value. All the
unary operators have equal precedence, and their associativity is from right to left. When we combine the
unary operator with an operand, we get the unary expression.
There are following types of unary operators found in the C language:

 unary minus (-)


 unary plus (+)
 decrement (- -)
 increment (++)
 NOT (!)
 sizeof ()
 Address of operator (&)
Unary Minus
This operator changes the sign of any given argument. It means that a positive number will become
negative, and a negative number will become positive.
But the unary minus is different from that of the subtractor operator. It is because we require two operands for
subtraction.
int p = 20;
int q = -p; // q = -20
Unary Plus
This operator changes the sign of any negative argument. It means that a negative number will become
positive, and a positive number will also become positive.
But the unary minus is different from that of the subtractor operator. It is because we require two operands for
subtraction.
int p = -20;
int q = +p; // q = 20

40
NOT (!)
We use this operator for reversing the logical state of the available operand. It means that the logical NOT
operator will make an available condition to be false if it is already true.
In simple words,
 If p is true, then !p will be false.
 If p is false, then !p will be true.
Increment
We use this operator to increment the overall value of any given variable by a value of 1. We can perform
increment using two major ways:
 Prefix increment
 Postfix Increment
Prefix Increment
The operator in this method precedes the given operand (Example, ++p). Thus, the value of the operand gets
altered before we finally use it.
For instance,
int p = 1;
int q = ++p; // q = 2
Postfix Increment
The operator in this method follows the given operand (Example, p++). Thus, the value of the available
operand gets altered after we use it.
For instance,
int p = 1;
int q = p++; // q = 1 int
r = p; // r = 2
Decrement
We use this operator to decrement the overall value of any given variable by a value of 1. We can
perform decrement using two major ways:
Prefix Decrement
The operator in this method precedes the given operand (Example, –p). Thus, the value of the operand gets
altered before we finally use it.
For instance,

41
int p = 1;
int q = –p; // q = 0
Postfix Decrement
The operator in this method follows the given operand (Example, p–). Thus, the value of the available
operand gets altered after we use it.
For instance,
int p = 1;
int q = p–; // q = 1
int r = p; // r = 0
Address of Operator (&)
This type of operator provides the user with the address of any variable. The address of operator is used to
return the address (memory address) of any variable. The addresses that are returned using this operator
are called pointers. It is because they point towards the variable present in the memory.
For instance,
& gives an address on variable n int
a;
int *ptr;
ptr = &a; // address of a is copied to the location ptr.

3.3.2 ARITHMETIC OPERATORS

The arithmetic operators used in C to form arithmetic expressions are


operator Meaning Precedence of
operators
/ Division 1
% Modulo Division 1
* Multiplication 1
+ Addition 2
- Subtraction 2

42
*, / and % will be performed before + or - in any expression. Parenthesis can be used to force a different
order of evaluation to this. Where division is performed between two integers, the result will be an
integer, with remainder discarded. Modulo reduction is only meaningful between integers. If a program is
ever required to divide a number by zero, this will cause an error, usually causing the program to crash.
/ Operator gives the real value after complete division.
% operator gives the remainder after division (integer value).
The order of precedence of operators can be altered by using parenthesis and in case of nested
parenthesis, innermost parenthesis is evaluated first.
Example:-
Assume that integer variable A holds value 10 and variable B holds 20, then A+B
gives value 30
A-B gives value -10
B/A gives value 2 B%A
gives value 0
EXAMPLE PROGRAM FOR C ARITHMETIC OPERATORS
In this example program, two values ―40‖ and ―20‖ are used to perform arithmetic operations such as
addition, subtraction, multiplication, division, modulus and output is displayed for each operation.

#include <stdio.h>
int main()
{
int a=40,b=20, add,sub,mul,div,mod; add =
a+b;
sub = a-b;
mul = a*b;
div = a/b;
mod = a%b;
printf("Addition of a, b is : %d\n", add);

43
printf("Subtraction of a, b is : %d\n", sub);
printf("Multiplication of a, b is : %d\n", mul);
printf("Division of a, b is : %d\n", div); printf("Modulus of
a, b is : %d\n", mod);
}
OUTPUT:
Addition of a, b is : 60
Subtraction of a, b is : 20
Multiplication of a, b is : 800
Division of a, b is : 2 Modulus
of a, b is : 0

3.3.3 RELATIONAL OPERATORS IN C

C provides you a list of relational operators to allow you to compare data. The relational operators enable
you to check whether two variables or expressions are equal, not equal, which one is greater or less than
other...etc. The relational operators are used to form boolean expressions which return logical value either
0 or [Link] following table illustrates the relational operators in C:

Relational Operators Description

== Equal to

> Greater than

< Less than

>= Greater than or equal to

<= Less than or equal to

!= Not equal to

44
Suppose that a and b are integer variables whose values are 100 and 4, respectively. Several logical expressions
involving these variables are shown below, together with their resulting values.

Expression Interpretation Value

a<b False 0

a>b True 1

a<=b False 0

a>=b True 1

a==b False 0

a!=b True 1
7.3.4 LOGICAL OPERATORS
A Logical operator is used to combine two or more logical expressions and to negate a logical
expression. There are three logical operators in C language. They are AND, OR and NOT operators.

For example

(x < 20 )&&(x >= 10) is a logical expression with logical operator &&. &&
operator gives the result TRUE if all the expressions give TRUE value.
| | operator gives the result TRUE if any one of the expressions is TRUE.
! operator gives the negation of the expression [Link], if the expression gives true value,
!(expression) gives false value.
Suppose that a and b are integer variables whose values are 100 and 4, respectively. Then,

Expression Interpretation Value


(a>b)&&(a==100) True 1
(b>a)||(a>b) True 1
!(a>b) False 0

45
3.3.5 BITWISE OPERATORS
Bitwise operators operate on individual bits of integer (int and long) values. This is useful for writing
low-level hardware or OS code where the ordinary abstractions of numbers, characters, pointers, and so
on, are insufficient. Bit manipulation code tends to be less "portable". Code is "portable" if without any
programmer intervention it compiles and runs correctly on different types of computers. The bit wise
operations are commonly used with unsigned types. These operators perform bit wise logical operations
on values. Both operands must be of the same type and width: the resultant value will also be this type and
width.

C Bitwise Operators Description

& Bitwise AND

| Bitwise inclusive OR

^ Bitwise exclusive OR

Bitwise left shift


<<
(multiply by power of 2)

Bitwise right shift


>>
(divide by power of 2)

~ one's complement

Definition of bitwise logical operators:

Bit a Bit b a&b a|b a^b ~a


0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

Example:

Bitwise Negation
a=00000011
~a =11111100

46
Bitwise AND
a = 00000011
b = 00010110
a&b=00000010
Bitwise OR
a = 00000011
b = 00010110
a|b=00010111
Bitwise Exclusive OR
a = 00000011
b = 00010110
a^b=00010101
Right Shift
a = 0000 0011 = 3
(a<<=1) = 00000110 = 6
(a<<=2) = 00011000 = 24
(a<<=3) = 11000000 = 192
Left Shift a=11000000
=192
(a>>=1) = 01100000 = 96
(a>>=2) = 00011000 = 24
(a>>=3) = 0000 0011 = 3
Example of C Bitwise Operators
Here is a simple program that demonstrates C bitwise operators:

47
/* Purpose: Demonstrates C bitwise operators */
#include <stdio.h>
void main() {
int d1 = 4, /* binary 101 */
d2 = 6, /* binary 110 */
d3;
printf("\nd1=%d", d1); printf("\nd2=%d",
d2);
d3 = d1 & d2; /* 0101 & 0110 = 0100 (=4) */
printf("\n Bitwise AND d1 & d2 = %d", d3); d3 =
d1 | d2; /* 0101 | 0110 = 0110 (=6) */

printf("\n Bitwise OR d1 | d2 = %d", d3);

d3 = d1 ^ d2; /* 0101 & 0110 = 0010 (=2) */

printf("\n Bitwise XOR d1 ^ d2 = %d", d3);

d3 = ~d1; /* ones complement of 0000 0101 is 1111 1010 (-5) */ printf("\n

Ones complement of d1 = %d", d3);

d3 = d1 << 2; /* 0000 0101 left shift by 2 bits is 0001 0000 */

printf("\n Left shift by 2 bits d1 << 2 = %d", d3);


d3 = d1 >> 2; /* 0000 0101 right shift by 2 bits is 0000 0001 */ printf("\n
Right shift by 2 bits d1 >> 2 = %d", d3); }

3.3.6 ASSIGNMENT OPERATOR


An Assignment operator is used to form an assignment expression, which assigns the value to an
identifier. The most commonly used assignment operator is = . Assignment expressions that make use of
this operator are written in the form
Identifier op=variable
The allowed operators in the place of op are arithmetic operators +,-,*, /, %.

48
Note:- The receiving variable(LHS) should be present in the RHS expression.
So beside = operator, +=,- =, /=, %= , *= are used and they are called shorthand operators.

operator Equation Assignment operator equation


+= i=i+1 i+=1
-= i=i-10 i-=10
*= i=i*11 i*=11
/= i=i/12 i/=12
%= i=i%5 i%=5
Program to demonstrate assignment operators:
#include <stdio.h>
/* a program demonstrates C assignment operator */
void main(){
int x = 10;
/* demonstrate = operator */
int y = x;
printf("y = %d\n",y);
/* demonstrate += operator */
y += 10;
printf("y += 10;y = %d\n",y);
/* demonstrate -= operator */
y -=5;
printf("y -=5;y = %d\n",y);
/* demonstrate *= operator */
y *=4;
printf("y *=4;y = %d\n",y);
/* demonstrate /= operator */
y /=2;
printf("y /=2;y = %d\n",y);
}

49
3.3.7 INCREMENT AND DECREMENT OPERATORS
In C, ++ and -- are called increment and decrement operators respectively. Both of theseoperators are
unary operators, i.e, used on single operand. ++ adds 1 to operand and -- subtracts 1from operand
respectively. For example:
Let a=5 and b=10
a++; //a becomes 6
a--; //a becomes 5
++a; //a becomes 6
--a; //a becomes 5
These operators can be placed as a prefix or post fix as below: a++;
++a;
When used on their own (as above) the prefix and postfix have the same effect BUT within an expression there
is a subtle difference....
1. Prefix notation will increment the variable BEFORE the expression is evaluated.
2. Postfix notation will increment AFTER the expression evaluation.
Here is an example:
main () main()
{ {
int a=1; int a=1;
printf(" a is %d", ++a); printf(" a is %d", a++);
} }
In both examples, the final value of a will be 2. BUT the first example will print 2 and the second will
print 1.

50
When a++ is used as prefix (like: ++var), ++var will increment the value of var and then return it but, if
++ is used as postfix(like: var++), operator will return the value of operand first and then only increment
it.

3.3.8 CONDITIONAL OPERATOR (? :)


Conditional operator takes three operands and consists of two symbols? and: Conditional operators are used
for decision making in C. i.e., executes different statements accordingto test condition whether it is
either true or false. It is also called ternary operator since it uses three operands.
Syntax of conditional operators
conditional_expression? expression1:expression2

If the test condition is true, expression1 is returned and if false expression2 is returned.

Program to illustrate conditional operator:


/*Conditional operator*/
#include<stdio.h>
#include<conio.h>
void main()
{
int a = 10, b = 11; int
c;
c = (a < b)? a : b; /* if a<b is true then a value is assigned to c otherwise b */ printf(“%d”,
c);
}

Output:
10

Program to find largest of two numbers:

#include<stdio.h>

51
Void main( )

int a, b,c;

scanf(“%d%d”,&a,&b);

c=(a>b)? a:b;/* if a>b is true then value of a is assigned to c otherwise b*/

printf(“%d”, c);

3.3.9 THE SIZEOF OPERATOR


This operator is used to check the size of data types, arrays, constants, structures in C. It is a unary
operator.
Syntax is:
sizeof( data type name)
Example:
Sizeof(int);
Below is the code to show the storage sizes of int, char and float data types.
#include <stdio.h>
int main()
{
printf("Sizes of int, char and float...\n"); printf("int
is: %d bytes\n", sizeof(int)); printf("char is: %d
bytes\n", sizeof(char)); printf("float is: %d bytes\n",
sizeof(float)); return 0;
}
Output
Sizes of int, char and float… int
is: 4 bytes

52
char is: 1 bytes
float is: 4 bytes

3.3.10 SPECIAL OPERATOR


Apart from these operators, C supports special operators: -
Reference Operator (&):– Used for returning the address of a memory location.
Pointer Operator (*):– It is a pointer to a variable.
Comma Operator
Mainly used for separating expressions, variable declarations, function calls etc. It works on two operands. It is
a binary operator. Comma acts as a separator.
Syntax of comma operator: -
Datatype variable name1=value1, variable2=value2,…; Example 1:
int a=1, b=2, c=3, d=4;
Here we are assigning value 1 to a, 2 to b, 3 to c and 4 to d.
Example 2:
int a, c=5, d;
Here we are assigning value 5 to both a and c variables.

 Type Cast Operator


C compiler performs automatic type conversions in mathematical expressions called as implicit type
conversion. In mixed mode expressions, the compiler promotes an integer type into a floating –point type.
To do type casting explicitly, ie, converting a value from one data type to another, type cast operator is
used.
General form is
(new type) expression;
(new type)variable;
Example:
#include<stdio.h>

53
Void main( )
{
Float x=5.5,y=6.2;
Printf(“result is %5d\n”,(int)(x+y));
}
Output is:
Result is 11

3.3.11 EXPRESSION

Every expression consists of at least one operand and can have one or more operators. Operands are
values, whereas operators are symbols that represent particular actions. In the expression
x+5
x and 5 are operands, and + is an operator.
Expressions are often classified by the type of value that they represent.
Boolean expressions : Evaluate to either TRUE or FALSE
Arithmetic expressions: Expression involving arithmetic
operators Integer expressions: Evaluate to whole numbers, like 3
or 100

Floating-point expressions: Evaluate to real numbers, like 3.141 or -0.005


String expressions: Evaluate to character strings

3.3.12 OPERATORS PRECEDENCE RULE

If more than one operator is involved in an expression then, C language has predefinedrule of
priority of operators. This rule of priority of operators is called operator precedence.
In C, precedence of arithmetic operators(*,%,/,+,-) is higher than relational operators(==,!=,>,<,>=,<=)
and precedence of relational operator is higher than logical operators(&&, || and !). Suppose an
expression:
(a>b+c&&d)
This expression is equivalent to: ((a>(b+c))&&d)

54
1. As it scans the expression from left to right, it comes across >, + and &&
symbols and among them + has highest priority so (b+c)is evaluated first
2. Then it performs a > result of 1
3. Result of 2 && d is executed at the end.

Associativity of operators:-
Associativity indicates in which order two operators of same precedence(priority) executes. Let
us suppose an expression:
a==b!=c
Here, operators == and != have same precedence. The associativity of both
== and != is left to right, i.e, the expression in left is executed first and execution takes place
towards right. Thus, a==b!=c equivalent to :
(a==b)!=c
The table below shows all the operators in C with precedence (highest to lowest) and associativity.
Associativity indicates in what order operators of equal precedence in an expression are applied.

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 (convert value to temporary value of type)
* Dereference
& Address (of operand)
sizeof Determine size in bytes on this implementation

*/ % Multiplication/division/modulus left-to-right

+ - Addition/subtraction left-to-right

<< >> Bitwise shift left, Bitwise shift right left-to-right

55
< <= 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


,

3.4 LIBRARY FUNCTIONS


Library functions are built-in functions that are grouped together and placed in a common location called
[Link] function here performs a specific operation. We can use this library functions to get the pre-
defined output.

56
All C standard library functions are declared by using many header files. These library functions are
created at the time of designing the [Link] include the header files in our C program by using
#include<filename.h>. Whenever the program is run and executed, the related files are included in the C
program.

Header File Functions

Some of the header file functions are as follows −

 stdio.h − It is a standard i/o header file in which Input/output functions are declared
 conio.h − This is a console input/output header file.
 string.h − All string related functions are in this header file.
 stdlib.h − This file contains common functions which are used in the C programs.
 math.h − All functions related to mathematics are in this header file.
 time.h − This file contains time and clock related [Link] functions in stdio.h
Advantages of Using C library functions

1. They work
One of the most important reasons you should use library functions is simply because they work. These
functions have gone through multiple rigorous testing and are easy to use.

2. The functions are optimized for performance


Since, the functions are "standard library" functions, a dedicated group of developers constantly make
them better. In the process, they are able to create the most efficient code optimized for maximum
performance.

3. It saves considerable development time


Since the general functions like printing to a screen, calculating the square root, and many more are
already written. You shouldn't worry about creating them once again.

57
4. The functions are portable

With ever-changing real-world needs, your application is expected to work every time, everywhere. And,
these library functions help you in that they do the same thing on every computer.

Example: Square root using sqrt() function

Suppose, you want to find the square root of a number.

To compute the square root of a number, you can use the sqrt() library function. The function is defined
in the math.h header file.
#include <stdio.h>
#include <math.h>
int main()
{
float num, root; printf("Enter
a number: "); scanf("%f",
&num);

// Computes the square root of num and stores in root. root =


sqrt(num);

printf("Square root of %.2f = %.2f", num, root); return 0;


}
When you run the program, the output will be:

Enter a number: 12
Square root of 12.00 = 3.46

3.5 TYPE CONVERSION IN C


A type cast is basically a conversion from one type to another. There are two types of type conversion:
Implicit Type Conversion
It is also known as ‘automatic type conversion’. Implicit type conversion is done by the compiler on its
own, without any external trigger from the user. Generally, takes place when in

58
an expression more than one data type is present. In such condition type conversion (type promotion)
takes place to avoid loss of data.
All the data types of the variables are upgraded to the data type of the variable with largest data type.
bool -> char -> short int -> int ->
unsigned int -> long -> unsigned ->
long long -> float -> double -> long double

Drawbacks of implicit conversion:

when signed is implicitly converted to unsigned, the signs may be lost and overflow can occur when long
long is implicitly converted to float.

Example for implicit conversion

// An example of implicit conversion


#include<stdio.h>
int main()
{
int x = 10; // integer x
char y = 'a'; // character c

// y implicitly converted to int. ASCII


// value of 'a' is 97 x
= x + y;

// x is implicitly converted to float float z


= x + 1.0;

printf("x = %d, z = %f", x, z);


return 0;
}
Output:
x = 107, z = 108.000000
Explicit Type Conversion–
This process is also called type casting and it is user defined. Here the user can type cast the result to
make it of a particular data type.

The syntax in C:

59
(type) expression

Type indicated the data type to which the final result is converted.

// C program to demonstrate explicit type casting


#include<stdio.h>
int main()

double x = 1.2;
// Explicit conversion from double to int int
sum = (int)x + 1;
printf("sum = %d", sum); return
0;
}

Output:

sum = 2
Advantages of Type Conversion

This is done to take advantage of certain features of type hierarchies or type


representations.
It helps us to compute expressions containing variables of different data types.

3.6 SUMMARY

In this unit, you have studied the different types of operators available in [Link] hierarchy of evaluation of
these operators in an expression when two or more operators are included is explain in this unit.
Assignment statement is the simple statement; assigning value to variables is done by two ways. One
during declaration of variable itself and other way of assigning value is by using assignment statement.
Implicit and explicit type conversions are explained.
3.7 KEYWORDS
 assignment statement
 assignment operator
 conditional operator
 increment

60
3.8 QUESTIONS FOR SELF STUDY

1. Explain assignment statement with example.


2. Explain different types of operators supported by C.
3. Explain the operator’s precedence rule with example.
4. Explain the special operators available in C.
5. Write the advantages of using library functions in C.
6. Illustrate the use of sqrt() function with program.
7. Write a program to find largest of two numbers using conditional operator.
8. Explain implicit and explicit type conversion with example program.

3.9 REFERENCES

 Programming In ANSI C by E Balagurusamy


 The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Programming in C - Gottfried B.S., TMH
 Programming in ANSI C - Balaguruswami, TMH
 C The Complete Reference - [Link], TMH
 Let us C - [Link], BPB Publications
 A Structured Programming Approach using C – B.A. Forouzan& R.F. Gillberg,
THOMSON Indian Edition
 Computer fundamentals and programming in C – PradipDey&Manas Ghosh, OXFORD

61
UNIT – 4: CONTROL STRUCTURES

Structure
4.0 Objectives
4.1 Introduction
4.2 Goto statement
4.3 If statement and if-else statement
4.4 Nesting of if statement
4.5 Switch statement
4.6 While and do-while loop
4.7 For loop
4.8 Break and continue statement
4.9 Summary
4.10 Keywords
4.11 Questions for self-study
4.12 Reference

4.0 OBJECTIVES

After going through this lesson, you will be able to


 Describe goto statement
 Elucidate if statement and if else statement
 Understand nesting of If statements
 Analyze switch statements
 Discuss while and do-while loop
 Describe for loop
 Discuss break and continue statement

62
4.1 INTRODUCTION

In this unit we will go through some control statements and decision-making condition. Generally, C
program statement is executed in the order in which the program was appearing, but sometimes we should
use decision making condition for execution only a part of program, which is called control statement.
Control statement defined how the control is transferred from one part to the other part of the program. There
several control statement like goto, if...else, switch, while, do while, for loop, break, continue and nesting of
if etc.

4.2 GOTO STATEMENT

A goto statement in C programming language provides an unconditional jump from the goto to a labeled
statement in the same function.

goto.
Syntax:
goto label; label:
statement;

The label can be any plain text except C keyword and also it can be set anywhere in the C program
above or below to goto statement.

Fig 4.2.1: Shows Flowchart of goto statement

63
Example: #include
<stdio.h>int main
()

{
int x = 10;

LOOP: do
{
if( x == 15)
{
x = x + 1;
goto LOOP;
}
printf("value of x: %d\n", x); x++;
}while( x < 20 );

return 0;

When the above code is compiled and executed, it produces the following result: value
of x: 10
value of x: 11
value of x: 12
value of x: 13
value of x: 14
value of x: 16
value of x: 17
value of x: 18
value of x:

64
4.3 IF STATEMENT AND IF-ELSE STATEMENT

If Statement:

If statement is decision making statement, here a single condition is to be checked. The condition enclosed
in if statement decides the sequence of execution of instruction. If the condition is true, the statements
inside if statement are executed, otherwise they are skipped. In C programming language, any non-zero
value is considered as true and zero or null is considered false.

Fig 4.3.1: Shows flow chart of If statemen

65
Syntax:

If(condition)
{
True statements;
}
The statement is executed only when condition is true. If the if statement body is consists of several
statement then better to use pair of curly braces. If the condition is false then compiler skip the line within
the if block.

Example:
#include<stdio.h>
#include<conio.h> void
main()
{
int x;
printf (“ enter a number:”\n);
scanf(“%d”,&x);
If (x>20)
Printf(“ number is greater”);
}
Output:

Enter a number:22

Number is greater

66
If-Else statement:
The If-else statement is a two-way branching statement. It consists of two blocks of statements if block
and else block enclosed inside the If-else statement. If the condition inside statement is true, statements
inside if block are executed, otherwise statements inside the else block are executed. Else block is
optional and it may be absent in a program.

Fig 4.3.2: Shows flowchart of If-else statement

Syntax:
if (condition)

67
{
True Statement;
}
Else
{
False Statement;
}

Example:
#include<stdio.h>
#include<conio.h>
int main()

{
int x;
printf (“enter a number:”);
scanf (“%d”, &x);
If (x<40)
{
printf (“the value is less than 40”);

}
Else
{
printf(“the value is greater than 40”);

Return 0;

Output: enter a number:12

The value is less than 20

68
4.4 NESTING OF IF STATEMENT
In nested-if statement the if statement placed inside another if statement. Nested if statements are usually
used when you have to test a combination of conditions before deciding on the proper action.

Syntax:
The syntax for a nested if statement is as follows:

if( Condition 1)
{
if(Condition 2)
{
Statement block2;
}
}
We can nest else if...else in the similar way as you have nested if statement. When nested if— else is
used, else is combined with its immediate above if statement.

Conditi

False

True

Condit
False

True
Statement block2

Next statement
Fig 4.4.1 : Shows flowchart of Nesting of if statements

69
Example:
#include<stdio.h>

void main()
{
int x=100,y=200;

if(x==100)
{
if(y==200)
{
printf("value of x is 100, and value of y is 200.");
}
}

}
Output:

4.5 SWITCH STATEMENT

The switch statement in c contained multiple cases with break. The switch statements in c test the value of
a variable and compare it with multiple cases. if the case match is found means a block of statement
associated with that particular case is executed. Every case in a block of a switch has a unique
name/number which is referred to as an identifier. The value provided by the user is compared with all the
cases inside the switch block till the match is found. If a case match is NOT found, then the default
statement is executed, and the control goes out of the switch block.

70
Fig 4.5.1: Shows flowchart of switch statement

Syntax:
Switch (choice )
{
case 1:
statement 1;
break;

71
case 2:
statement 2;
break;

case 3:
statement 3;
break;

case n:
statement n;
}

Example:

void main()

{
int a;
printf("Please choose your favorite color(1:red,2:green,3:blue,4:yellow,5:white)\n "); scanf("%d",&color);

switch(a)
{
case 1:
printf("red color");
break;

case 2:
printf("green color"); break;

72
case 3:
printf("blue color");
break;

case 4:
printf("yellow color");
break;

case 5:
printf("white color"); break;

default:
printf("You’ve entered a wrong choice"); break;
}

4.6 WHILE LOOP AND DO-WHILE LOOP

Loops in C

Loop: -This is a block of statement that will perform a set of instructions. In loops repeating particular
portion of the program either a specified number of times or until a particular number of conditions is
satisfied.

Three types of loops in C are:


1. While loop
2. Do while loop
3. For loop

While loop
Syntax: -

73
while(condition)

Statement 1;

Statement 2;

The test condition can be any expression. when we wish to do something a fixed number of times but not
knowing about the number of iteration, in a program then while loop will be [Link] first condition is
checked and if it is true then body of the loop is executed else, control will be come out of loop.

Example: -

/* write a program to print 5 times welcome to C” */#include<stdio.h> void


main ()
{
int p=1; While(p<=5)
{
printf(“Welcome to C\n”);P=p+1;
}
}

Output: Welcome to C
Welcome to C
Welcome to C
Welcome to C
Welcome to C
So as long as condition remains true statements within the body of while loop willget executed
repeatedly.

Do while loop
This (do while loop) statement is also used for looping. The body of this loop may

74
contain single statement or block of statement. The syntax for writing this statement is: Syntax:
-
Do

Statement;

while(condition);

Example:

#include
<stdioh.h>

Int main ()

Int j=0;

do

{
Printf (“value of variable j is: %d\n”, j);
Output:

Value of variable j is: 0


Value of variable j is: 1
Value of variable j is: 2
Value of variable j is: 3

Here firstly statement inside body is executed then condition is checked. If the condition is true
again body of loop is executed and this process continue until the condition becomes false.
Unlike while loop semicolon is placed at the end of while. There is minor difference between
while and do while loop, while loop test the condition before executing any of the statement of
loop. Whereas do while loop test condition after having executed the statement at least one
within the loop. If initial condition is false while loop would not executed it’s statement on other
hand do while loop executed it’s statement at least once even If condition fails for first time. It
means do while loop always executes at least once.

75
4.7 FOR LOOP

A loop is used for executing a block of statements repeatedly until a given condition returns false.

Flowchart of for loop

Step 1: First initialization happens and the counter variable gets initialized.
Step 2: In the second step the condition is checked, where the counter variable is tested for the given
condition, if the condition returns true then the C statements inside the body of for loop gets executed, if
the condition returns false then the for loop gets terminated and the control comes out of the loop.
Step 3: After successful execution of statements inside the body of loop, the counter variable is incremented or
decremented, depending on the operation (++ or –).

Fig 4.7.1: Shows flowchart of For loop

76
Syntax:-

for(exp1;exp2;exp3)

Statement;
}
or

for(initialized counter; test counter; update counter)

Statement;

Example:
#include <stdio.h> int main()
{
int i;
for (i=1; i<=3; i++)
{
printf("%d\n", i);

Output:
1
2

Here exp1 is an initialization expression, exp2 is test expression or condition andexp3 is


an update expression. Expression 1 is executed only once when loop started and used to
initialize the loop variables. Condition expression generally uses relational and logical
operators. And updating part executed only when afterbody of the loop is execute

77
4.8 BREAK AND CONTINUE STATEMENT

Sometimes it becomes necessary to come out of the loop even before loop condition
becomes false then break statement is used. Break statement is used inside loop and switch
statements. It causes immediate exit from that loop in which it appears and it is generally
written with condition. It is written with the keyword as break. When break statement is
encountered loop is terminated and control is transferred to the statement, immediately after
loop or situation where we want to jump out of the loop instantly without waiting to get
back to conditional state. When break is encountered inside any loop, control automatically
passes to the first statement after the loop. This break statement is usually associated with if
statement.

Example : #include <stdio.h> int main()


{
int num =0; while(num<=100)
{
printf("value of variable num is: %d\n", num); if (num==2)
{
break;
}
num++;
}
printf("Out of while-loop"); return 0;
}

Output:

value of variable num is: 0


value of variable num is: 1
value of variable num is: 2
Out of while-loop

78
 Continue statement (key word continue)
Continue statement is used for continuing next iteration of loop after skipping some
statement of loop. When it encountered control automatically passes through the beginning
of the loop. It is usually associated with the if statement. It is useful when we want to
continue the program without executing any part of the program. The difference between
break and continue is, when the break encountered loop is terminated and it transfer to the
next statement and when continue is encounter control come back to the beginning position.
In a while and do while loop after continue statement control transfer to the test condition
and then loop continue where as in, for loop after continue control transferred to the updating
expression and condition is tested.

#include <stdio.h> int main ()


{
int a,sum = 0;
for (a = 0; a < 10; a++)
{

if ( a % 2 == 0 ) continue;
sum = sum + a;
}
printf("sum = %d",sum); return 0;

79
4.9 SUMMARY

In this unit we have introduced the concept of goto statement, if statement, if-else statement and
nested if statement. We also discussed switch statement, while and do-while loops along with
examples are given in their sections. At the end of this unit reader are able to figure out the concept of
for loop, break and continue statements which are available in C.

4.10 KEYWORDS

 Syntax,
 break,
 switch,
 goto,

4.11 QUESTIONS
1. Explain if-else statement with flowchart.
2. With example explain nested if statement.
3. Write a Flowchart of switch statement with an example.
4. Describe difference between while and do-while loop.
5. Discuss continue and break statement.
6. Write a program explain for loop.

4.12 REFERENCES

 Programming in ANSI C by E Balagurusamy


 The C Programming Language (Ansi C Version) by Brian W. Kernighan,
Dennis M. Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Computer concepts and programming in c by [Link] and [Link] Prasad
 [Link]

80
Unit – 5 FUNCTIONS

Structure
5.0 Objectives

5.1 Introduction
5.2 Graphical Representation
5.3 The Need for a Function
5.4 Types of C Function

5.5 Prototype of Function


5.6 Calling a Function
5.7 Summary
5.8 Keywords

5.9 Questions for self-study

5.10 Reference

5.0 OBJECTIVES
After going through this lesson, you will be able to

 Describe access to function


 define parameters data types specification
 Explain function prototype and recursion

5.1 INTRODUCTION
A number of statements grouped into a single logical unit are called a function. The use of function
makes programming easier since repeated statements can be grouped into functions. Splitting the
program into separate function make the program more readable and maintainable. It is necessary to
have a single function ‘main’ in every C program, along with other functions used/defined by the
programmer. A function definition has two principal components: the function header and body of the
function. The function header is the data type of return value followed by function name and
(optionally) a set of arguments separated

81
by commas and enclosed in parenthesis. Associated type to which function accepts precedes each
argument. In general terms function header statement can be written as

return_type function_name (type1 arg1,type2 arg2,..,typen argn)

where return_type represents the data type of the item that is returned by the function, function_name
represents the name of the function, and type1,type2,…,typen represents the data type of the
arguments arg1,arg2,..,argn.

Example: Following function returns the sum of two integers. int


add(int p, int q)
{
return p+q; //Body of the function
}

Here p and q are arguments. The arguments are called formal arguments or formal parameters,
because they represent the name of the data item that is transferred into the function from the calling
portion of the program. The corresponding arguments in the function call are called actual arguments
or actual parameters, since they define the data items that are actually transferred. A function can be
invoked whenever it is needed. It can be accessed by specifying its name followed by a list of
arguments enclosed in parenthesis and separated by commas. e.g., add(5,10);

The following condition must be satisfied for function call.

 The number of arguments in the function calls and function declaration must be same.

 The prototype of each of the argument in the function call should be same as the
corresponding parameter in the function declaration statement.

For example, the code shown below illustrate how function can be used in programming

//C Program for Addition of Two Number's using User Define Function
#include<stdio.h>

82
#include<conio.h>

float add(float, float); // function declaration void


main()
{

float a,b,c;
clrscr();
printf("Enter the value for a & b\n\n"); scanf("%f
%f",&a,&b);

c=add(a,b);
printf("\nc=%f",c); getch();
}

// Here is the function definition float add


(float x,float y)
{

float z; z=x+y;
return(z);
}

5.2 Graphical Representation of Working Principal of Functions

Graphical Representation is a way of analyzing numerical data. It exhibits the relation between data,
ideas, information and concepts in a diagram. It is easy to understand and it is one of the most
important learning strategies. It always depends on the type of information in a particular domain.
There are different types of graphical representation. Some of them are as follows:
 Line Graphs – Line graph or the linear graph is used to display the continuous data and it is
useful for predicting future events over time. Fig:5.2.1

83
 Bar Graphs – Bar Graph is used to display the category of data and it compares the data
using solid bars to represent the quantities. Fig:5.2.2

 Histograms – The graph that uses bars to represent the frequency of numerical data that
are organized into intervals. Since all the intervals are equal and continuous, all the bars
have the same width. Fig:5.2.3

 Line Plot – It shows the frequency of data on a given number line. ‘ x ‘ is placed above a
number line each time when that data occurs [Link].2.4

84
 Frequency Table – The table shows the number of pieces of data that falls within the
given interval. Fig:5.2.5

 Circle Graph – Also known as the pie chart that shows the relationships of the parts of the
whole. The circle is considered with 100% and the categories occupied is represented
with that specific percentage like 15%, 56%, etc. Fig:5.2.6

 Stem and Leaf Plot – In the stem and leaf plot, the data are organized from least value to
the greatest value. The digits of the least place values from the leaves and the next place
value digit forms the stems. Fig:5.2.7

85
 Box and Whisker Plot – The plot diagram summarizes the data by dividing into four
parts. Box and whisker show the range (spread) and the middle (median) of the data.
Fig:5.2.8

 General Rules for Graphical Representation of Data


There are certain rules to effectively present the information in the graphical representation. They are:

o Suitable Title: Make sure that the appropriate title is given to the graph which indicates
the subject of the presentation.
o Measurement Unit: Mention the measurement unit in the graph.
o Proper Scale: To represent the data in an accurate manner, choose a proper scale.
o Index: Index the appropriate colors, shades, lines, design in the graphs for better
understanding.
o Data Sources: Include the source of information wherever it is necessary at the
bottom of the graph.
o Keep it Simple: Construct a graph in an easy way that everyone can understand.
o Neat: Choose the correct size, fonts, colors etc. in such a way that the graph should be
a visual aid for the presentation of information.

86
 Graphical Representation in Math’s

In Mathematics, a graph is defined as a chart with statistical data, which are represented in the form
of curves or lines drawn across the coordinate point plotted on its surface. It helps to study the
relationship between two variables where it helps to measure the change in the variable amount with
respect to another variable within a given interval of time. It helps to study the series distribution and
frequency distribution for a given problem. There are two types of graphs to visually depict the
information. They are:

o Time Series Graphs – Example: Line Graph


o Frequency Distribution Graphs – Example: Frequency Polygon Graph

 Principles of Graphical Representation

Algebraic principles are applied to all types of graphical representation of data. In graphs, it is
represented using two lines called coordinate axes. The horizontal axis is denoted as the x- axis and
the vertical axis is denoted as the y-axis. The point at which two lines intersect is called an origin
‘O’. Consider x-axis, the distance from the origin to the right side will take a positive value and the
distance from the origin to the left side will take a negative value.
Similarly, for the y-axis, the points above the origin will take a positive value, and the points below the
origin will a negative value. Fig:5.2.9

Generally, the frequency distribution is represented in four methods, namely

o Histogram

87
o Smoothed frequency graph
o Pie diagram
o Cumulative or ogive frequency graph
o Frequency Polygon

 Merits of Using Graphs


Some of the merits of using graphs are as follows:

o The graph is easily understood by everyone without any prior knowledge.


o It saves time
o It allows us to relate and compare the data for different time periods
o It is used in statistics to determine the mean, median and mode for different data, as
well as in the interpolation and the extrapolation of data.

 Example for Frequency polygon Graph


Here are the steps to follow to find the frequency distribution of a frequency polygon and it is
represented in a graphical way.

o Obtain the frequency distribution and find the midpoints of each class interval.
o Represent the midpoints along x-axis and frequencies along the y-axis.
o Plot the points corresponding to the frequency at each midpoint.
o Join these points, using lines in order.
o To complete the polygon, join the point at each end immediately to the lower- or
higher-class marks on the x-axis.

88
5.3 The Need for Function

Functions are very much required in hard core programming because of many reasons. Here we list
out most common necessity for function requirement: Functions can be executed as many times as
necessary from different points in a program. Without the ability to package a block of code
into a function, programs would end up being much larger, since you would typically need to
replicate the same code at various points in your program. But the real reason that you need
functions is to modularize your program into easily manageable chunks. Functions allow a
program to be segmented so that it can be written piecemeal, and each piece tested
independently before bringing it together with the other pieces. It also allows the work to be
divided among members of a programming team, with each team member taking
responsibility for a tightly specified piece of the program, with a well-defined functional
interface to the rest of the code. Real-world large-scale programming projects are developed
using this approach

5.4 Types of C functions


Basically, there are two types of functions in C on basis of whether it is defined by user or not.

 Library function
 User defined function

Library functions are built-in functions that are grouped together and placed in a common location
called library. Each function here performs a specific operation. We can use this library functions to get
the pre-defined output. All are declared by using many header files. These library functions are created
at the time of designing the compilers. We include the header files in our C program by using
#include<filename.h>. Whenever the program is run and executed, the related files are included in the
C program.

 Header File Functions


Some of the header file functions are as follows

o stdio.h − It is a standard i/o header file in which Input/output functions are declared
o conio.h − This is a console input/output header file.
o string.h − All string related functions are in this header file.
o stdlib.h − This file contains common functions which are used in the C programs.
o math.h − All functions related to mathematics are in this header file.
o time.h − This file contains time and clock related [Link] functions in stdio.h

89
For example:
main()
The execution of every C program starts from this main. prinf() is
printf()
used for displaying output in C.
scanf()
scanf() is used for taking input in C.

for further information about the library functions readers can look into help section of C
compiler and more library functions and their usage is discussed in forthcoming sections and
modules.

 user defined functions

A function is a block of code that can be used to perform a specific action. C allows
programmers to write their own functions, also known as user-defined functions. A user-
defined function has three main components that are function declarations, function definition
and function call. Further functions can be called by call by value or call by reference.
Functions need to be written once and can be called as many times as required inside the
program, which increases reusability in code and makes code more readable and easier to test,
debug, and maintain the code.

C provides programmer to define their own function according to their requirement known as user
defined functions.
Example of how C function works
#include <stdio.h>
void
function_name(){

................
................
}
int main(){
...........
...........
function_name();
...........

90
...........
}

As mentioned earlier, every C program begins from main() and program starts executing the codes
inside main function. When the control of program reaches to function_name() inside main. The
control of program jumps to "void function_name()" and executes the codes inside it. When, all the
codes inside that user defined function is executed, control of the program jumps to statement just
below it. Analyze the figure below for understanding the concept of function in C. Fig 5.4.1

Remember, the function name is an identifier and should be unique.

Advantages of user defined functions


o User defined functions helps to decompose the large program into small segments
which makes programmer easy to understand, maintain and debug.
o If repeated code occurs in a program. Function can be used to include those codes and
execute when needed by calling that function.
o Programmer working on large project can divide the workload by making different
functions.

91
 Example of user defined function

/*Program to demonstrate the working of user defined function*/

#include <stdio.h>
int add(int a, int b); //function
prototype(declaration)int main(){

int num1,num2,sum;
printf("Enters two number to add\n");
scanf("%d %d",&num1,&num2);
sum=add(num1,num2); //function
callprintf("sum=%d",sum);

return 0;
}
int add(int a,int b) //function declarator
{
/*line 13-19 is called function body
line 12-19 is called function definition.*/
int add;

add=a+b;
return add; //return statement of function
}

5.5 Prototype of a Function


Every function in C programming should be declared before they are used. This type of declaration
are also called function prototype. Function prototype gives compiler information about function
name, type of arguments to be passed and return type.
Syntax of function prototype
return_type function_name(type(1) argument(1),. ,type(n) argument(n));

Here, in the above example, function prototype is "int add(int a, int b);" which provides
following information to the compiler:
1. name of the function is "add"
2. return type of the function is int.
3. two arguments of type int are passed to function.

92
Function prototype is not needed, if you write function definition above the main function. In this
program if the code from line 12 to line 19 is written above main( ), there is no need of function
prototype.

5.6 Calling a Function

Control of the program cannot be transferred to user-defined function (function definition) unless
it is called (invoked).
Syntax of function call
function_name(argument(1),. argument(n));

In the above example, function call is made using statement "add(num1,num2);" in line 9. This
makes control of program transferred to function declarator (line 12). In line 8, the value returned
by function is kept into "sum" which you will study in detail in function return type of next unit.

 Functions Arguments

Before the Standard, it was not possible to give any information about a function's arguments
except in the definition of the function itself. The information was only used in the body of the
function and was forgotten at the end. In those bad old days, it was quite possible todefine a
function that had three double arguments and only to pass it one int, when it was called. The
program would compile normally, but simply not work properly. It was considered to be the
programmer's job to check that the number and the type of arguments toa function matched
correctly. As you would expect, this turned out to be a first-rate source of bugs and portability
problems. Here is an example of the definition and use of a function witharguments, but omitting
for the moment to declare the function fully.

#include
<stdio.h>
#include
<stdlib.h>
main(){

void pmax(); /* declaration


*/int i,j;

for(i = -10; i <= 10; i++){ for(j =


-10; j <= 10; j++){

pmax(i,j);

93
}
}
exit(EXIT_SUCCES
S);
}

/*
* Function pmax.
* Returns: void
* Prints larger of its two arguments.
*/
vo
id

pmax(int a1, int a2){ /* definition


*/int biggest;

if(a1 > a2){


biggest = a1;
}else{
biggest = a2;
}

printf("larger of %d and %d is %d\n", a1, a2,


biggest);

}
To start with, notice the careful declaration that pmax returnsvoid. In the function definition, the
matching void occurs on the line before the function name. The reason for writing it like that is
purely one of style; it makes it easier to find function definitions if their names are always at the
beginning of a line.

The function declaration (in main) gave no indication of any arguments to the function, yet the use
of the function a couple of lines later involved two arguments. That is permitted by both the old
and Standard versions of C, but must nowadays be considered to be bad practice. It is much
better to include information about the arguments in the declaration too, as we will see. The old
style is now an ‘obsolescent feature’ and may disappear in a later version of the Standard.

Now on to the function definition, where the body is supplied. The definition shows that the
94
function takes two arguments, which will be known as a1 and a2 throughout the body of the
function. The types of the arguments are specified too, as can be seen.

In the function definition you don't have to specify the type of each argument because they will
default to int, but this is bad style. If you adopt the practice of always declaring arguments, even if
they do happen to be int, it adds to a reader's confidence. It indicates that

you meant to use that type, instead of getting it by accident: it wasn't simply forgotten. The
definition of pmax could have been this:

/* BAD STYLE OF FUNCTION DEFINITION */


void pmax(a1,
a2){

/* and so on */
The proper way to declare and define functions is through the use of prototypes.

Passing Argument to a Function

Arguments can be passed to a function by two methods, they are called passing by value and
passing by reference. When a single value is passed to a function via an actual argument, the value
of the actual argument is copied into the function. Therefore, the value of the corresponding formal
argument can be altered within the function, but the value of the actual argument within the calling
routine will not change. This procedure for passing the value of an argument to a function is known
as passing by value.

Let us consider an example

#include <stdio.h> main()

{
int x=3;
printf(“\n x=%d(from main, before calling the
function”),x);

change(x);
printf(“\n\nx=%d(from main, after calling
thefunction)”,x);

}
change(x) int x;
{
x=x+3;
printf(“\nx=%d(from the function, after
beingmodified)”,x);
95
return;
}
The original value of x (i.e. x=3) is displayed when main begins execution. This value is then
passed to the function change, where it is sum up by 3 and the new value displayed. This new value
is the altered value of the formal argument that is displayed within the function. Finally, the value
of x within main is again displayed, after control is transferred back to mainfrom change.

x=3 (from main, before calling the function)

x=6 (from the function, after being modified)

x=3 (from main, after calling the function)

Passing an argument by value allows a single-valued actual argument to be written as an expression


rather than being restricted to a single variable. But it prevents information from being transferred
back to the calling portion of the program via arguments. Thus, passing by value is restricted to a
one-way transfer of information. Arrays are passed differently than single-valued entities. If an
array name is specified as an actual argument, the individual array elements are not copied to the
function. Instead the location of the array is passed to the function. If an element of the array is
accessed within the function, the access will refer to the location of that array element relative to
the location of the first element. Thus, any alteration to an array element within the function will
carry over to the calling routine.

The return statements

The return statement is very important. Every function except those returning void should have at
least one, each return showing what value is supposed to be returned at that point. Although it is
possible to return from a function by falling through the last }, unless the function returns void an
unknown value will be returned, resulting in undefined behavior.

Here is another example function. It uses getchar to read characters from the program input and
returns whatever it sees except for space, tab or newline, which it throws away.

96
#include <stdio.h>
int non_space(void)
{
int c;
while ( (c=getchar ())=='\t' || c== '\n' || c==' ')
; /* empty statement */ return
(c);

}
Look at the way that all of the work is done by the test in the while statement, whose body was an
empty statement. It is not an uncommon sight to see the semicolon of the empty statement sitting
there alone and forlorn, with only a piece of comment for company and readability. Please, please,
never write it like this:

while (something);

with the semicolon hidden away at the end like that. It's too easy to miss it when you read the code,
and to assume that the following statement is under the control of the while.

The type of expression returned must match the type of the function, or be capable of being
converted to it as if an assignment statement were in use. For example, a function declared to
return double could contain

return (1);

and the integral value will be converted to double. It is also possible to have just return without any
expression—but this is probably a programming error unless the function returns void. Following
the return with an expression is not permitted if the function returns void.

Nesting Function

A nested function is a function defined inside the definition of another function. It can be defined
wherever a variable declaration is permitted, which allows nested functions within nested
functions. Within the containing function, the nested function can be declared prior to being
defined by using the

autokeyword. Otherwise, a nested function has internal linkage.

A nested function can access all identifiers of the containing function that precede its definition.
A nested function must not be called after the containing function exits.

97
A nested function cannot use a goto statement to jump to a label in the containing function, or to a
local label declared with the label keyword inherited from the containing function.

The main() function


When a program begins running, the system calls the function main, which marks the entry point of
the program. By default, main has the storage class extern. Every program must have one function
named main, and the following constraints apply:

No other function in the program can be called main.


main cannot be defined as inline or static.
main cannot be called from within a program.
The address of main cannot be taken.
The function main can be defined with or without parameters, using any of the following
forms:

int main (void) int


main ( )
int main(int argc, char *argv[]) int main
(int argc, char ** argv)

Although any name can be given to these parameters, they are usually referred toas argc
and argv. The first parameter, argc (argument count) is an integer that indicates how many
arguments were entered on the command line when the program was started. The second
parameter, argv(argument vector), is an array of pointers to arrays of character objects. The array
objects are null-terminated strings, representing the arguments that were entered on the command
line when the program was started.

The first element of the array, argv[0], is a pointer to the character array that contains the program
name or invocation name of the program that is being run from the command line. argv[1]
indicates the first argument passed to the program, argv[2] the second argument, and so on.

Recursion

With argument passing safely out of the way we can look at recursion. Recursion is a topic that often
provokes lengthy and unenlightening arguments from opposing camps. Some think it is wonderful,
and use it at every opportunity; some others take exactly the opposite view. Let's

98
just say that when you need it, you really do need it, and since it doesn't cost much toput into
a language, as you would expect, C supports recursion.

Every function in C may be called from any other or itself. Each invocation of a function causes a
new allocation of the variables declared inside it. In fact, the declarations that we have been using
until now have had something missing: the keyword auto, meaning ‘automatically allocated’.

/* Example of auto
*/ main(){
auto int var_name;
.
.
.
}
The storage for auto variables is automatically allocated and freed on function entry and return. If
two functions both declare large automatic arrays, the program will only have tofind room for
both arrays if both functions are active at the same time. Although auto is a keyword, it is never
used in practice because it's the default for internal declarations and is invalid for external ones. If
an explicit initial value isn't given for an automatic variable, then its value will be unknown when it is
declared. In that state, any use of its value will cause undefined behavior.

The real problem with illustrating recursion is in the selection of examples. Too often, simple
examples are used which don't really get much out of recursion. The problems where it really helps
are almost always well out of the grasp of a beginner who is having enough trouble trying to sort out
the difference between, say, definition and declaration without wanting the extra burden of having
to wrap his or her mind around a new concept as well. The chapter on data structures will show
examples of recursion where it is a genuinely useful technique.

The following example uses recursive functions to evaluate expressions involving single digit
numbers, the operators *, %, /, +, - and parentheses in the same way that C does. The whole
expression is evaluated and its value printed when a character not in the ‘language’ is read. For
simplicity no error checking is performed. Extensive use is made of the ungetc library function,
which allows the last character read by getchar to be ‘unread’ and become once again the next
character to be read. Its second argument is one of the things declaredin stdio.h.

99
The main places where recursion occurs are in the function unary_exp, which calls itself, and at the
bottom level where primary calls the top level all over again to evaluate parenthesized expressions.

Try running following piece of code for better understanding. Trace its actions by hand on inputs
such as

1
1+2
1+2 * 3+4
1+--4
1+(2*3)+4

/*Recursive code for simple C expressions*/

#include <stdio.h>
#include <stdlib.h>

int expr(void);
int
mul_exp(void);
int
unary_exp(void);
int primary(void);

main(){
int val;

for(;;){
printf("expression: "); val =
expr(); if(getchar() != '\n'){

printf("error\n"); while(getchar() !=
'\n')

; /* NULL */

100
} else{
printf("result is %d\n", val);
}

} exit(EXIT_SUCCESS);

int
expr(voi
d){

int val, ch_in;

val = mul_exp();
for(;;){

switch(ch_in = getchar()){ default:

ungetc(ch_in,stdin); return(val);

case '+':
val = val + mul_exp(); break;

case '-':
val = val - mul_exp(); break;

}
}
}

int
mul_exp(voi
d){

101
int val, ch_in;

val = unary_exp();
for(;;){

switch(ch_in = getchar()){ default:

ungetc(ch_in, stdin); return(val);

case '*':
val = val * unary_exp(); break;

case '/':
val = val / unary_exp(); break;

case '%':
val = val % unary_exp(); break;

}
}
}

int
unary_exp(void
){

int val, ch_in;

switch(ch_in = getchar()){
default:

102
ungetc(ch_in, stdin); val =
primary(); break;

case '+':
val = unary_exp(); break;

case '-':
val = -unary_exp(); break;

}
return(val);
}

int
primary(void
){

int val, ch_in;

ch_in = getchar();
if(ch_in >= '0' && ch_in <= '9'){ val =
ch_in - '0';

goto out;
}
if(ch_in == '('){
val = expr();
getchar(); /* skip closing ')' */
goto out;

}
printf("error: primary read %d\n",
ch_in);exit(EXIT_FAILURE);

out:
return(val);
}

 Storage Class Specifier

103
Every variable and function in C programming have two properties: type and storage class. Type
refers to the data type of variable whether it is character or integer or floating-point value etc.
There are 4 types of storage class:

o automatic
o external
o static
o register

 Automatic storage class


Keyword
Variables declared inside the function body are automatic by default. These variables are also
known as local variables as they are local to the function and doesn't have meaning outside that
function Since, variable inside a function is automatic by default, keyword auto is rarely used.

 External storage class

External variable can be accessed by any function. They are also known as global variables.
Variables declared outside every function are external variables. In case of large program,
containing more than one file, if the global variable is declared in file 1 and that variable is used in
file 2 then, compiler will show error. To solve this problem, keyword extern is used in file 2 to
indicate that, the variable specified is global variable and declared in another file.

 Register Storage Class


Keyword to declare register variable: register Example
of register variable
register int a;
Register variables are similar to automatic variable and exists inside that particular function [Link]
the compiler encounters register variable, it tries to store variable in microprocessor's register rather
than memory. Value stored in register is much faster than that of memory.
In case of larger program, variables that are used in loops and function parameters are declared
register variables. Since, there are limited number of registers in processor and if it couldn't store the
variable in register, it will automatically store it in memory.

104
5.7 Summary
At the end of this unit, you have learnt about functions, how to define and declare functions,
what are the functions different data types. It has been also discussed about the library
functions and user defined functions. You are now able to execute function from different
places of a program.

5.8 Keywords

 Function call
 prototype
 library function
 used defined function

5.9 Questions for self-study

1. Distinguish between a user-defined and one supplied, functions in the C library.


2. In what sense does the user-defined function feature of 'C' extends its repertoire?
3. How many values can a function return?
4. How are argument data types specified in a function declaration?
5. Discuss in detail about passing arguments to the function?
6. What is recursion? With a suitable example explain the recursion?
7. Explain about main () function?

5.10 Reference

 Programming in ANSI C by E Balagurusamy


 The C Programming Language (Ansi C Version) by Brian W. Kernighan,
Dennis M. Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Computer concepts and programming in c by [Link] and [Link] Prasad
 [Link]

105
Unit-6 ARRAY

Structure
6.0 Objectives
6.1 Introduction: Basics of Array
6.2 Pointer Declaration
6.3 The & and * Operators
6.4 Passing Pointers to a Function
6.5 Operations on Pointers
6.6 Pointer Arithmetic
6.7 Summary
6.8 Key words
6.9 Questions for self-study
6.10 References

6.0 OBJECTIVES

At the end of this unit, you will be able to

 Understand the concepts of Array


 Describe the functionality of pointer
 List out various operation on pointers
 Explain the arithmetic operation performed on pointers

6.1 INTRODUCTION BASICS OF ARRAY

We belong to an era where it is impossible to long for a progressive world without


Information Technology. And when we talk about Information Technology, Computer
Programming readily comes into our mind. An Array is one of the essential facets of
programming languages and software development. This is because an array is of great
utility in maintaining extensive datasets, sorting, and identifying variables. In its simplest
terms, an array can be defined as a formation of digits, images, or objects arranged in rows
and columns in accordance with their types. Comprehending the concept of array facilitates
your tedious work and allows you to make it concise as arrays illustrate numerous data
elements of similar type using a sole name.

106
 What Is Array?

In Computer Programming, an array assembles equivalent data elements stored at adjacent


memory locations. This easiest data structure helps to determine the location of each piece
of data by simply using an offset to the base value. An offset is a number that illustrates th e
distinction between two index numbers

For instance, if you want to keep a record of the marks obtained by a student in 6 subjects,
then you don’t need to determine the variables individually. Rather, you can determine an
array that will store each piece of data factors at a contiguous memory location. Arrays are
one of the oldest and most essential data structures used in almost every program. Arrays
are also useful in implementing other data structures such as lists, heaps, hash tables,
deques, queues, stacks, and strings.

6.2 POINTER DECLARATION

In c a pointer is a variable that points to or references a memory location in which data is


stored. Each memory cell in the computer has an address that can be used to access that
location so a pointer variable point to a memory location we can access and change the
contents of this memory location via the pointer.

A pointer is a variable that contains the memory location of another variable. The syntax is as
shown below. We start by specifying the type of data stored in the location identified by the
pointer. The asterisk tells the compiler that we are creating a pointer variable. Finally we give
the name of the variable.
type * variable name;

Example:
int *ptr;
float *string;

6.2 THE & AND * OPERATORS

Once we declare a pointer variable, we must point it to something we can do this by assigning
to the pointer the address of the variable we want to point as in the following example:
ptr=&num;
This places the address where num is stores into the variable ptr. If num is stored in memory
21260 address then the variable ptr has the value 21260.

107
/* A program to illustrate pointer declaration*/
main()
{
int *ptr;
int sum;
sum=45;
ptr=sum;
printf (“\n Sum is %d\n”, sum);
printf (“\n The sum pointer is %d”, ptr);
}

We will get the same result by assigning the address of num to a regular (non-pointer)
variable. The benefit is that we can also refer to the pointer variable as *ptr the asterisk tells to
the computer that we are not interested in the value 21260 but in the value stored in that
memory location. While the value of pointer is 21260 the value of sum is 45 however we can
assign a value to the pointer * ptr as in *ptr=45.
This means place the value 45 in the memory address pointer by the variable ptr. Since the
pointer contains the address 21260 the value 45 is placed in that memory location. And since
this is the location of the variable num the value also becomes 45. this shows how we can
change the value of pointer directly using a pointer and the indirection pointer.

6.3 PASSING POINTERS TO A FUNCTION

The pointers are very much used in a function declaration. Sometimes only with a pointer a
complex function can be easily represented and success. The usage of the pointers in a
function definition may be classified into two groups.
1. Call by reference
2. Call by value

 Call by value
We have seen that a function is invoked there will be a link established between the formal
and actual parameters.A temporary storage is created where the value of actual parameters is
stored. The formal parameters picks up its value from storage area the mechanism of data
transfer between actual and formal parameters allows the actual parameters mechanism of
data transfer is referred as call by value.

The corresponding formal parameter represents a local variable in the called function. The
current value of corresponding actual parameter becomes the initial value of formal
parameter. The value of formal parameter may be changed in the body of the actual
parameter. The value of formal parameter may be changed in the body of the subprogram by
108
assignment or input statements. This will not change the value of actual parameters.
/* Include< stdio.h >
void main()
{
int x,y;
x=20;
y=30;
printf(“\n Value of a and b before function call =%d %d”,a,b);
fncn(x,y);
printf(“\n Value of a and b after function call =%d %d”,a,b);
}
fncn(p,q)
int p,q;
{
p=p+p;
q=q+q;
}

 Call by Reference
When we pass address to a function the parameters receiving the address should be pointers.
The process of calling a function by using pointers to pass the address of the variable is
known as call by reference. The function which is called by reference can change the values
of the variable used in the call.
/* example of call by reference*/
/* Include< stdio.h >
void main()
{
int x,y;
x=20;
y=30;
printf(“\n Value of a and b before function call =%d %d”,a,b);
fncn(&x,&y);
printf(“\n Value of a and b after function call =%d %d”,a,b);
}
fncn(p,q)
int p,q;

109
{
*p=*p+*p;
*q=*q+*q;
}

6.4 OPERATIONS ON POINTERS

Pointer variables are not directly usable by many of the operators, functions, or procedures
provided by IDL. You cannot, for example, do arithmetic on them or plot them. You can, of
course, do these things with the heap variables referenced by such pointers, assuming that
they contain appropriate data for the task at hand. Pointers exist to allow the construction of
dynamic data structures that have lifetimes that are independent of the program scope they are
created in.

There are 4 IDL operators that work with pointer variables: assignment, dereference, EQ, and
NE. The remaining operators (addition, subtraction, etc.) do not make any sense for pointer
types and are not defined.

Many non-computational functions and procedures in IDL do work with pointer variables.
Examples are SIZE, N_ELEMENTS, HELP, and PRINT. It is worth noting that the only I/O
allowed directly on pointer variables is default formatted output, where they are printed as a
symbolic description of the heap variable they point at. This is merely a debugging aid for the
IDL programmer—input/output of pointers does not make sense in general and is not allowed.
Please note that this does not imply that I/O on the contents of non-pointer data held in heap
variables is not allowed. Passing the contents of a heap variable that contains non-pointer data
to the PRINT command is a simple example of this type of I/O.

 Assignment
Assignment works in the expected manner—assigning a pointer to a variable gives you
another variable with the same pointer. Hence, after executing the statements:
A = PTR_NEW(FINDGEN(10))
B=A
HELP, A, B

A and B both point at the same heap variable and we see the output:

A POINTER= <PtrHeapVar1>
B POINTER= <PtrHeapVar1>

110
 Dereference
In order to get at the contents of a heap variable referenced by a pointer variable, you must use
the dereference operator, which is * (the asterisk). The dereference operator precedes the
variable dereferenced. For example, if you have entered the above assignments of the
variables A and B:

PRINT, *B

IDL prints:

0.00000 1.00000 2.00000 3.00000 4.00000 5.00000


6.00000 7.00000 8.00000 9.00000

That is, IDL prints the contents of the heap variable pointed at by the pointer variable B.

 Dereferencing Pointer Arrays


Note that the dereference operator requires a scalar pointer operand. This means that if you
are dealing with a pointer array, you must specify which element to dereference. For example,
create a three-element pointer array, allocating a new heap variable for each element:
ptarr = PTRARR(3, /ALLOCATE_HEAP)

To initialize this array such that the heap variable pointed at by the first pointer contains the
integer zero, the second the integer one, and the third the integer two, you would use the
following statement:

for i = 0,2 do *ptarr[i] = i

Note: The dereference operator is dereferencing only element I of the array for each iteration.
Similarly, if you wanted to print the values of the heap variables pointed at by the pointers in
ptarr, you might be tempted to try the following:

PRINT, *ptarr
IDL prints:

% Expression must be a scalar in this context: PTARR.


% Execution halted at: $MAIN$
To print the contents of the heap variables, use the statement:
FOR I = 0, N_ELEMENTS(ptarr)-1 DO PRINT, *ptarr[I]

111
Dereferencing Pointers to Pointers

The dereference operator can be applied as many times as necessary to access data pointed at
indirectly via multiple pointers. For example, the statement:

A = PTR_NEW(PTR_NEW(47))
 Assigns to A a pointer to a pointer to a heap variable containing the value 47.
To print this value, use the following statement:

PRINT, **A
 Dereferencing Pointers within Structures
If you have a structure field that contains a pointer, dereference the pointer by prepending the
dereference operator to the front of the structure name. For example, if you define the
following structure:

struct = {data:’10.0’, pointer:ptr_new(20.0)}

you would use the following command to print the value of the heap variable pointed at by the
pointer in the pointer field:

PRINT, *[Link]

Defining pointers to structures is another common practice. For example, if you define the
following pointer:

ptstruct = PTR_NEW(struct)

you would use the following command to print the value of the heap variable pointed at by the
pointer field of the struct structure, which is pointed at by ptstruct:

PRINT, *(*pstruct).pointer

Note that you must dereference both the pointer to the structure and the pointer within the
structure.

 Dereferencing the Null Pointer


It is an error to dereference the NULL pointer, an invalid pointer, or a non-pointer. These
cases all generate errors that stop IDL execution. For example:

PRINT, *45

112
IDL prints:

% Pointer type required in this context: <INT( 45)>.


% Execution halted at: $MAIN$

For example:

A = PTR_NEW() & PRINT, *A


IDL prints:
% Unable to dereference NULL pointer: A.
% Execution halted at: $MAIN$
For example:
A = PTR_NEW(23) & PTR_FREE, A & PRINT, *A
IDL prints:
% Invalid pointer: A.
% Execution halted at: $MAIN$
 Equality and Inequality
The EQ and NE operators allow you to compare pointers to see if they point at the same heap
variable. For example:

Make A a pointer to a heap variable containing 23.


A = PTR_NEW(23);
//B points at the same heap variable as A.
B = A;
//C contains the null pointer.
C = PTR_NEW();

PRINT, 'A EQ B: ', A EQ B & $


PRINT, 'A NE B: ', A NE B & $
PRINT, 'A EQ C: ', A EQ C & $
PRINT, 'C EQ NULL: ', C EQ PTR_NEW() & $
PRINT, 'C NE NULL:', C NE PTR_NEW()
IDL prints:
A EQ B: 1
A NE B: 0
A EQ C: 0
C EQ NULL: 1

113
C NE NULL: 0

6.5 POINTER ARITHMETIC

C has the speed and efficiency of assembly language combined with readability of assembly
language. In other words, it's just a glorified assembly [Link]'s perhaps too harsh a
judgment of C, but certainly one of the reasons the language was invented was to write
operating systems. Writing such code requires the ability to access addresses in memory in an
efficient manner. This is why pointers are such an important part of the C language. They're
also a big reason programmers have bugs.
If you're going to master C, you need to understand pointer arithmetic, and in particular, the
relationship between arrays and pointers.
 Arbitrary Pointer Casting
Because most ISAs use the same number of bits as integers, it's not so uncommon to cast
integers as pointers.
Here's an example.
// Casting 32 bit int, 0x0000ffff, to a pointer
char * ptr = reinterpret_cast<char *>( 0x0000ffff ) ;
char * ptr2 = reinterpret_cast<char *>( 0x0000ffff ) ;

In general, this is one of the pitfalls of C. Arbitrary pointer casting allows you to point
anywhere in [Link], this is not good for safe programs. In a safe
programming language (say, Java), the goal is to access objects from pointers only when
there's an object there. Furthermore, you want to call the correct operations based on the
object's type.
Arbitrary pointer casting allows you to access any memory location and do anything you want
at that location, regardless of whether you can access that memory location or whether the
data is valid at that memory location.
6.6 POINTERS AND ARRAYS

In C, arrays have a strong relationship to [Link] the following declaration.


int arr[ 10 ] ;
You might think from the above statement that arr is of type int. However, arr, by itself,
without any index subscripting, can be assigned to an integer pointer.
Do you know, however, that arr[ i ] is defined using pointer arithmetic?
In particular:
arr[ i ] == * ( arr + i )

114
Let's take a closer look at arr + i. What does that mean? arr is a pointer to arr[ 0 ]. In fact, it is
defined to be & arr[ 0 ].
A pointer is an address in memory. arr contains an address in memory---the address
where arr[ 0 ] is located.
What is arr + i? If arr is a pointer to arr[ 0 ] then arr + i is a pointer to arr[ i ].
Perhaps this is easier shown in a diagram. Fig 6.5.1

We assume that each int takes up 4 bytes of memory. If arr is at address 1000, then arr + 1 is
address 1004, arr + 2 is address 1008, and in general, arr + i is address 1000 + (i * 4).Now that
you see the diagram, something may strange. Why is arr + 1 at address 1004 and not 1001?
That's pointer arithmetic in action. arr + 1 points to one element past arr. arr + 3 is points to 3
elements past arr. Thus, arr + i points to i elements past [Link] idea is to have arr + i point
to i elements after arr regardless of what type of element the array [Link] the array
had contained short where a short is only 2 bytes. If arr is at address 1000, then, arr + 1 is
address 1002 (instead of 1004). arr + 2 is at address 1004 (instead of 1008), and in general arr
+ i is at address 1000 + (2 * i). Fig 6.5.2

Notice that arr + 1 is now 2 bytes after arr and arr + 2 is 4 bytes. When we had an int array, arr
+ 1 was 4 bytes after arr and arr + 2 was 8 bytes afterwards.
Why is there a difference? What's the difference between arr before and now?
The difference is in the type. Before, arr had (roughly) type int * and now arr has type short *.
In C, a pointer is not only an address, it tells you what (in principle) the data type at that
address is. Thus, int * is a pointer to an int. Not only does it tell you the data type, but you can
also determine the data type's [Link] can find out the data type's size with
the sizeof() operator.

115
sizeof( int ) ==> 4
sizeof( short ) ==> 4
That's important, because that's how pointer arithmetic computes address. It uses the size of
the data type, which it knows from the pointer's [Link]'s the formula for computing the
address of ptr + i where ptr has type T *. then the formula for the address is:
addr( ptr + i ) = addr( ptr ) + [ sizeof( T ) * i ]
T can be a pointer
How does pointer arithmetic work if you have an array of pointers, for example:
int * arr[ 10 ] ;
int ** ptr = arr ;
In this case, arr has type int **. Thus, T has type int *. All pointers have the same size, thus
the address of ptr + i is:
addr( ptr + i ) = addr( ptr ) + [ sizeof( int * ) * i ]
= addr( ptr ) + [ 4 * i ]
Static arrays are constant
When you declare
int arr[ 10 ] ;
arr is a constant. It is defined to be the address, & arr[ 0 ].
You can't do the following:
int arr[ 10 ] ;

arr = arr + 1 ; // NO! Can't reassign to arr--it's constant


However, you can declare a pointer variable.
int arr[ 10 ] ;
int * ptr ;

ptr = arr + 1 ; // This is OK. ptr is a variable.


Parameter Passing an Array
If you pass an array to a function, it's type changes.
void foo( int arr[ 10 ], int size ) {
// code here
}
The compiler translates arrays in a parameter list to:
void foo( int * arr, int size ) {
// code here
}

116
Thus, it becomes arr becomes a pointer variable.
Why doesn't this cause problem? After all, won't we pass arr as an argument? Isn't arr a
constant?
Yes, it is. However, we pass a copy of the address to arr the parameter. Thus, the copy can be
manipulated while the original pointer address that was passed during the function call is
unchanged.
Subtraction
We can also compute ptr - i. For example, suppose we have an int array called arr.
int arr[ 10 ] ;
int * p1, * p2 ;

p1 = arr + 3 ; // p1 == & arr[ 3 ]


p2 = p1 - 2 ; // p1 == & arr[ 1 ]
We can have a pointer point to the middle of the array (like p1). We can then create a new
pointer that is two elements back of p1.
As it turns out, we can even point way past the end of the array.
int arr[ 10 ];
int * p1, * p2;

p1 = arr + 100; // p1 == & arr[ 100 ]


p2 = arr - 100; // p1 == & arr[ -100 ]
The compiler still computes an address, and does not core dump. For example, if arr is address
1000, then p1 is address 1400 and p2 is address 600. The compiler still uses the formula for
pointer arithmetic to compute the address.
Passing the Array Size
This is why it's usually important to keep track of the array size and pass it in as a parameter.
When you're in a function, you can't tell the size of the array. All you have is a pointer, and
that's it. No indication of how big that array is.
If you try to compute the array's size using sizeof, you just get 4.
// Compiler translates arr's type to int *
void foo ( int arr[], int size ) {
// Prints 4
cout << sizeof( arr ) ;

int arr2[ 10 ] ;

117
// Prints 40
cout << sizeof( arr2 ) ;
}

If you declare a local array (not using dynamic memory allocation), you can get the size of the
array. However, once you pass that array, all that's passed is the address. There's no
information about the array size anymore.

 Pointers on two dimensional Arrays


Suppose you declare:
int arr[ 10 ][ 12 ] ;
What type is arr? You may have been told that it's int **, but that's incorrect. Two
dimensional arrays (as declared above) are contiguous in memory. If you create an array of
pointers to dynamically allocated arrays, such as:
int * arr[ 10 ] ;
then, arr has type int ** (or at least has a type compatible with int **).
The type is rather complicated, and is due to the fact that arr[ 0 ] = & arr[ 0 ][ 0 ], arr[ 1 ] = &
arr[ 1 ][ 0 ], and in general, arr[ i ] = & arr[ i ][ 0 ].
Pointer arithmetic says that arr + i gives you & arr[ i ], yet this skips an entire row of 12
elements, i.e., skips 48 bytes times i. Thus, if arr is address 1000 then arr + 2 is address 1096.
If the array's type were truly int **, pointer arithmetic would say the address is 1008ten, so that
doesn't work.
Note: A two-dimensional array is not the same as an array of pointers to 1D array
The actual type for a two-dimensional array, is declared as:
int (*ptr)[ 10 ] ;
Which is a pointer to an array of 10 elements? Thus, when you do pointer arithmetic, it can
compute the size of the array and handle it correctly. The parentheses are NOT optional
above. Without the parentheses, ptr becomes an array of 10 pointers, not a pointer to an array
of 10 int.
If you have a conventional two dimensional array, and you want to compute the address
for arr[ row ][ col ] and you have ROWS rows (where ROWS is some constant)
and COLS columns, then the formula for the address in memory is:
addr( & arr[ row ][ col ] ) = addr( arr ) + [ sizeof( int ) * COLS * row ]+ [ sizeof( int ) * col ]
Two dimensional arrays are stored in row major order, that is, row by row. Each row
contains COLS elements, which is why you see COLS in the formula. In fact, you don't
see ROWS.

118
When you have a 2D array as a parameter to a function, there's no need to specify the number
of rows. You just need to specify the number of columns. The reason is the formula above.
The compiler can compute the address of an element in a 2D array just knowing the number
of columns.
Thus, the following is valid in C, i.e. it compiles:
void sumArr( int arr[][ COLS ], int numRows, int numCols ) {
}
The following is also valid in C.
void sumArr( int arr[ ROWS ][ COLS ], int numRows, int numCols ) {
}
The compiler ignores ROWS. Thus, any 2D array with the COLS columns and any number of
rows can be passed to this function.
The following, however, is NOT valid in C:
void sumArr( int arr[][], int numRows, int numCols ) {
}
It's not syntactically valid to declare int arr[][] in C.
However, it's OK to write:
void sumArr( int **arr, int numRows, int numCols ) {
}
Note that int **arr is an array of pointers (possibly to 1D arrays), while int arr[][ COLS ] is a
2D array. They are not the same type, and are not interchangeable.
 Pointer Subtraction
It turns out you can subtract two pointers of the same type. The result is the distance (in array
elements) between the two elements.
For example:
int arr[ 10 ] ;
int * p1 = arr + 2 ;
int * p2 = arr + 5 ;

cout << ( p2 - p1 ) ; // Prints 3


cout << ( p1 - p3 ) ; // Prints -3
The formula used is rather simple. Assume that p1 and p2 are both pointers of type T *. Then,
the value computed is:
( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )
This can result in negative values if p2 has a smaller address than p1.
p2 and p1 need not point to valid elements in an array. The formula above still works even

119
when p2 and p1 contain invalid addresses (because they contain some address).
Pointer subtraction isn't used very much, but can be handy to determine the distances between
two array elements (i.e., the difference in the array indexes). You may not know exactly
which element you're pointing to using pointer subtraction, but you can tell relative distances.

6.7 SUMMARY

At the end of this unit, we have covered the topics such as basic terminology of pointer. It has
been clearly given about how the pointer variables can be declared and how it can visualize
with a suitable example. In subsequent stages we have discussed about the role of & and *
operators.
6.8 KEYWORDS

 Pointer, & and *


 operator,
 Sizeof(),
 Null
6.9 QUESTIONS FOR SELF-STUDY
1. Briefly explain the role of pointers in C programming?
2. Discuss about the advantages and disadvantages using pointer in programming?
3. What is meaning of following declaration?
i. int(*ptr[5])();
4. Explain about various arithmetic operations on pointers?
5. Write a C program using pointer to find the memory address of all declared variables in
a program?
6.10 REFERENCES
 " Programming in ANSI C by E Balagurusamy
 The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Computer concepts and programming in c by [Link] and [Link] Prasad
 [Link]

120
UNIT – 7 STRINGS

Structure
7.0 Objectives
7.1 Introduction
7.2 Declaration and Initialization of String
7.3 Reading String from Terminal
7.4 Writing String to screen
7.5 Arithmetic Operations on String
7.6 String Handling Function
7.7 Summary
7.8 Key words
7.9 Questions for self-study
7.10 References

7.0 OBJECTIVES

At the end of this unit, you will be able to

 Understand the string concept


 Describe the string handling
 Explain string handling function

7.1 STRINGS

In C, array of character are called strings. A string is terminated by null character /0. For
example:
"c string unit"
Here, "c string unit" is a string. When, compiler encounters strings, it appends null character
at the end of string.

7.2 DECLARATION AND INITIALIZATION OF STRINGS

Strings are useful for communicating information from the program to the program user and,
thus are a part of all programming languages and applications. They are implemented
121
with characters arrays that behave like usual arrays with which we can perform regular
operations, including modification. Another way of implementing strings is
through pointers since character arrays act as pointers. These pointers point to string literals
and cannot be modified as string literals are stored in the read-only memory by most
compilers. Thus, any attempt at modifying them leads to undefined behavior.

Strings is declared in C in similar manner as arrays. Only difference is that, strings are
of char type.
char s[5];

Strings can also be declared using pointer.


char *p

Initialization of strings
In C, string can be initialized in different number of ways.

char c[]="abcd";
OR,
char c[5]="abcd";
OR,
char c[]={'a','b','c','d','\0'};
OR;
char c[5]={'a','b','c','d','\0'};

String can also be initialized using pointers


char *c="abcd";

7.3 READING STRINGS FROM TERMINAL


Reading words from user
char name[20];
scanf("%s",name);
String variable, name can only take a word. It is because when white space is encountered,
the scanf() function terminates.
C program to illustrate how to read string from terminal.
122
#include <stdio.h>
int main(){
char name[20];
printf("Enter name: ");
scanf("%s",name);
printf("Your name is %s.",name);
return 0;
}
Output
Enter name: Dennis Ritchie
Your name is Dennis.
Here, program will ignore Ritchie because, when the scanf() function takes only string before
the white space.

Reading a line of text


C program to read line of text manually.

#include <stdio.h>
int main(){
char name[30],ch;
int i=0;
printf("Enter name: ");
while(ch!='\n') //terminates if user hit enter
{
ch=getchar();
name[i]=ch;
i++;
}
name[i]='\0'; //inserting null character at end
printf("Name: %s",name);
return 0;
}
This process to take string is tedious. There are predefined functions gets() and puts in C
language to read and display string respectively.

123
#include<stdio.h>
int main(){
char name[30];
printf("Enter name: ");
gets(name); //Function to read string from user.
printf("Name: ");
puts(name); //Function to display string.
return 0;
}
Both, the above program have same output below:
Output
Enter name: Anil Ross
Name: Anil Ross
Passing Strings to Functions
String can be passed in similar manner as arrays as, string is also an array (of characters).

#include <stdio.h>
void Display(char ch[]);
int main(){
char c[50];
printf("Enter string: ");
gets(c);
Display(c); //Passing string c to function.
return 0;
}
void Display(char ch[]){
printf("String Output: ");
puts(ch);
}
Here, string c is passed from main() function to user-defined function Display(). In function
declaration in line 10, ch[] is the formal argument. It is not necessary to give the size of array
in function declaration.

7.4 WRITING STRINGS TO THE SCREEN

To write strings to the terminal, we use a file stream known as stdout. The most common
124
function to use for writing to stdout in C is the printf function, defined as follows:
Sample Code
int printf(const char *format, ...);
To print out a prompt for the user you can:
Sample Code
printf("Please type a name: \n");

The above statement prints the prompt in the quotes and moves the cursor to the next line.
If you wanted to print a string from a variable, such as our fname string above you can do this:
Sample Code
printf("First Name: %s", fname);

You can insert more than one variable, hence the "..." in the prototype for printf but this is
sufficient. Use %s to insert a string and then list the variables that go to each %s in your string
you are printing. It goes in order of first to last. Let's use a first and last name printing
example to show this:
Sample Code
printf("Full Name: %s %s", fname, lname);

The first name would be displayed first and the last name would be after the space between
the %s's.

7.5 ARITHMETIC OPERATIONS ON STRINGS

Characters in C can be used just like integers when used with arithmetic operators. This is
nice, for example, in low memory applications because unsigned chars take up less memory
than do regular integers as long as your value does not exceed the rather limited range of an
unsigned char.
For example: consider the following piece of code
charmath.c:
#include <stdio.h>
void main() {
unsigned char val1 = 20;
unsigned char val2 = 30;
int answer;

125
printf("%d\n", val1);
printf("%d\n", val2);

answer = val1 + val2;


printf("%d + %d = %d\n", val1, val2, answer);

val1 = 'a';
answer = val1 + val2;

printf("%d + %d = %d\n", val1, val2, answer);


}

First we make two unsigned character variables and give them number values. We then add
them together and put the answer into an integer variable. We can do this without a cast
because characters are an alphanumeric data type. Next we set var1 to an expected character
value, the letter lowercase a. Now this next addition adds 97 to 30.

This is because the ASCII value of lowercase a is 97. So it adds 97 to 30, the current value in
var2. Notice it did not require casting the characters to integers or having the compiler
complain. This is because the compiler knows when to automatically change between
characters and integers or other numeric types.

7.6 STRING HANDLING FUNCTIONS

One can perform different type of string operations manually like: finding length of string,
concatenating (joining) two strings etc. But this process is tedious. To perform these
operations, there are different library functions.

 String Manipulations Using Library Functions


Strings are often needed to be manipulated according to the problem. All string manipulation
can be done manually by the programmer but, this makes programming complex and large.
To solve this, the C library supports a large number of string handling functions.
There are numerous functions defined in "string.h" header file. Few commonly used string
handling functions are discussed below:

Function Work Of Function

126
Function Work Of Function

strlen() Calculates the length of string


strcpy() Copies a string to another string
strcat() Concatenates(joins) two strings
strcmp() Compares two string
strlwr() Converts string to lowercase
strupr() Converts string to uppercase

Strings handling functions are defined under "string.h" header file, i.e, you have to include the
code below to run string handling functions.
#include <string.h>
Example to show how to "string.h" header file

#include <stdio.h>
#include <string.h>
int main(){
char s[]="Programiz";
int length;
length=strlen(s); /* Compiler will show error if you
use
this statement without using code #include <string.h>
in line number 2*/
printf("%d",length);
return 0;
}

gets() and puts()


Functions gets() and puts() are two string functions to take string input from user and display
string respectively as mentioned in previous chapter.

#include<stdio.h>
int main(){
char name[30];
printf("Enter name: ");
gets(name); //Function to read string from user.

127
printf("Name: ");
puts(name); //Function to display string.
return 0;
}
Though, gets() and puts() function handle string, both these functions are defined in "stdio.h"
header file.

7.7 SUMMARY

In this unit we have introduced string operations which are supported in C programming. We
have seen how strings can be declared and initialized. Later we have seen an example how to
read and write the string from terminal and to screen respectively. At the end the section we
have list out some standard library function in support of string operations.

7.8 KEYWORDS
 String,
 char,
 strlen,
 strrev,

7.9 QUESTIONS FOR SELF STUDY


1. Explain about string data type which is supported in C?
2. How can an arithmetic operation can be performed on string?
3. Write a C program to accept two strings and concatenate them?
4. Write a C program to reverse a string?

7.10 REFERENCES
 Programming In ANSI C by E Balagurusamy
 The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden

128
UNIT – 8 STRUCTURE AND UNIONS

Structure
8.0 Objectives
8.1 Introduction
8.2 Structure Variable Declaration
8.3 Accessing Members of Structure
8.4 Nested Structure
8.5 Structure and Functions
8.6 Union-Defining Structure
8.7 Array of structure
8.8 Structure assignment
8.9 Structures as Function Arguments
8.10 Pointers to structures
8.11 Typedefs
8.12 Unions
8.13 Bit fields
8.14 Summary
8.15 Key words
8.16 Questions for self-study
8.17 References

8.0 OBJECTIVES

At the end of this unit, you will be able to

 Understand advance concept on pointers


 Sketch out the working principle of pointer to function as argument
 Explain various memory related function
 List out the various preprocess directives and bitwise operators

8.1 INTRODUCTION

Structure is the collection of variables of different types under a single name for better
handling. For example: You want to store the information about person about his/her name,
citizenship number and salary. You can create this information separately but, better approach
129
will be collection of this information under single name because all these information are
related to person.
 Structure Definition in C
Keyword struct is used for creating a structure.
Syntax of structure
struct structure_name
{
data_type member1;
data_type member2;
.
.
data_type memebern;
};
We can create the structure as mentioned in above example as:
struct person
{
char name[50];
int cit_no;
float salary;
};
This declaration above creates the derived data type struct person, i.e, a user-defined type.

8.2 STRUCTURE VARIABLE DECLARATION

When a structure is defined, it creates a user-defined type but, no storage is allocated. You can
use structure variable using tag name in any part of program. For example:
struct person
{
char name[50];
int cit_no;
float salary;
};
struct person p1, p2, p[20];
Another way of creating sturcture variable is:
struct person
{

130
char name[50];
int cit_no;
float salary;
}p1 ,p2 ,p[20];

In the above cases, 2 variables p1, p2 and array p having 20 elements of type struct
person are created.

8.3 ACCESSING MEMBERS OF A STRUCTURE

There are two types of operators used for accessing members of a structure.
Member operator(.)
Structure pointer operator(->) (will be discussed in respective chapter of structure and
pointers)
Any member of a structure can be accessed as: structure_variable_name.member_name
Suppose, if we want to access salary for variable p2. Then, it can be accessed as: [Link]
Consider following Example of structure

#include <stdio.h>
struct Distance{
int feet;
float inch;
}d1,d2,sum;
int main(){
printf("1st distance\n");
printf("Enter feet: ");
scanf("%d",&[Link]); //input of feet structure for d1
printf("Enter inch: ");
scanf("%f",&[Link]); //input of inch structure for d1
printf("2nd distance\n");
printf("Enter feet: ");
scanf("%d",&[Link]); //input of feet for structure variable d2
printf("Enter inch: ");
scanf("%f",&[Link]); //input of inch for structure variable d2
[Link]=[Link]+[Link];
[Link]=[Link]+[Link];
if ([Link]>12){ //If inch is greater than 12, changing it to feet.
++[Link];
[Link]=[Link]-12;
}
printf("Sum of distances=%d\'-%.1f\"",[Link],[Link]); //printing
sum of distance d1 and d2
return 0;
}

131
Structure is the collection of variables of different types under a single name for better
handling. For example: You want to store the information about person about his/her name,
citizenship number and salary. You can create this information separately but, better approach
will be collection of these information under single name because all these information are
related to person.
 Keyword typedef while using structure
Programmers are generally use typedef while using structure in C language. For example:
typedef struct complex{
int imag;
float real;
}comp;

comp c1,c2;
Here, typedef keyword is used in creating a type comp(which is same type as struct complex).
Then, two structure variables c1 and c2 are created by this comp type.

8.4 NESTED STRUCTURE

In the C programming language, a nested structure is a data structure that contains another
data structure within it. This means that a structure can be a member of another structure,
creating a hierarchy of related data. Before understanding nested structure, we have to
understand what is structure in c.
 Structures within structures
In C, the structure is a user-defined data type that is used to store a group of items of different
data types as a single data type. Each element of a structure is known as its [Link]
can be nested within other structures in C programming.
struct complex
{
int imag_value;
float real_value;
};
struct number{
struct complex c1;
int real;
}n1,n2;
Suppose you want to access imag_value for n2 structure variable then, structure

132
member n1.c1.imag_value is used.
typedef struct complex complex; complex_no c1,c2,c3;
Here, typdef is used to create a type complex. This type complex is then used in declaring
variables c1, c2 and c3.

8.5 STRUCTURE AND FUNCTION

In C, structure can be passed to functions by two methods:


o Passing by value (passing actual value as argument)
o Passing by reference (passing address of an argument)
 Passing structure by value
A structure variable can be passed to the function as an argument as normal variable. If
structure is passed by value, change made in structure variable in function definition does not
reflect in original structure variable in calling function.
For example consider the C program to create a structure student, containing name and roll.
Ask user the name and roll of a student in main function. Pass this structure to a function and
display the information in that function.
#include <stdio.h>
struct student{
char name[50];
int roll;
};
void Display(struct student stu);
/*function prototype should be below to the structure
declaration
otherwise compiler shows error */
int main(){
struct student s1;
1 printf("Enter student's name: ");
scanf("%s",&[Link]);
printf("Enter roll number:");
scanf("%d",&[Link]);
Display(s1); //passing structure variable s1 as
argument
return 0;
}
void Display(struct student stu){
printf("Output\nName: %s",[Link]);
printf("\nRoll: %d",[Link]);
}
Output
Enter student's name: Kevin Amla
Enter roll number: 149
Output

133
Name: Kevin Amla
Roll: 149

 Passing structure by reference


The address location of structure variable is passed to function while passing it by reference.
If structure is passed by reference, change made in structure variable in function definition
reflects in original structure variable in the calling function.
Write a C program to add two distances (feet-inch system) entered by user. To solve this
program, make a structure. Pass two structure variable (containing distance in feet and inch)
to add function by reference and display the result in main function without returning it.

#include <stdio.h>
struct distance{
int feet;
float inch;
};
void Add(struct distance d1,struct distance d2, struct distance
*d3);

//function prototype
int main()
{
struct distance dist1, dist2, dist3;
printf("First distance\n");
printf("Enter feet: ");
scanf("%d",&[Link]);
printf("Enter inch: ");
scanf("%f",&[Link]);
printf("Second distance\n");
printf("Enter feet: ");
scanf("%d",&[Link]);
printf("Enter inch: ");
scanf("%f",&[Link]);
Add(dist1, dist2, &dist3);

/*passing structure variables dist1 and dist2 by value whereas


passing structure variable dist3 by reference */

printf("\nSum of distances = %d\'-%.1f\"",[Link],


[Link]);
return 0;
}
void Add(struct distance d1,struct distance d2, struct distance
*d3)
{
//Adding distances d1 and d2 and storing it in d3
d3->feet=[Link]+[Link];
d3->inch=[Link]+[Link];
134
if (d3->inch>=12) {
//if inch is greater or equal to 12, converting it to feet.
d3->inch-=12;
++d3->feet;
}
}

Output
First distance
Enter feet: 12
Enter inch: 6.8
Second distance
Enter feet: 5
Enter inch: 7.5
Sum of distances = 18'-2.3"
In this program, structure variables dist1 and dist2 are passed by value (because value of dist1
and dist2 does not need to be displayed in main function) and dist3 is passed by reference, i.e,
address of dist3 (&dist3) is passed as an argument. Thus, the structure pointer variable d3
points to the address of dist3. If any change is made in d3 variable, effect of it is seed in dist3
variable in main function.

8.5 STRUCTURE AND FUNCTION

Structures can be passed as function arguments like all other data types. We can pass
individual members of a structure, an entire structure, or a pointer to a structure to a function.
Like all other data types, a structure or a structure member or a pointer to a structure can be
returned by a function. Structure-function helps in writing better code. Structure functions in
C make the code efficient. A code that consumes less memory and takes less time to execute
is good.

Before we jump into the concept of structure and functions in C. Let us go through some
prerequisites. Functions are reusable codes that perform a specific task when they are called.
Derived data types are formed from fundamental data types. Structures are one such user-
defined data type. The structures can have many fundamental data types known as structure
members grouped into a single user-defined data type. Functions are the blocks of codes that
perform a specific task when called. We need to pass the parameters to the function, and the
function returns the result. Structures can also be passed as parameters to the functions.

135
When a function is called, if we pass the values of the variables to the function, it is known as
the call by value. Instead of passing the values, if we pass the address of the variables to the
function, it is known as call by reference. The dot (.) operator is used to access a structure
member. The arrow (->) operator is to access the members of a structure when the pointer
references the structure. With these basics of structures and functions, It will be easy to
understand structure functions clearly.
Structure-function can be effectively used while writing code. Structures can be passed as
arguments to the functions. This can be done in three ways. They are,
o Passing the members of the structures as an argument.
o Passing the entire structure as an argument.
o Passing the address of the structure as arguments.

8.6 UNION DEFINING STRUCTURE

Unions are quite similar to the structures in C. Union is also a derived type as structure. Union
can be defined in same manner as structures just the keyword used in defining union
in union where keyword used in defining structure was struct.
union car{
char name[50];
int price;
};
Union variables can be created in similar manner as structure variable.
union car{
char name[50];
int price;
}c1, c2, *c3;

OR;

union car{
char name[50];
int price;
};
union car c1, c2, *c3;

In both cases union variables c1, c2 and union pointer variable c3 of type union car is

136
created.
Accessing members of an union
Again, the member of unions can be accessed in similar manner as that structure. Suppose, we
you want to access price for union variable c1 in above example, it can be accessed as
[Link]. If you want to access price for union pointer variable c3, it can be accessed
as (*c3).price or as c3->price.
 Difference between union and structure
Though unions are similar to structure in so many ways, the difference between them is
crucial to understand. This can be demonstrated by an example.

#include <stdio.h>
union job { //defining a union
char name[32];
float salary;
int worker_no;
}u;
struct job1 {
char name[32];
float salary;
int worker_no;
}s;
int main(){
printf("size of union = %d",sizeof(u));
printf("\nsize of structure = %d", sizeof(s));
return 0;
}
Output
size of union = 32
size of structure = 40
There is difference of memory allocation between union and structure as suggested in above
example. The amount of memory required to store a structure variable is the sum of memory
size of all members.

137
But, the memory required to store a union variable is the memory of largest element of union.

 Difference between structure and union


As you know, all members of structure can be accessed at any time. But, only one member of
union can be accessed at a time in case of union and other members will contain garbage
value.

#include <stdio.h>
union job {
char name[32];
float salary;
int worker_no;
}u;
int main(){
printf("Enter name:\n");
scanf("%s",&[Link]);
printf("Enter salary: \n");
scanf("%f",&[Link]);
printf("Displaying\nName :%s\n",[Link]);
printf("Salary: %.1f",[Link]);
return 0;
}
Output
Enter name
Hillary
Enter salary
1234.23
Displaying
Name: f%Bary
Salary: 1234.2
Note: You may get different garbage value of name.

When code in line no. 9 is executed, Hillary will be stored in [Link] and other members of
union will contain garbage value. When code all will executed, 1234.23 will be stored in
[Link] and other members will contain garbage value. Thus in output, salary is printed
accurately but, name displays some random string.

138
8.7 ARRAY OF STRUCTURE

It is possible to define a array of structures for example if we are maintaining information of


all the students in the college and if 100 students are studying in the college. We need to use
an array than single variables. We can define an array of structures as shown in the following
example:
structure information
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
}
student[100];
An array of structures can be assigned initial values just as any other array can.
Each element is a structure that must be assigned corresponding initial values as
illustrated below.
#include< stdio.h >
{
struct info
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
}
struct info std[100];
int I,n;
printf(“Enter the number of students”);
scanf(“%d”,&n);
printf(“ Enter Id_no,name address combination age\m”);
for(I=0;I < n;I++)
scanf(%d%s%s%s
%d”,&std[I].id_no,std[I].name,std[I].address,std[I].combinatio
n,&std[I].age);
139
printf(“\n Student information”);
for (I=0;I< n;I++)
printf(“%d%s%s%s%d\n”,”,std[I].id_no,std[I].name,std[I].address,std[I].combination,std[I].a
ge);
}

8.8 STRUCTURE ASSIGNMENT

The following assignment of a struct to another struct does what one might expect. It is not
necessary to use memcpy() to make a duplicate of a struct type. The memory is already given
and zeroed by just declaring a variable of that type regardless of member initialization. This
should not be confused with the requirement of memory management when dealing with a
pointer to a struct.

#include <stdio.h>

/* Define a type point to be a struct with integer members x, y */


typedef struct {
int x;
int y;
} point;

int main(int argc, char * argv[]) {

/* Define a variable p of type point, and initialize all its members inline! */
point p = {1,2};

/* Define a variable q of type point. Members are initialized with the defaults for their
derivative types such as 0. */
point q;

/* Assign the value of p to q, copies the member values from p into q. */


q = p;

/* Change the member x of q to have the value of 2 */


q.x = 2;

/* Demonstrate we have a copy and that they are now different. */


if (p.x != q.x) printf("The members are not equal! %d != %d", p.x, q.x);
}

8.9 STRUCTURES AS FUNCTION ARGUMENTS

A structure can be passed as a function argument just like any other variable. This raises a few
practical issues. Where we wish to modify the value of members of the structure, we must
140
pass a pointer to that structure. This is just like passing a pointer to an int type argument
whose value we wish to [Link] we are only interested in one member of a structure, it is
probably simpler to just pass that member. This will make for a simpler function, which is
easier to re-use. Of course if we wish to change the value of that member, we should pass a
pointer to [Link] a structure is passed as an argument, each member of the structure is
copied. This can prove expensive where structures are large or functions are called frequently.
Passing and working with pointers to large structures may be more efficient in such cases.

#include <stdio.h>
void input (dob_st *);
int main ()
{
typedef struct
{
int year;
int month;
int day;
}
dob_st;

dob_st date;
dob_st *p;
p=&date;
input (*p);
printf("%02i.",p->day);
printf("%02i.",p->month);
printf("%i.",p->year);

return 0;
}
void upis (dob_st *p)
{
printf ("Date of birth:\nDay?\n");
scanf ("%i",&(p->day));
printf ("Month?\n");
scanf ("%i",&(p->month));

141
printf ("Year?\n");
scanf ("%i",&(p->year));
}

8.10 POINTERS TO STRUCTURES

Pointers can be used to refer to a struct by its address. This is particularly useful for passing structs to
a function by reference. The pointer can be dereferenced just like any other pointer in C —
using the *operator. There is also a -> operator in C which dereferences the pointer to struct
(left operand) and then accesses the value of a member of the struct (right operand).

struct point {
int x;
int y;
} my_point;

struct point *p = &my_point; /* To declare p as a pointer of type struct point */

(*p).x = 8; /* To access the first member of the struct */


p->x = 8; /* Another way to access the first member of the struct */

8.11 TYPEDEFS

Typedef is a keyword. The more theoretical information about the typedef is given in last unit.
Readers are directed to refer theoretical aspects from last unit. In this section we will see
programmatic aspects using typedef.

typedef struct {
int account_number;
char *first_name;
char *last_name;
float balance;
} account;
Different users have differing preferences; proponents usually claim:
 shorter to write
 can simplify more complex type definitions
As an example, consider a type that defines a pointer to a function that accepts pointers to
142
struct types and returns a pointer to struct:
Without typedef:
struct point {
int x;
int y;
};
typedef struct point *(*point_compare_t) (struct point *a, struct point *b);
With typedef:
struct point {
int x;
int y;
};
typedef struct point point_t;
typedef point_t *(*point_compare_t) (point_t *a, point_t *b);

If neither typedef were used in defining a function that takes a pointer to a type of the above
function pointer, the following code would have to be used. Although valid, it becomes
increasingly hard to read quickly.

/* Using the struct point type from before */

/* Define a function that returns a pointer to the biggest point, using a function to do the
comparison. */
struct point * biggest_point (size_t size, struct point *points, struct point *(*point_compare)
(struct point *a, struct point *b))
{
int i;
struct point *biggest = NULL;

for (i=0; i < size; i++) {


biggest = point_compare(biggest, points + i);
}
return biggest;
}

Now with all of the typedefs being used you should see that the complexity of the function

143
signature is drastically reduced.

/* Using the struct point type from before and all of the typedefs */

/* Define a function that returns a pointer to the biggest point, using a function to do the
comparison. */
point_t * biggest_point(size_t size, point_t * points, point_compare_t point_compare )
{
int i;
point_t * biggest = NULL;

for (i=0; i < size; i++) {


biggest = point_compare(biggest, points + i);
}
return biggest;
}

However, there are a handful of disadvantages in using them:

 They pollute the main namespace (see below), however this is easily overcome with prefixing
a library name to the type name.
 Harder to figure out the aliased type (having to scan/grep through code), though most IDEs
provide this lookup automatically.
 Typedefs do not really "hide" anything in a struct or union — members are still accessible
([Link]) (To really hide struct members, one needs to use 'incompletely-declared'
structs.)

8.12 UNIONS

In computer science, a union is a value that may have any of several representations or
formats; or a data structure that consists of a variable which may hold such a value.
Some programming languages support special data types, called union types, to describe such
values and variables. In other words, a union type definition will specify which of a number of
permitted primitive types may be stored in its instances, e.g. "float or long integer". Contrast
with a record, which could be defined to contain a float and an integer; whereas, in a union,

144
there is only one value at a time.

In type theory, a union has a sum type.

Depending on the language and type, a union value may be used in some operations, such
as assignment and comparison for equality, without knowing its specific type. Other
operations may require that knowledge, either by some external information, or by the use of
a tagged union.

Because of the limitations of their use, untagged unions are generally only provided in
untyped languages or in an unsafe way (as in C). They have the advantage over simple tagged
unions of not requiring space to store the tag.

The name "union" stems from the type's formal definition. If one sees a type as the set of all
values that that type can take on, a union type is simply the mathematical union of its
constituting types, since it can take on any value any of its fields can. Also, because a
mathematical union discards duplicates, if more than one field of the union can take on a
single common value, it is impossible to tell from the value alone which field was last written.

However, one useful programming function of unions is to map smaller data elements to
larger ones for easier manipulation. A data structure, consisting for example of 4 bytes and a
32-bit integer, can form a union (in this case with an unsigned 64-bit integer) and thus be
more readily accessed for purposes of comparison [Link] a structure, all of the members of a
union are by default public. The keywords private, public, and protected may be used inside a
struct or a union in exactly the same way they are used inside a class for defining private,
public, and protected members.

8.13 BIT FIELDS

A bit field is a common idiom used in computer programming to compactly store multiple
logical values as a short series of bits where each of the single bits can be addressed
separately. A bit field is most commonly used to represent integral types of known, fixed bit-
width. A well-known usage of bit-fields is to represent single bit flags with each flag stored in
a separate bit.
A bit field is distinguished from a bit array in that the latter is used to store a large set of bits
indexed by integers and is often wider than any integral type supported by the language. Bit
fields, on the other hand, typically fit within a machine word, and the denotation of bits is
independent of their numerical index.

8.14 SUMMARY
At the end this unit we have learnt the concepts about structure and unions. We have

145
introduced structure through basic thing such as declaring a structure, accessing structure
members. A suitable piece of code as an example taken and demonstrated how exactly the
structure concepts works. In later sections we have touch upon advanced concepts on structure
such as passing structure as a function argument and returning the value. In the last section of
this unit, we have introduced union defining function.

8.15 KEYWORDS

 struct,
 typedef,
 passing by reference

8.16 QUESTIONS FOR SELF-STUDY

1. What is structure? How this is useful in programming?


2. How can structure be treated as a function argument?
3. Explain the concept of union defined functions?
4. Do survey and prepare report on how exactly the structure is different from class in
object orient programming?
8.17 REFERENCE

 Programming in ANSI C by E Balagurusamy


 The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
 Expert C Programming: Deep C Secrets by Peter Van, Der Linden
 Computer concepts and programming in c by [Link] and [Link] Prasad
 [Link]

146
UNIT 9: INPUT AND OUTPUT

Structure:

9.0 Objectives
9.1 Introduction
9.2 Input and output

9.3 The printf() function


9.4 The scanf() function
9.5 Getchar() and Putchar() function
9.6 Gets() and puts() function
9.7 File handling in C
9.8 Summary
9.9 Keywords
9.10 Questions
9.11 References

9.0 OBJECTIVES

After studying this unit, we will be able to explain the following:


 Input and output
 The printf() function
 The scanf() function

9.1 INTRODUCTION

Input and Output in C programming language are accomplished through library functions. C
programming language has defined many library functions for input and output. In C
programming, scanf () and printf () functions are most commonly used standard library function for
taking input form keyboard and printing output on screen respectively. Here, when we are say Input
that means feeding data into C program using the keyboard and

147
output means printing data on screen. We will discuss file Input and Output in separate section. Most of

the standard library function for Input and Output is defined in stdio.h header file.C programming

language treats all the I/O devices and files as stream of data. A C programreading data from

keyboard is similar to reading data from a file similarly printing data on screen is similar to writing

data on a file. Three streams gets automatically attached when a program starts execution.

9.2 INPUT AND OUTPUT

Input refers to feeding data into the program, and Output refers to getting data out of the program.
Input and Output in C are done using the Standard Input/Output library, which we could include in the
program using stdio.h header file consists of Input and Output functions in C like scanf() for input and
printf() for output. Streams in C programming are used to take input or give output to put away worries
about the data's initial location or final destination.

Input is given through the keyboard, and output may be shown on screen or printed through the
printer or in another way. Still, for the different devices, there may be a different type of process for
input/output, which may be a problem for the programmer. To avoid this, all input/output are done
using streams in C, which handles input/output without taking care of where input is coming and the
destination of the output. It can be added to any C program by introducing a Standard Input/Output
library using stdio.h header.

Stream is the sequence of bytes of data in the form of a sequence of characters. While taking input, we
get a sequence of characters entering into our program, that is, the input stream and for output, we
send a sequence of characters out from our program, which is the output stream. The main advantage of
the stream is it makes input/output programming independent of the device.

Input means to provide the program with some data to be used in it.
Output means to display data on the screen or write the data to a printer or a file.
The C programming provides standard library functions to read any given input and display
output on the console.

While dealing with input-output operations in C, we use the following two streams:

148
Standard Input (stdin)
Standard Output (stdout)
Standard input or stdin is used for taking input.
Standard output or stdout is used for giving output.
The functions used for standard input and output are present in the stdio.h header file.
Hence, to use those functions, we need to include the stdio.h header file in our program, as
shown below.

#include<stdio.h>
Functions Used for Input and Output
C language offers us several built-in functions for performing input/output operations. The following
are the functions used for standard input and output:

1. printf() function - Show Output


2. scanf() function - Take Input
3. getchar() and putchar() function
4. gets() and puts() function

In C Language, output devices like computer monitors, printers, etc. are treated as files and the same
process is followed to write output to these devices as would have been followed to write the output to
a file.

9.3 THE PRINTF() FUNCTION

The printf() function is the most used function in the C language.


This function is defined in the stdio.h header file and is used to show output on the console
(standard output).

Following is how the printf() function is defined in the C stdio.h library.

int printf(const char )*format, ...);

Copy
It writes the C string pointed by the format pointer to the standard output (stdout).
On success, the total number of characters written is returned.

149
This function is used to print a simple text sentence or value of any variable which can
be of int, char, float, or any other datatype.

printf() Code Examples

Let's start with a simple example.

1. Print a sentence

Let's print a simple sentence using the printf() function. #include

<stdio.h>

int main() {

// using printf()

printf("Welcome to Studytonight"); return

0;

Copy

Welcome to study tonight


This one is a very common code example.

To understand the complete code and structure of a basic C language program, check Hello
World Program in C.

2. Print an Integer value

We can use the printf() function to print an integer value coming from a variable using the %d
format specifier.

For example,

#include <stdio.h>

150
int main() {
int x = 10;
// using printf()
printf("Value of x is: %d", x);
return 0;
}

Value of x is: 10

 In the program, above we have used the %d format specifier, to specify the type of
value that will be added there.
 The format specifiers %d and %i are used for integer values.

3. Print a Character value

The %c format specifier is used to print character variable values using the printf() function.

4. Print a Float and a Double value

In the code example below, we have used the printf() function to print values of a float
and double type variable.

For float value we use the %f format specifier and for double value we use the %lf format
specifier.

#include <stdio.h>
int main() {
// using printf() float
num1 = 15.50;
double num2 = 15556522.0978678
printf("Value of num1 is: %f \n", num1);
printf("Value of num2 is: %lf", num2); return
0;
}
Output:
Value of num is: 15.500000

151
Value of num2 is 15556522.097868
We have used the \n Escape sequence which is used for a newline at the end of the first
printf() statement so that the next printf() statement output is shown in the next line.

5. Print multiple outputs


We can use a single printf() function to display values of multiple variables. #include
<stdio.h>

int main() {
// using printf() for multiple outputs int
day = 20;
int month = 11; int
year = 2021;
printf("The date is: %d-%d-%d", day, month, year);
return 0;
}

Output: The date is 20-11-2021

As you can see in the code example above, we can do the formatting and print values of
multiple variables using the printf() function.

We can also perform some simple calculations inside printf(). Here is a simple example of that,

#include <stdio.h>
int main()
{
int a = 5, b = 6; printf("%d", a + b);
return 0;
}

Output :11

152
Format Specifiers

 To print values of different data types using the printf() statement and while taking
input using the scanf() function, it is mandatory to use format specifiers.

Datatype Format Specifier

int %d, %i

char %c

float %f

double %lf

short int %hd

unsigned int %u

long int %li

long long int %lli

unsigned long int %lu

unsigned long long int %llu

signed char %c

unsigned char %c

long double %Lf

 It is a way to tell the compiler what type of data is in a variable.


 Some examples are %c, %d, %f, etc.

Here is a list of all the format specifiers.

153
9.4 THE SCANF () FUNCTION

When we want to take input from the user, we use the scanf() function and store the input value
into a variable.

Following is how the scanf() function is defined in the C stdio.h library.

int scanf(const char *format, ...);


It reads data from stdin and stores it according to the parameter format into the
locations pointed by the additional arguments.
On success, the function returns the number of items of the argument
list successfully filled.
The scanf() function can be used to take input of any type from the user.
All you have to take care of is that the variable in which you store the value should have the
same data type.

Here is the syntax for scanf():

scanf("%x", &variable);
where, %x is the format specifier.

Using the format specifier, we tell the compiler what type of data to expect from the user.
The & is the address operator which tells the compiler the address of the variable so that the
compiler can store the user input value at that address.

scanf() Code Examples

Let's start with a simple example.

1. Input Integer value

If we have to take an integer value input from the user, we have to define an integer variable and then
use the scanf() function.

#include <stdio.h>

154
int main() {
// using scanf()
int user_input;
printf("Please enter a number: ");
scanf("%d", &user_input); printf("You
entered: %d", user_input); return 0;
}

Please enter a number: 7

You entered: 7

NOTE: If you use our compiler, then while running the code example above, there is a button for
Input at the top-right corner of the editor, you can click on it and provide custom value for input.

 In the above code example, we have used %d format specifier to inform the
scanf() function that user input will be of type int.
 And we have also used & symbol before the name of the variable, because
&user_input refers to the address of the user_input variable where the input value will
be stored.

2. Input Float value

Just like integer value, we can take input for any different datatype. Let's see an example of float
type value.

#include <stdio.h>
int main() {
// using scanf()
float user_input;
printf("Please enter a decimal number: "); scanf("%f",
&user_input);
printf("You entered: %f", user_input);

155
return 0;
}
Output:

Please enter a decimal number: 7.007 You entered: 7.007

 We have used the %f format specifier and defined a float type variable.
 Try doing the same for taking a double type value as user input.
 The format specifier for double is %lf.

Input Character value


Let's see how we can take a simple character input from the user. #include
<stdio.h>
int main() {
// using scanf()
char gender;
printf("Please enter your gender (M, F or O): ");
scanf("%c", &gender);
printf("Your gender: %c", gender); return
0;
}
Copy

Please enter your gender (M, F or O): M

Your gender: M

4. Take Multiple Inputs from the User


In the below code example, we are taking multiple inputs from the user and saving them into different
variables.
#include <stdio.h>
int main() {
// using scanf() for multiple inputs char
gender;

156
int age;
printf("Enter your age and then gender(M, F or O): "); scanf("%d
%c", &age, &gender);
printf("You entered: %d and %c", age, gender);

return 0;
}

Output:

Enter your age and then gender(M, F or O): 32 M

You entered: 32 and M

Return Value of printf() & scanf()


 The printf() function returns the number of characters printed by it,
 and scanf() function returns the number of characters read by it.
int i = printf("studytonight");
printf("Value of i is: %d", i);

studytonightValue of i is: 12

 In this program printf("studytonight"); will return 12 as a result, which will be stored


in the variable i, because the word studytonight has 12 characters.
 The first printf() statement will print the statement studytonight on the output too.

9.5 GETCHAR() & PUTCHAR() FUNCTIONS

The getchar and putchar functions are used for taking character input from the user and printing the
character as output.

The getchar() function

The getchar() function reads a character from the terminal and returns it as an integer.
This function reads only a single character at a time.

Here is the syntax for the getchar() function:

157
int getchar(void);
You can use this method in a loop if you want to read more than one character. The

putchar() function

The putchar() function displays the character passed to it on the screen and returns the same
character.
This function too displays only a single character at a time.

Here is the syntax for the putchar() function:

int putchar(int character);


In case you want to display more than one character, use putchar() method in a loop. #include
<stdio.h>
void main( )
{
int c;
printf("Enter a character");
/*
Take a character as input and
store it in variable c
*/
c = getchar();
/*
display the character stored in
variable c
*/
putchar(c);
}

Output:

Enter a character: Studytonight S

158
When you will compile the above code, it will ask you to enter a value. When you will enter the value,
it will display the value you have entered.

9.6 GETS() & PUTS() FUNCTIONS

The gets and puts functions are used for taking string input and giving string output. The gets()
function
The gets() function reads a line of text from stdin(standard input) into the buffer pointed to by str
pointer, until either a terminating newline or EOF (end of file) occurs.
Here is the syntax for the gets() function:
char* gets(char* str);
The puts() function
The puts() function writes the string str with a newline character ('\n') at the end to stdout. On success,
a non-negative value is returned.
Here is the syntax for the gets() function:

int puts(const char* str);

str is the pointer to an array of chars where the C string is stored (Don't worry if you are not able to
understand this now.)

#include <stdio.h>

void main()
{
/* character array of length 100 */ char
str[100];
printf("Enter a string: ");
gets(str);
puts(str);
getch();
return 0;
}
Output:

Enter a string: Studytonight

Studytonight

159
 When you will compile the above code, it will ask you to enter a string.
 When you will enter the string, it will display the value you have entered.

The gets() function is considered dangerous to use and should be avoided. We get a warning when we
compile any code in which we have used gets() function. This is because the function doesn't know how
big the buffer is, so it continues reading until it finds a newline or encounters EOF, and may overflow
the bounds of the buffer it was given. We can use alternatives to gets() function, like the fgets()
function.

The fgets() function

Here is the syntax for the fgets() function:

char* fgets(char* str, int num, FILE* stream);


 It reads characters and stores them as a C string into str until (num-1) characters have
been read or either a newline or the end-of-file is reached, whichever happens first.
 A newline character makes fgets stop reading, but it is considered a valid character by
the function and included in the string copied to str.
 On success, the function returns the str.
For example,

#include <stdio.h>
#define MAX 10 int
main()
{
char str[MAX]; fgets(str,
MAX, stdin);
printf("The string is: %s", str);
return 0;
}

Output: abcdefghijkl

The string is: abcdefghij

160
9.7 FILE HANDLING IN C
File handing in C is the process in which we create, open, read, write, and close operations on a file.
C language provides different functions such as fopen(), fwrite(), fread(), fseek(), fprintf(), etc. to
perform input, output, and many different C file operations in our program.

Why do we need File Handling in C?


So far the operations using the C program are done on a prompt/terminal which is not stored
anywhere. The output is deleted when the program is closed. But in the software industry, most
programs are written to store the information fetched from the program. The use of file handling is
exactly what the situation calls for.

In order to understand why file handling is important, let us look at a few features of using files:

Reusability: The data stored in the file can be accessed, updated, and deleted anywhere
and anytime providing high reusability.
Portability: Without losing any data, files can be transferred to another in the computer
system. The risk of flawed coding is minimized with this feature.
Efficient: A large amount of input may be required for some programs. File handling
allows you to easily access a part of a file using few instructions which saves a lot of time
and reduces the chance of errors.
Storage Capacity: Files allow you to store a large amount of data without having to
worry about storing everything simultaneously in a program.
Types of Files in C
A file can be classified into two types based on the way the file stores the data. They are as follows:

Text Files
Binary Files
1. Text Files
A text file contains data in the form of ASCII characters and is generally used to store a
stream of characters.

 Each line in a text file ends with a new line character (‘\n’).
 It can be read or written by any text editor.
 They are generally stored with .txt file extension.

161
 Text files can also be used to store the source code.
2. Binary Files
A binary file contains data in binary form (i.e. 0’s and 1’s) instead of ASCII characters. They
contain data that is stored in a similar manner to how it is stored in the main memory.
 The binary files can be created only from within a program and their contents
can only be read by a program.
 More secure as they are not easily readable.
 They are generally stored with .bin file extension.
C File Operations
C file operations refer to the different possible operations that we can perform on a file in C such as:

1. Creating a new file – fopen() with attributes as “a” or “a+” or “w” or “w+”
2. Opening an existing file – fopen()
3. Reading from file – fscanf() or fgets()
4. Writing to a file – fprintf() or fputs()
5. Moving to a specific location in a file – fseek(), rewind()
6. Closing a file – fclose()
The highlighted text mentions the C function used to perform the file operations.

Functions for C File Operations

162
File Pointer in C
A file pointer is a reference to a particular position in the opened file. It is used in file handling to
perform all file operations such as read, write, close, etc. We use the FILE macro to
declare the file pointer variable. The FILE macro is defined inside <stdio.h> header file.

Syntax of File Pointer

FILE* pointer_name;
File Pointer is used in almost all the file operations in C.

Open a File in C
For opening a file in C, the fopen() function is used with the filename or file path along with the
required access modes.

Syntax of fopen()

163
FILE* fopen(const char *file_name, const char *access_mode);

Parameters

 file_name: name of the file when present in the same directory as the source file.
Otherwise, full path.
 access_mode: Specifies for what operation the file is being opened.

Return Value

 If the file is opened successfully, returns a file pointer to it.


 If the file is not opened, then returns NULL.

File opening modes in C

File opening modes or access modes specify the allowed operations on the file to be opened. They
are passed as an argument to the fopen() function. Some of the commonly used file access modes are
listed below:

Opening
Modes Description

Searches file. If the file is opened successfully fopen( ) loads it into memory
r and sets up a pointer that points to the first character in it. If the file cannot be
opened fopen( ) returns NULL.

Open for reading in binary mode. If the file does not exist, fopen( ) returns
rb
NULL.

Open for reading in text mode. If the file exists, its contents are overwritten. If
w the file doesn’t exist, a new file is created. Returns NULL, if unable to open the
file.

Open for writing in binary mode. If the file exists, its contents are overwritten.
wb
If the file does not exist, it will be created.

a Searches file. If the file is opened successfully fopen( ) loads it into memory

164
Opening
Modes Description

and sets up a pointer that points to the last character in it. If the file doesn’t
exist, a new file is created. Returns NULL, if unable to open the file.

Open for append in binary mode. Data is added to the end of the file. If the file
ab
does not exist, it will be created.

Searches file. It is opened successfully fopen( ) loads it into memory and sets up
r+ a pointer that points to the first character in it. Returns NULL, if unable to open
the file.

Open for both reading and writing in binary mode. If the file does not exist,
rb+
fopen( ) returns NULL.

Searches file. If the file exists, its contents are overwritten. If the file doesn’t
w+
exist a new file is created. Returns NULL, if unable to open the file.

Open for both reading and writing in binary mode. If the file exists, its contents
wb+
are overwritten. If the file does not exist, it will be created.

Searches file. If the file is opened successfully fopen( ) loads it into memory and
a+ sets up a pointer that points to the last character in it. If the file doesn’t exist, a
new file is created. Returns NULL, if unable to open the file.

Open for both reading and appending in binary mode. If the file does not exist,
ab+
it will be created.

As given above, if you want to perform operations on a binary file, then you have to append ‘b’ at the
last. For example, instead of “w”, you have to use “wb”, instead of “a+” you have to use “a+b”.

165
Example of Opening a File

// C Program to illustrate file opening


#include
<stdio.h>
#include
<stdlib.h> int
main()
{
// file pointer variable to store the value returned by
// fopen
FILE* fptr;
// opening the file in read mode
fptr = fopen("[Link]", "r");

// checking if the file is opened successfully


if (fptr == NULL) {
printf("The file is not opened. The program will " "now
exit.");
exit(0);
}
return 0;
}

Output
The file is not opened. The program will now exit.

The file is not opened because it does not exist in the source directory. But the fopen() function is
also capable of creating a file if it does not exist. It is shown below

Create a File in C
The fopen() function can not only open a file but also can create a file if it does not exist already.
For that, we have to use the modes that allow the creation of a file if not found such as w,
w+, wb, wb+, a, a+, ab, and ab+.

FILE *fptr;

fptr = fopen("[Link]", "w");

166
Example of Opening a File

// C Program to create a
file#include <stdio.h>
#include <stdlib.h>

int main()

{
// file
pointerFILE*
fptr;

// creating file using fopen() access mode


"w"fptr = fopen("[Link]", "w");

// checking if the file is created


if (fptr == NULL) {

printf("The file is not opened. The program will " "exit


now");

exit(0);
}
else {

The file is created successfully

Output
The file is created Successfully.

Reading From a File


The file read operation in C can be performed using functions fscanf() or fgets(). Both the functions
performed the same operations as that of scanf and gets but with an additional parameter, the file
pointer. There are also other functions we can use to read from a file. Such functions are listed below:

167
Function Description

Function Description

fscanf() Use formatted string and variable arguments list to take input from a file.

fgets() Input the whole line from the file.

fgetc() Reads a single character from the file.

fgetw() Reads a number from a file.

fread() Reads the specified bytes of data from a binary file.

So, it depends on you if you want to read the file line by line or character by character.

Example:

FILE * fptr;

fptr = fopen(“[Link]”, “r”);

fscanf(fptr, "%s %s %s %d", str1, str2, str3, &year); char

c = fgetc(fptr);

The getc() and some other file reading functions return EOF (End Of File) when they reach the end of
the file while reading. EOF indicates the end of the file and its value is implementation- defined.

Note: One thing to note here is that after reading a particular part of the file, the file pointer will be
automatically moved to the end of the last read character.

Write to a File
The file write operations can be performed by the functions fprintf() and fputs() with similarities to
read operations. C programming also provides some other functions that can be used to write data to
a file such as:

168
Function Description

Function Description

Similar to printf(), this function use formatted string and varible arguments list
fprintf()
to print output to the file.

fputs() Prints the whole line in the file and a newline at the end.

fputc() Prints a single character into the file.

fputw() Prints a number to the file.

fwrite() This functions write the specified amount of bytes to the binary file.

Example:

FILE *fptr ;

fptr = fopen(“[Link]”, “w”);

fprintf(fptr, "%s %s %s %d", "We", "are", "in", 2012); fputc("a",

fptr);

Closing a File
The fclose() function is used to close the file. After successful file operations, you must always
close a file to remove it from the memory.

Syntax of fclose()

fclose(file_pointer);
fptr= fopen(“[Link]”, “w”);

---------- Some file Operations -------

fclose(fptr);

169
9.8 SUMMARY
In this unit we have studied in detail input and output functions. We also dealt with printf() and scanf()
function. We have discussed getchar() and putchar() functions and also gets() and puts() function. At the
end of this unit we have explained in detail about file handling in C.

9.9 KEYWORDS

 Input,
 Output,
 printf(),
 scanf(),
 getchar() and putchar().

9.10 QUESTIONS FOR SELF STUDY

1. Describe input and output functions.


2. With example explain printf() function.
3. Explain scanf() function along with program.
4. Elucidate features of file handling in C.
5. Differentiate getchar() and putchar() function.

9.11 REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg


 "Programming with C" by E. Balagurusamy
 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Mill

170
UNIT 10: TYPEDEF AND ENUMERATION IN C

Structure:

10.0 Objectives
10.1 Introduction
10.2 Typedef in C

10.3 Enumeration in C
10.4 Summary
10.5 Keywords
10.6 Questions
10.7 References

10.0 OBJECTIVES
After studying this unit, we will be able to explain the following:

 Typedef in C.
 Enumeration in C.

10.1 INTRODUCTION

To make the coding of a program more intelligible, it is sometimes useful to replace integer values
such as 1, 2, 3 etc. with meaningful names. An enumeration is created withthe enum keyword, and
is an ordered collection of names that represent integer [Link] otherwise specified, the first
name in the collection represents 0, the second name represents 1, and so on. In the
statement below, for example, the names false and true become synonymous with the
integer values 0 and 1.

enum {false, true};

It is perfectly possible to define an enumerated data type using the typedef keyword. This keyword
allows you to give a new name to an existing data type - you can think of it as an alias
- with the aim of making the source code easier to follow. This might be useful, for example, if you
wanted to create a Boolean data type for your program. A variable of type Boolean can take one of
two values - false or true (represented by the values 0 and 1 respectively). While many programming
languages have a specific Boolean data type, C does not. We could therefore create a Boolean data
type with the following statement:

171
typedef enum {false, true} boolean;

We can now create a variable of this type (boolean) using a statement such as the following:

boolean error = false;

Supposing you want to be able to handle a situation in which the user enters a value that does not
match one of the expected responses. Your program should be able to "trap" such an error, and report
its occurrence to the user. The short program below expects the user to enter a temperature value, and
then respond to a question about whether or not it is raining by pressing either "Y" or "N" (for "yes"
or "no"). If the user responds to this question with

anything other than "Y" or "N", the variable input_error (of type boolean) is set to true (1), indicating
that an input error has occurred. The variable is initialised to false (0), so if a valid response is given,

the error message will not be displayed.

10.2 TYPEDEF IN C

The typedef is a keyword used in C programming to provide some meaningful names to the already
existing variable in the C program. It behaves similarly as we define the alias for the commands. In
short, we can say that this keyword is used to redefine the name of an already existing variable.

Syntax of typedef

1. typedef <existing_name> <alias_name>

In the above syntax, 'existing_name' is the name of an already existing variable while 'alias name' is
another name given to the existing variable.

For example, suppose we want to create a variable of type unsigned int, then it becomes a tedious
task if we want to declare multiple variables of this type. To overcome the problem, we use a typedef
keyword.

typedef unsigned int unit;

In the above statements, we have declared the unit variable of type unsigned int by using a typedef
keyword.

Now, we can create the variables of type unsigned int by writing the following statement: unit a, b;

172
instead of writing: unsigned int a, b;

Till now, we have observed that the typedef keyword provides a nice shortcut by providing an
alternative name for an already existing variable. This keyword is useful when we are dealing with the
long data type especially, structure declarations.

Let's understand through a simple example.

#include <stdio.h>
int main()
{
typedef unsigned int unit;
unit i,j;

i=10;
j=20;
printf("Value of i is :%d",i);
printf("\nValue of j is :%d",j);
return 0;
}

Output

Value of i is :10 Value

of j is :20

Using typedef with structures

Consider the below structure declaration:

struct student
{
char name[20];
int age;
};
struct student s1;

In the above structure declaration, we have created the variable of student type by writing the
following statement:

173
1. struct student s1;

The above statement shows the creation of a variable, i.e., s1, but the statement is quite big. To avoid
such a big statement, we use the typedef keyword to create the variable of type student.

struct student
{
char name[20];
int age;
};
typedef struct student
stud;stud s1, s2;

In the above statement, we have declared the variable stud of type struct student. Now, we can use the
stud variable in a program to create the variables of type struct student.

The above typedef can be written as:

typedef struct student


{
char name[20];
int age;
} stud; stud
s1,s2;

From the above declarations, we conclude that typedef keyword reduces the length of the code and
complexity of data types. It also helps in understanding the program.

Let's see another example where we typedef the structure declaration.

#include <stdio.h>
typedef struct student
{
char name[20];
int age;
}stud;

174
int main()
{
stud s1;
printf("Enter the details of student s1: ");
printf("\nEnter the name of the student:");
scanf("%s",&[Link]);
printf("\nEnter the age of student:");
scanf("%d",&[Link]);
printf("\n Name of the student is : %s", [Link]);
printf("\n Age of the student is : %d", [Link]); return
0;
}

Output

Enter the details of student s1:

Enter the name of the student: Peter Enter

the age of student: 28

Name of the student is : Peter Age

of the student is : 28

Using typedef with pointers

We can also provide another name or alias name to the pointer variables with the help of the typedef.

For example, we normally declare a pointer, as shown below:

int* ptr;

We can rename the above pointer variable as given below:

typedef int* ptr;

In the above statement, we have declared the variable of type int*. Now, we can create the

175
variable of type int* by simply using the 'ptr' variable as shown in the below statement: ptr p1, p2

In the above statement, p1 and p2 are the variables of type 'ptr'.

10.3 ENUMERATION IN C

 Enum is user defined data type like structure,union.


 Enum is used to define a set of constants of type int.
 To declare enum , we use keyword enum.

Syntax :

Enum tag { enumeration list};

e.g.
enum day { MON, TUE, WED, THU, FRI, SAT, SUN };

Here name of enumeration is day.

And, MON, TUE, WED, ......... are the values of type day.

By default, MON is 0, TUE is 1 and so on. This is done by compiler and it starts from 0, You can
change default values of enum elements during declaration (if necessary).

Example :

#include<stdio.h> int main()


{
int i;
enum day {MON,TUE,WED,THU,FRI,SAT,SUN}; for(i=MON;i<=SUN;i++) {
printf("%d ",i);
}
return 0;
}

Output:
012345

176
Points to remember :

Two enum names can have same value. For example,

#include<stdio.h>
enum exam {Pass = 1, Failed = 0, Awaited = 0};

int main()
{
printf("%d, %d, %d", Pass, Failed, Awaited); return 0;
}

Output

1,0,0

If we do not explicitly assign values to enum names, the compiler by default assigns values starting
from 0. For example, in the following C program, MON gets value 0, TUEgets 1, and so on.

#include<stdio.h> int main()


{
int i;
enum day {MON,TUE,WED,THU,FRI,SAT,SUN}; for(i=MON;i<=SUN;i++) {
printf("%d ",i);
}
return 0;
}

Output:
0123456

Output

177
We can assign values to some name in any order. All unassigned names get value as value
of previous name plus one.

#include<stdio.h> int main()


{
enum day {MON = 1,TUE,WED,THU = 7,FRI,SAT,SUN};
printf("%d %d %d %d %d %d %d ",MON,TUE,WED,THU,FRI,SAT,SUN);
return 0;
}

Output

123789

All enum constants must be unique in their scope. For example, the following program fails in
compilation.
#include<stdio.h> enum e1 {a,
b};
enum e2 {a, b}; int main ( )
{
return 0;
}

Output

Compilation Error

Enumeration or Enum in C is a special kind of data type defined by the user. It consists of constant
integrals or integers that are given names by a user. The use of enum in C to name the integer values
makes the entire program easy to learn, understand, and maintain by the same or even different
programmer.

178
Syntax to Define Enum in C

An enum is defined by using the ‘enum’ keyword in C, and the use of a comma separates the
constants within. The basic syntax of defining an enum is:

enum enum_name{int_const1, int_const2, int_const3, …. int_constN};


In the above syntax, the default value of int_const1 is 0, int_const2 is 1, int_const3 is 2, and so on.
However, you can also change these default values while declaring the enum. Below isan example of
an enum named cars and how you can change the default values.
enum cars{BMW, Ferrari, Jeep, Mercedes-Benz}; Here,
the default values for the constants are:
BMW=0, Ferrari=1, Jeep=2, and Mercedes-Benz=3. However, to change the default values, you can
define the enum as follows:
enum cars{
BMW=3,
Ferrari=5,
Jeep=0,
Mercedes-Benz=1
};

Enumerated Type Declaration to Create a Variable


Similar to pre-defined data types like int and char, you can also declare a variable for enum and other
user-defined data types. Here’s how to create a variable for enum.
enum condition (true, false); //declaring the enum
enum condition e; //creating a variable of type condition
Suppose we have declared an enum type named condition; we can create a variable for that data type
as mentioned above. We can also converge both the statements and write them as: enum condition
(true, false) e;
For the above statement, the default value for true will be 1, and that for false will be 0.

How to Create and Implement Enum in C Program


Now that we know how to define an enum and create variables for it, let’s look at some
examples to understand how to implement enum in C programs.
Also Read: Most Important Features of C Language You Must be Aware Of

179
Example 1: Printing the Values of Weekdays
#include <stdio.h>
enum days{Sunday=1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}; int
main(){
// printing the values of weekdays for(int
i=Sunday;i<=Saturday;i++){
printf("%d, ",i);
}
return 0;
}
Output:

1,2,3,4,5,6,7,
In the above code, we declared an enum named days consisting of the name of the weekdays starting
from Sunday. We then initialized the value of Sunday to be 1. This will assign the value for the other
days as the previous value plus 1. To iterate through the enum and print the values of each day, we have
created a for loop and initialized the value for i as Sunday.

Example 2: Assigning and Fetching Custom Values of Enum Elements


#include<stdio.h>
enum containers{ cont1
= 5,
cont2 = 7,
cont3 = 3,
cont4 = 8
};
int main(){
// Initializing a variable to hold enums
enum containers cur_cont = cont2;
printf("Value of cont2 is = %d \n", cur_cont); cur_cont =
cont3;
printf("Value of cont3 is = %d \n", cur_cont);

180
cur_cont = cont1;
printf("Value of hearts is = %d \n", cur_cont);
return 0;
}
Output:
Value of cont2 is=7
Value of cont3 is =3
Value of hearts is =5

We have declared an enum named containers with four different containers as the elements in the
above code. We have then given custom values to the elements and initialized the variable for the
enum multiple times to print the relevant output.

How To Use enum in C?


We use enums for constants, i.e., when we want a variable to have only a specific set of values. For
instance, for weekdays enum, there can be only seven values as there are only seven days in a week.
However, a variable can store only one value at a time. We can use enums in C for multiple purposes;
some of the uses of enums are:

 To store constant values (e.g., weekdays, months, directions, colors in a rainbow)


 For using flags in C
 While using switch-case statements in C

Example of Using Enum in Switch Case Statement


In this example, we will create an enum with all the 4 directions, North, East, West, andSouth as the
constants. We will then use the switch case statements to switch between the direction elements and
print the output based on the value of the variable for the enum directions. #include <stdio.h>
enum directions{North=1, East, West, South}; int
main(){
enum directions d;
d=West; switch(d){

181
case North:
printf("We are headed towards North.");
break;
case East:
printf("We are headed towards East."); break;
case West:
printf("We are headed towards West.");
break;
case South:
printf("We are headed towards South");
break;
}
return 0;
}
Output:
We are headed towards west

Example of Using Enum in C for Flags

We can use enum in C for flags by keeping the values of integral constants a power of 2. This will
allow us to choose and combine two or more flags without overlapping with the help of the Bitwise
OR (|) operator. Let’s consider the example below where we set three flags: Crop, Rotate, and Save to
work with an image.
Example: #include
<stdio.h>
enum designFlags{
CROP = 1,
ROTATE = 2,
SAVE = 4
};

182
int main() {
int myExample = ROTATE | SAVE;
printf("%d", myExample);
return 0;
}
Output:
6

If we do the calculations for the above code, it is:


00000010 (ROTATE = 2)
| 00000100 (SAVE = 4)

00000110 (Output = 6)

As you can see, our calculation and the output given by the program are the same. This
concludes that we can use enum in C for flags. Also, we can add our custom flags.

Interesting Points About Initialization of Enum in C

There are a few facts about the enum worth noting, such as:
1. Multiple enum names or elements can have the same value. Here’s an example of two
enum elements having a similar value.
Example:
#include <stdio.h>
enum Cars{Jeep = 1, BMW = 0, Mercedes_Benz = 0}; int
main(){
printf("%d, %d, %d", Jeep, BMW, Mercedes_Benz);
return 0;
}

Output:
1,0,0

183
2. If we do not assign custom values to enum elements, the compiler will assign them default
values starting from 0. For instance, the compiler will assign values to the months in the
example below, with January being 0.

Example:
#include <stdio.h>
enum Months{January, February, March, April, May, June, July, August, September, October,
November, December};
int main(){
enum Months m = May;
printf("The Value of May in Months is %d", m); return
0;
}
Output:
The value of May in Months is 4

3. We can provide values to any elements of enum in any order. All the unassigned elements
will get the value as previous + 1. The following program demonstrates the same.

Example:

#include <stdio.h>
enum weekdays {Sunday, Monday = 2, Tuesday, Wednesday = 6, Thursday, Friday = 9,
Saturday = 12};
int main()
{
printf("%d %d %d %d %d %d %d", Sunday, Monday, Tuesday, Wednesday,
Thursday, Friday, Saturday);
return 0;
}
Output:

0,2,3,6,7,9,1

184
4. All the values assigned to the elements of enum must be an integral constant. For instance,
they should be within the range of minimum and maximum possible integers.
5. All the enum elements or constants should have a unique scope. It means that an element
cannot be a part of two different enums in the same program as it will fail during compilation.
Here’s an example:
Example:
#include <stdio.h>
enum Cars{Mahindra, Jeep, BMW};
enum Luxury_Cars{BMW, Ferrari, Mercedes_Benz}; int
main(){
return 0;
}
Output:

Enum in C vs. Macro


Similar to enum, you can also use the macro in C to define named constants. However, the use of enum
in C is preferred as it has many advantages over the macro. Two of the key benefits are:
 Enums follows the ‘scope’ rules as discussed earlier (in the last point of the previous
section).
 The compiler can automatically assign values to enum elements. Hence, the declaration
becomes easier.

10.5 SUMMARY

In this unit we have studied in detail about typedef function in C and also explained typedef using with
pointers and structure. At the end of this unit we also explained enum or enumeration in detail.

185
10.6 KEYWORDS

 Typedef

 Enum,

 Macro and Struct.

10.7 QUESTIONS FOR SELF STUDY

1. Write syntax of typedef and also discuss.


2. Explain using typedef with structure.
3. Write a short note on using typedef with pointers.
4. Briefly explain enumeration in C.
5. How to create and implement enum in C proram.

10.8 REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg


 "Programming with C" by E. Balagurusamy
 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

186
UNIT 11: BITWISE OPERATORS

Structure:

11.0 Objectives
11.1 Introduction
11.2 Bitwise operation
11.3 Bitwise operators
11.4 Summary

11.5 Keywords
11.6 Questions for self-study

11.7 References

11.0 OBJECTIVES

After studying this unit, we will be able to explain the following:

 Bitwise operation.
 Bitwise operators.

11.1 INTRODUCTION

The Bitwise Operator in C is a type of operator that operates on bit arrays, bit strings, and
tweaking binary values with individual bits at the bit level. For handling electronics and IoT-related
operations, programmers use bitwise operators. It can operate faster at a bit level.

The Bitwise Operator in C performs its operation on the individual bits of its operand, where
operands are values or expressions on which an operator operates. These operators are also used to
perform the core actions as well as high-level arithmetic operations that require direct support of the
processor. We can further subcategorize bitwise operators into three subtypes based on their working
principles, logical (Bitwise AND, OR, and XOR), Shift (Right Shift and left shift), and Complement
(Bitwise NOT).

There are six different Bitwise Operators in C. These are:

· Bitwise AND operator (&)


187
· Bitwise OR operator (|)
· Bitwise exclusive OR operator (^)
· Binary One’s Complement or Bitwise NOT operator (~)
· Bitwise Left shift operator (<<)
· Bitwise Right shift operator (>>)

Using bitwise operators, programmers can change the individual bits of any value contained in the
operand. We can view a single byte of computer memory as 8 -bits that signifies the true or false status
of 8 flags. Bitwise operators are usually applied to define flag values in operating systems and driver
software. For instance, in a file property, the read-only mode is conceptually expressed as a flag bit in
the operating system, and the bitwise operator is used to toggle between the true and the false value.

There are six different types of Bitwise Operators in C. These are:

The Bitwise AND (&) in C: The C compiler recognizes the Bitwise AND with & operator. It takes
two operands and performs the AND operation for every bit of the two operand numbers. It is a binary
operator. The output of this operator will result in 1 only if both bits are 1.

The Bitwise OR (|) in C: The C compiler recognizes the Bitwise OR with | operator. It takes two
operands and performs the OR operation for every bit of the two operand numbers. It is also a binary
operator. The output of this operator will result in 1 if any oneof the two bits is 1.

The Bitwise XOR (^) in C: The C compiler recognizes the Bitwise XOR with ^ operator. It takes
two operands and performs the XOR operation for every bit of the two operand numbers. It is also a
binary operator. The output of this operator will result in 1 if both the bits have different values.

Binary One’s Complement or Bitwise NOT operator (~) in C: The C compiler recognizes the
Bitwise NOT with ~ operator. It takes only one operand and performs the inversion of all digits of it.
It is a unary operator. The output of this operator will invert all the existing bits of that operand.

Bitwise Left shift operator (<<) in C: The C compiler recognizes the left shift operation with this
<<. It takes only two operands and shifts all the bits of the first operand to the left. The second
operand decides how many numbers of places this operator will shift its bits. It is a binary operator.

Bitwise Right shift operator (>>) in C: The C compiler recognizes the left shift operation
with this >>. It takes only two operands and shifts all the bits of the first operand to the

188
right. The second operand decides how many numbers of places this operator will shift its bits. It is a
binary operator.

11.2 BITWISE OPERATIONS

Bitwise is a level of operation that involves working with individual bits which are the smallest units of
data in a computing system. Each bit has single binary value of 0 or 1. Most programming languages
manipulate groups of 8, 16 or 32 bits. These bit multiples are known as bytes. The arithmetic logic
unit (ALU) is a part of a computer's CPU. Inside the ALU, mathematical operations like addition,
subtraction, multiplication and division are all done at bit level. For those operations, bitwise
operators are used.

Bitwise operations
A bitwise operation operates on two-bit patterns of equal lengths by positionally matching their
individual bits. For example, a logical AND (&) of each bit pair results in a 1 if both the first AND
second bits are 1. If only one bit is a 1, the result is 0. AND can also be used to test individual bits in a
bit string to see if they are 0 or 1.
A logical OR (|) operation functions differently from the AND operations. For each bit pair, the result
is 1 if the first OR second bit is 1. If neither bit is 1, the result is 0.
A logical XOR (~) of each bit pair results in a 1 if the two bits are different, and 0 if they are the same
(both zeros or both ones).
Logical NOT is represented as ^.
Left shift (<<), right shift (>>) and zero-fill right shift (>>>) bitwise operators are also known as bit
shift operators.

Arithmetic logic unit, part of a computer CPU, is where bitwise operators used to perform
mathematical operations.

189
11.3 BITWISE OPERATORS

Bitwise operators are characters that represent actions (bitwise operations) to be performed on single
bits. They operate at the binary level and perform operations on bit patterns that involve the
manipulation of individual bits. Thus, unlike common logical operators like + or - which work with
bytes or groups of bytes, bitwise operators can check each individual bit within a byte. The most
common bitwise operators used in C/C++ are given in the table below.

Operator Name Description Application

& Bitwise AND Copies a bit to the result if it To set up a mask to check
exists in both operands. The the values of specific bits
result is 1 only if both bits are
1.

| Bitwise OR Copies a bit to the result if it To add two numbers if there


exists in either operand. The is no carry involved
result is 1 if either bit is 1.

^ Bitwise Copies a bit to the result if it To toggle bits or swap two


Exclusive exists in either operand. So, if variables without using a
O one of the operands is TRUE, third temporary variable
R (XOR) the result is TRUE. If neither To find specific types of
operand is TRUE, the result numbers (e.g., odd) in a
is FALSE. series of numbers (e.g., all
even)
To find nonrepeating
elements
To detect if two integers
have opposite signs

~ Bitwise NOT Also known as bitwise To flip or invert bits


complement and bitwise
inversion, it flips zeros into
ones and ones into zeros.

<< Shift left The left operand value is To align bits


shifted left by the number of
bits specified by the right
operand.

>> Shift right The left operand value is To align bits


shifted right by the number of
bits specified by the right
operand.

190
Multiple bitwise operators are used in bit manipulation. These operations happen very fast and
optimize system performance and time complexity. It’s important to keep in mind that the left shift
and right shift operators should not be used for negative numbers. Doing this can result in undefined
behaviors in the programming language. Also, bitwise operators should not be used in place of logical
operators because they work differently. Logical operators consider non-zero operands as 1 and their
result is either 0 or 1. In contrast, bitwise operators return an integer value. The table below defines
the JavaScript bitwise operators.

Operator Name Type Action

& Bitwise AND Binary If bits of both operands are


ones, returns a one in each
bit position

| Bitwise OR Binary If bits of either operand are


ones, returns a one in a bit
position

^ Bitwise XOR Binary If a single operand is a


one, returns a one in a bit
position

~ Bitwise NOT Unary Flips the bits in the operand

191
Operator Name Type Action

<< Left shift Binary Shifts first operand a


numberof bits to the left as
specified inthe second
operand, shifting in zeros
from the right

>> Right shift Binary Shifts first operand a


numberof bits to the right as
specified in the second
operand, and discards
displaced bits

>>> Zero-fill right shift Binary Shifts first operand a


numberof bits to the right as
specified in the second
operand, discards displaced
bits, and shifts in zeros from
the left
Applications of bitwise operations and operators
There are many applications of bitwise operations and operators. For one, they are used in data
compression where data is converted from one representation to another to reduce the amount of
storage space required. Bitwise operations are also used in encryption algorithms to encrypt data and
protect it from unauthorized use, manipulation or [Link] following are some other common
applications:

 low-level programming for device drivers, memory allocators and compression software;
 maintaining large integer sets for search and optimization;
 ability to store multiple Boolean flags on limited memory devices;
 embedded software in chips and microcontrollers;
 communications where individual header bits carry sensitive or important information;
and

192
 converting text cases, such as uppercase to lowercase or lowercase to uppercase.

193
Bitwise AND
The bitwise AND operator produces an output of 1 if the corresponding bits of both the
operands are 1. If not, the output is 0.
Example 1: Bitwise AND operation of two one-bit operands.

Left operand Right Result


operand

0 0 0

0 1 0

1 0 0

1 1 1

Example 2: Bitwise AND operation of two integers: 28 and 17; the & operator compares
each binary digit of these integers.

Binary digits

28 0 0 0 1 1 1 0 0

17 0 0 0 1 0 0 0 1

Are both digits 1? No No No Yes No No No No

Bitwise AND 0 0 0 1 0 0 0 0
output

Thus: 28 & 17 (bitwise AND) = 00010000 (binary) = 16 (decimal).

Bitwise OR

The bitwise OR operator produces an output of 1 if either one of the corresponding bits is 1.
Otherwise, the output is zero.

194
Example 1: The bitwise OR operation of two one-bit operands.

Left operand Right operand Result

0 0 0

0 1 1

1 0 1

1 1 1

Example 2: Let's consider the previous example of two integers: 28 and 17.

Binary digits

28 0 0 0 1 1 1 0 0

17 0 0 0 1 0 0 0 1

Is either digit 1? No No No Yes Yes Yes No Yes

Bitwise OR output 0 0 0 1 1 1 0 1

Thus: 28 | 17 (bitwise OR) = 00011101 (binary) = 29 (decimal).

Bitwise exclusive OR (XOR)

The bitwise exclusive OR (XOR) operator returns 1 if the bits of both operands are opposite.
Otherwise, it returns 0.

195
Example 1: The bitwise XOR operation of two one-bit operands.

Left operand Right operand Result

0 0 0

0 1 1

1 0 1

1 1 0

Example 2: Let's see how bitwise XOR works for our two integers 28 and 17.

Binary digits

28 0 0 0 1 1 1 0 0

17 0 0 0 1 0 0 0 1

Are the two digits opposite No No No No Yes Yes No Yes


of each other?

Bitwise XOR output 0 0 0 0 1 1 0 1

Thus: 28 ^ 17 (bitwise XOR) = 00001101 (binary) = 13 (decimal).

Bitwise NOT

The bitwise NOT operator reverses the bits. Unlike other bitwise operators, it accepts only one
operand.

Example: Let's consider the bitwise NOT operation of the integer 28.

196
Binary digits

28 0 0 0 1 1 1 0 0

Bitwise NOT output 1 1 1 0 0 0 1 1

Thus: ~28 (bitwise NOT) = 11100011 (binary) = 227 (decimal).

Bitwise left shift

The bitwise left shift operator shifts the bits left by the bits specified by the right operand. The
positions vacated by the left shift operator are filled with 0.

Example: Let's perform the bitwise left shift operation on the integer 6. Each bit will be shifted
left by 1.

6 = 0110

6<<1 = 1100 (binary) = 12 (decimal)

Bitwise right shift

Like the left shift operator, the bitwise right shift operator shifts the bits right by the bits specified by
the right operand. The positions vacated by the right shift operator are filled with 0.

Example: Let's perform the right shift by two bits operations on the integer 8. Each bit will be
shifted right by 2.

8 = 1000

8>>2 = 0010 (binary) = 2 (decimal)

197
11.4 SUMMARY

In this unit we have discussed about bitwise operations. We also discussed about bitwise operators
such as bitwise AND, bitwise OR, bitwise XOR, bitwise NOT, bitwise left shift and bitwise right shift.

11.5 KEYWORDS

 Bitwise operator,
 bitwise XOR,
 bitwise AND,
 bitwise OR,

11.6 QUESTIONS FOR SELF STUDY

1. Explain bitwise operations.


2. Briefly discuss bitwise operators.
3. Write the applications of bitwise operators.
4. Explain bitwise AND and bitwise OR.
5. Differentiate bitwise left shift and bitwise right shift.

11.7 REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg

 "Programming with C" by E. Balagurusamy


 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

198
UNIT 12: DYNAMIC MEMORY ALLOCATION

Structure:

12.0 Objectives
12.1 Introduction
12.2 Dynamic memory allocation
12.3 Malloc() method
12.3 Calloc() method
12.4 Free() method
12.5 Realloc() method
12.6 Summary
12.7 Keywords
12.8 Questions

12.9 References

12.0 OBJECTIVES

After studying this unit, we will be able to explain the following:

 Analyze the Representation of a polynomial using linked lists.


 Understand Addition of two polynomials using
linked lists.

12.1 INTRODUCTION

Dynamic Memory Allocation is unique feature of C Programming Language. This allows us to create
data types and structures of any size and length which suits our program. There are two common
application of dynamic memory allocation, these are while using dynamic

199
arrays and dynamic data structure e.g. linked lists in C Programs. Let’s see use case. There comes
a situation in programming, when we don’t know exact size of array until compiler compiles the code
and generate executable. The size of array we have declared maybe not enough or more than required.
In this case use of dynamic memory allocation is best solution. Now the question is how to allocate
dynamic memory? The answer is C Language supports 4 library functions which are knows as
memory management functions (malloc, calloc, realloc, f r e e ). These
functions are defined in #include<stdlib.h> header file. We will see each function
in detail. Let’s first understand organization of application memory. The heap is a part of application
memory which will be used while allocating and de-allocating memory using memory management
functions. The Heap is also known as Free Memory. The figure below will illustrate.

F i g : 1 2 . 1 Application Memory Organization


The Heap memory is used for dynamic memory allocation during execution of the
program. The size of heap memory keeps changing. As mentioned earlier heap is free poolof
memory. This is enough as an introduction. The list of dynamic memory management
functions.

Now, Let us see the definition, syntax and some examples of each library functions below.

200
12.2 DYNAMIC MEMORY ALLOCATION
When we declare a variable or an array of any data type the space occupied by them in the
system's memory remains constant throughout the execution of the program. Sometimes the
constant space allocated at the compile-time may fall short, and to increase the space during
run-time we came through the concept of Dynamic Memory Allocation in C. Allocation and
Deallocation of memory at run-time in C are done using the concept of Dynamic Memory
Allocation. It is a method in which we use different library functionslike
malloc(), calloc(), realloc(), and free() to allocate and deallocate a memory block during run-
[Link] is considered as a very important topic because almost every Data Structure (such
asLinked Lists, Stack, Queue, Trees, etc.) is associated with the concept of Dynamic Memory
Allocation in [Link] understand Dynamic Memory Allocation in C, we first have to learn about
the types of memory that are used during the execution of a C Program
. There are two types of memory in our machine, one is Static Memory and another oneis
Dynamic Memory; both the memory are managed by our Operating System. Our operating
system helps us in the allocation and deallocation of memory blocks either during compile-
time or during the run-time of our program. When the memory is
allocated during compile-time it is stored in the Static Memory and it is known as Static
Memory Allocation, and when the memory is allocated during run-time it is stored in the
Dynamic Memory and it is known as Dynamic Memory [Link], let us see some
differences in Static Memory Allocation and Dynamic Memory Allocation.

Static Memory Allocation Dynamic Memory Allocation


Constant (Invariable) memory is reserved at
Dynamic (Variable) memory is reserved at run- time of
compile-time of our program that can't be modified.
our program that can be modified.

It is used at compile-time of our program and is also It is used at run-time of our program and is also
known as compile-time memory allocation. known as run-time memory allocation.

We can't allocate or deallocate a memory block during We can allocate and deallocate a memory block during
run-time. run-time.
Heap space is used in Dynamic
Stack space is used in Static Memory Allocation.
Memory Allocation.

It doesn't provide reusability of memory, while the It provides reusability of memory, while the program i
program is running. So, it is less efficient.

201
 How Does Memory Management in C works?

When we execute a C Program, it requires to reserve some memory in the machine to store its
variables, functions, instructions and the program file itself. However, we also have a memory segment
that we can use dynamically as much memory as the system have and that too during the run-time of a
program. So, now let us see the components/segments of memory that are used during the execution
of a C [Link] are further four components in which our system's memory is divided:

1. Stack Segment (Static Memory)


2. Global Variables Segment (Static Memory)
3. Instructions / Text Segment (Static Memory)
4. Heap Segment (Dynamic Memory)

The amount of memory allocated for Stack, Global Variables, and Instructions / Text during compile-
time is invariable and cannot be reused until the program execution finishes. However, the Heap
segment of the memory can be used at run-time and can be expanded until the system's memory
exhausts.

Let's look at the some important points related to all the memory segments :

Instructions / Text

Text outside the main() function is stored in the Static Memory.


These instructions are stored during compile-time of a program.

Global Variables

Global variable also known as static variables and can be declared by two methods,
o Using static keyword, ex. static int i = 0;
o Declaring variable outside main() or any other function.
These variables are stored in the Static Memory during the compile-time of our program.

Stack

Stack is a constant space (memory) allocated by our operating system to store local variables,
function calls and local statements that are present in the function definition. It is the major
part of the Static Memory in our system.
There are some drawbacks of stack space as follows:
o The memory allocated for stack can't grow during the run-time of an

202
application.
o We can't allocate or deallocate memory during execution.

Heap
Heap is the Dynamic Memory of our program, It can be also be imagined as a big free pool of
memory available to us. The space occupied by heap section is not fixed, it can vary during the
run-time of our program and there are functions to perform allocation and deallocation of
memory blocks during run-time.
Heap space can grow as long as we do not run out of the system's memory itself, however it is
not in the best interest of a programmer to exhaust the system's memory, so we need to be
really careful while using the heap space in our program.

Note : A machine's memory is one of the most useful resource available to us that can be used as both
Statically and Dynamically. So, we have to make sure to manage it well and not waste it during the
execution of our program.

Memory Allocation Process

Let us now see how our Operating System processes the allocation of memory through an example.
We will see how the memory is allocated at compile-time in this section using the example of
calculating Greatest Common Divisor (GCD) and Least Common Multiple (LCM).

C Program :

#include <stdio.h>
int sum; // global variable
// Declaring gcd and lcm functions, both takes two integer arguments,
// (memory will not be allocated upon declaring or defining our functions).
int greatestCommonDivisor(int, int); int
leastCommonMultiple(int, int);
// Defining greated common divisor function (also know as HCF).
int greatestCommonDivisor(int a, int b) { while (a
&& b) {
if (a > b) {
a %= b;
} else {

b %= a;
}

203
}
return a + b;
}
// Defining least common multiple function by using greatest common divisor.
int leastCommonMultiple(int a, int b) {
return (a / greatestCommonDivisor(a, b)) * b;
}
int main() {
int x, y;
printf("Enter two values to find their Greatest Common Divisor and Least Common
Multiple : ");
scanf("%d%d", &x, &y);
printf("Greatest Common Divisor : %d \nLeast Common Multiple : %d", greatestCommonDivisor(x, y),
leastCommonMultiple(x, y));
sum = greatestCommonDivisor(x, y) + leastCommonMultiple(x, y); printf("\nSum
of GCD and LCM : %d\n", sum);
return 0;
}

Output :

Enter two values to find their Greatest Common Divisor and Least Common Multiple : 12 15 Greatest
Common Divisor : 3
Least Common Multiple : 60
Sum of GCD and LCM : 63

Explanation of Memory Allocation Process :

The first rectangular box represents the memory reserved for text / instructions, second box as
memory reserved for global variables section, third box as the space reserved for stack and
fourth box represents the heap space.
When we run our program, first the main() function is called, then some amount of memory
from the stack frame is allocated for the execution of main() function and as sum is a
global variable, it has been given a space in the global segment.

204
Heap space remains empty throughout the execution of the program as there is no allocation
of memory during run-time.
The amount of memory allocated for a function in the stack can be called as a stack frame. All
of the local variables, arguments and the information in a function is stored within the stack
frame allocated to that function and as soon as a function returns something or reaches its last
statement, it is cleared from the stack memory.
When the main() finishes, program also finishes. In the end, space occupied by our global
variables also gets cleared.

Dynamic Memory Allocation in C is a process in which we allocate or deallocate a block of memory


during the run-time of a program. There are four functions malloc(), calloc(),
realloc() and free() present in <stdlib.h> header file that are used for Dynamic Memory Allocation in
our system. It can also be referred to as a procedure to useHeap Memory in which we can vary the size
of a variable or Data Structure (such as anArray) during the lifetime of a program using the
library functions. Dynamic Memory Allocation is considered as a very important concept in the field
of Data Structures and is used in almost every Data Structures like Linked Lists, Stacks, Dynamic
Arrays,

12.3 MALLOC() METHOD

malloc() is a method in C which is used to allocate a memory block in the heap section of the memory
of some specified size (in bytes) during the run-time of a C program. It is a library function present in
the <stdlib.h> header file.

Syntax of malloc()

General Syntax:

(cast-data-type *)malloc(size-in-bytes);

malloc() function takes size in bytes as an argument and returns a void pointer, so we have to type cast
the malloc() function to the required data type. malloc() does not initialises the allocated memory
block, so initially it contains a garbage value.

205
Defined in header <stdlib.h> as : void* malloc( size_t size );
o size : number of bytes to be allocated
Example Syntax:

int *ptr = (int *)malloc(sizeof(int));

In the above statement, we have assigned and allocated a block of size 4-bytes (64-bit compiler) with
cast data type as integer to an integer pointer ptr during the run-time of our program.

We can simply pass number of bytes instead of using sizeof() in argument, both are correct, but
sizeof() automatically takes care of the type of compiler and operating system that can cause changes
in sizes of different data types on different compilers and operating systems, so it is recommended to
use sizeof() function in Dynamic Memory Allocation in C.

Example of malloc()

Let's see an example to allocate a memory block of size 1-byte to a char pointer ptr during run- time
using malloc().

C Program :

// C Program to dynamically allocate an int ptr


#include <stdio.h>
#include <stdlib.h>

int main() {
// Dynamically allocated variable, sizeof(char) = 1 byte.
char *ptr = (char *)malloc(sizeof(char));

if (ptr == NULL) {
printf("Memory Error!\n");
} else {
*ptr = 'S';
printf("%c", *ptr);
}

return 0;
}

Output :

206
S

Explanation :

In the main() function, first we have declared and initialized a char pointer ptr with a dynamic
memory block allocated using malloc() function.
(char *)malloc(sizeof(char)) returns address of a char block of size 1-byte.
char ptr contains the address of the memory block returned by the malloc() function.
Now, if the system memory is exhausted it will print Memory Error! (ptr = NULL) in the
output console, else we have assigned character S in the memory block pointed by ptr and
printf("%c", *ptr); prints S in the output.
return 0; exits the program successfully.

12.4 CALLOC() METHOD

calloc() is a method in C which is also used to allocate memory blocks in the heap section, but it is
generally used to allocate a sequence of memory blocks (contiguous memory) like an array of
elements. It is also present in <stdlib.h> header file.

Syntax of calloc()

General Syntax:

(cast-data-type *)calloc(num, size-in-bytes);

calloc() function takes two arguments, first is the size of the array (number of elements) and second is
the sizeof() data type (in bytes) of which we have to make an array.

Defined in header <stdlib.h> as :

void* calloc( size_t num, size_t size );

num : number of elements


size : size of each element
Example Syntax: int *arr = (int *)calloc(5, sizeof(int));

207
In the above statement, we are allocating an integer array of size 5 at run-time and assigning it to an
integer pointer arr, arr will store the address of the very first element of the allocated array.

Example of calloc()

We will see an example to allocate an character array of size n using calloc() method.

C Program :

// C Program to dynamically allocate an array using calloc()


#include <stdio.h>
#include <stdlib.h>

int main() {
int n; scanf("%d",
&n);
// Dynamically allocated array of size 10 using calloc()
// array elements are initialized with 0
// arr stores the base address of the memory block
char *str = (char *)calloc(n, sizeof(char)); if
(str == NULL) {
printf("Memory Error!\n");
} else {
// initializing array with char variables
for (int i = 0; i < n; i++) {
char ch; scanf("%c",
&ch);
*(str + i) = ch;
}
// printing array using pointer
for (int i = 0; i < n; i++) {
printf("%c", *(str + i));
}
}

208
return 0;
}

Input:

14
Scaler Topics

Output:

Scaler Topics

Explanation :

In the main() function, first we have declared a integer variable n as it is the size of the
array or string that we are going to store in our dynamic memory.
We have declared and initialized a char pointer ptr with the dynamic array memory
allocated using calloc() function.
(char *)calloc(n, sizeof(char)) returns address of first element in the char array. str
contains the address of the first element of the array.
Now, if the system memory is exhausted it will print Memory Error! (str = NULL) in the
output console, else we have assigned a string Scaler Topics in our exampleoutput. printf("%c",
*str); statement inside the for loop will print each character of the Scaler
Topics string in the output.
return 0; exits the program successfully.

12.5 FREE() METHOD

free() as the name suggests is used to free or deallocate a memory block previously allocated using
malloc() and calloc() functions during run-time of our program.

Syntax of free()

General syntax:

209
free( pointer );

free() takes one argument and it is the pointer containing the address of the memory block that is to
be freed or deallocated.

Defined in header <stdlib.h> as :

void free( void* ptr );

Example :

free(arr);

In the above statement, we are deallocating memory block(s) pointed by a pointer arr in the memory.

Example 1 : malloc() and free()

Let's extend our malloc() example and add free() method in it.

C Program :

// C Program to dynamically allocate an int ptr


#include <stdio.h>
#include <stdlib.h>

int main() {
// dynamically allocated variable, sizeof(char) = 1 byte
char *ptr = (char *)malloc(sizeof(char));

if (ptr == NULL) {
printf("Memory Error!\n");
} else {

*ptr = 'S';
printf("%c", *ptr);
}

// deallocating memory pointed by ptr

210
free(ptr); printf("\n%c
", *ptr);
// assign NULL to avoid garbage values
ptr = NULL; return
0;
}

Output :
S
garbage value

(output garbage values are compiler dependent)

Explanation :

We have allocated a char block of size 1-byte using malloc() method and assigned it to a
character pointer ptr.
We are using the free() method to deallocate the memory block pointed by the pointer ptr in
the above example.
After deallocation of memory, ptr acts as a Dangling Pointer and is not pointing to any
location. It now contains some garbage value.
Assign NULL to the pointer ptr after using free() method to avoid garbage values in our
program.

Example 2 : calloc() and free()

In this example, let's also use our previous example of calloc() and add free() in it.

C Program :

#include <stdio.h>
#include <stdlib.h>

int main() {
int n; scanf("%d",
&n);

// dynamically allocated array of size 10 using calloc()

211
// array elements are initialized with 0
// arr stores the base address of the memory block
char *str = (char *)calloc(n, sizeof(char));

if (str == NULL) {
printf("Memory Error!\n");
} else {
// initializing array with Scaler Topics string
for (int i = 0; i < n; i++) {
char ch; scanf("%c",
&ch);
*(str + i) = ch;
}

// printing array using pointer


for (int i = 0; i < n; i++) {
printf("%c", *(str + i));
}
}

// deallocating memory pointed by str


free(str);

// printing array using pointer


for (int i = 0; i < n; i++) {
printf("%c", *(str + i));
}

// assigning NULL to avoid garbage values


str = NULL;

return 0;
}

Input:

14
Scaler Topics

Output:

Scaler Topics
garbage value

(output garbage values are compiler dependent)

212
Explanation :
We have allocated an array of size n using calloc() method and assigned it to a character
pointer str.
We are using the free() method to deallocates the whole array memory pointed by the pointer
str in the above example.
After deallocation of memory, str acts as a Dangling Pointer and is not pointing to any
location. It now contains some garbage value.
Assign NULL to the pointer str after using free() method to avoid garbage values in our
program.

How to deallocate memory using free()

When we allocate a memory block using malloc() or calloc(), the address of the memory block is
stored in a pointer that points to the allocated memory. We can easily deallocate
a memory block allocated by malloc() or calloc() method just by passing the pointer containing the
address of the block that is to be deallocated in to the free() method as an argument.
Free(ptr);

We have seen in the above examples of malloc() and calloc() to use free() function to deallocate
memory block(s). Let's see how free() works through a diagram. This is an example of deallocation of
integer memory block using free() function, previously allocated using malloc() [Link], let us
see how we can deallocate a memory block without using free() function.

How to deallocate memory without using free()

We can deallocate a memory block without using free() function, alternatively using the
realloc() function, which is used in reallocation of memory blocks.

realloc(ptr, 0); statement is the same as free(ptr);.

We will see more about this in the realloc() section and an example where we deallocate a memory
block using realloc().

213
12.6 REALLOC() METHOD

realloc() is also a method in C that is generally used to reallocate a memory block, here re- allocate
means to increase or decrease the size of a memory block previously allocatedusing malloc() or
calloc() methods. It can also be used to completely allocate or deallocate a memory block on its own,
we will see how to do it in the examples below.

Syntax of realloc()

General syntax : (cast-data-type *)realloc(ptr, new-size-in-bytes)

realloc() takes two arguments, one is the pointer pointing the the memory which is to be
realloacted and second is the new size in bytes.

Defined in header <stdlib.h> as : void *realloc( void *ptr, size_t new_size );


o ptr : pointer to the memory area to be reallocated
o new_size : new size of the array in bytes
Example : int *arr2 = (int *)realloc(arr, (n / 2) * sizeof(int));

In the above statement, we are reallocating arr pointer's memory to reduce it to half and
assigning it to arr2 pointer, other half of the array will now contain garbage values.

return value of realloc()

realloc() returns the address of the re-allocated memory block.

realloc() function need to be type casted because the address returned by the realloc() does
not represent any data type.
realloc() function may change the address of the previously allocated block, so it is
recommended to store the new address in pointer or use some new pointer to store the
reallocated address.

Examples of realloc()

Reallocating memory allocated by malloc() and calloc() using realloc()C

Program :

214
// C Program to reallocate memory blocks during run-time
#include <stdio.h>
#include <stdlib.h>

int main() {
int n; scanf("%d",
&n);

// dynamically allocated array of size n using malloc() and calloc()


// array is initialized with garbage values
int *arr1 = (int *)malloc(n * sizeof(int));
// array is initialized with 0
int *arr2 = (int *)calloc(n, sizeof(int));

if (arr1 == NULL || arr2 == NULL) { printf("Memory


Error!\n");
} else {
// filling the array arr1 with index values
for (int i = 0; i < n; i++) {
*(arr1 + i) = i;
}
// filling the array arr2 with reverse index values
for (int i = 0; i < n; i++) {
*(arr2 + i) = n - i;
}

// reallocating arr1 pointer dynamic memory to reduce to half,


// other half deallocted will now contain garbage values
int *arr3 = (int *)realloc(arr1, (n / 2) * sizeof(int));

// reallocating arr2 pointer dynamic memory to increase by double,


// increased double half will now contain garbage values
int *arr4 = (int *)realloc(arr2, (2 * n) * sizeof(int));

if (arr3 == NULL || arr4 == NULL) {


printf("Reallocation failed!\n");
} else {
// printing array arr1 using pointer
for (int i = 0; i < n; i++) {
printf("%d ", *(arr3 + i));

215
}

printf("\n");

// printing array arr2 using pointer


for (int i = 0; i < 2 * n; i++) {
printf("%d ", *(arr4 + i));
}
}
}

return 0;
}

Input

5
0 1 650005713 46458 12462928

Output :

0 1 688964574 53444 14232920


5 4 3 2 1 0 1224736841 53442 14231728 14227000

(output garbage values are compiler dependent)

Explanation :

First, We have allocated an integer array memory block of size n


using malloc() and calloc() assigned it to integer
pointers arr1 and arr2 respectively.
If the system's memory is exhausted, we print Memory Error and exit, else we are filling index
and reverse index values in arr1 and arr2 respectively.
Now, we are using realloc() function to reduce the size of first array arr1 to half and assigning
it to arr3 pointer, then increasing the size of second array arr2 to double and assigning it to
arr4 pointer.
If arr3 or arr4 is NULL then reallocation failed, else we are printing the array values in the
output window.
arr3 is reduced to half so the other half will contain garbage values, and same in arr4
the size of of array is doubled so the other half will contain garbage values.

Allocation and Deallocation of memory using realloc()

216
#include <stdio.h>
#include <stdlib.h>

int main() {
int *ptr = NULL;
ptr = (int *)realloc(ptr, sizeof(int));

if (ptr == NULL) {
printf("Memory Error!\n");
} else {

*ptr = 7;

printf("%d\n", *ptr);

// deallocating memory blocks pointed by


// ptr using realloc()
realloc(ptr, 0);

printf("%d\n", *ptr);

// assigning NULL to avoid dangling pointer


ptr = NULL;

printf("Memory freed using realloc()!");


}

return 0;
}

Output:

715078952
Memory
freed using
realloc()!

(output
garbage
values are
compiler
dependent)

217
Explanation :

In the main() function, first we have declared a Null Integer pointer.


We have allocated an integer block of memory using the realloc() function to the pointer ptr.
If ptr contains NULL it shows Memory Error in the output, else we have
stored 7 value in the memory block and printed 7 in the output.
Now, We have freed the memory block using realloc(ptr, 0) statement. ptr is a
Dangling Pointer now, it contains some garbage values.
Assign NULL to ptr to avoid garbage values.

malloc() vs calloc()

As we know, malloc() and calloc() both are library functions that are used to allocate memory block(s)
during the run-time of a program. But, there are some differences in malloc() and calloc()
methods and we are going see them below.
malloc() method calloc() method
It is generally used to allocate a single memory It is generally used to allocate contiguous
block of the given size (in bytes) during the run- (multiple) blocks of memory of given size (in
time of a program. bytes) during the run-time of a program.
It doesn't initializes the allocated memory block It initializes all the allocated memory blocks
and contains some garbage value. with 0 (zero) value.
calloc() takes two arguments i.e. the number of
malloc() takes a single arugment i.e. the size of
elements and the size of one element that are to be
memory block that is to be allocated.
allocated.
syntax: (cast-data-type *)calloc(num, size-in-
syntax: (cast-data-type *)malloc(size-in-bytes)
bytes)
Example : float *ptr = (float Example : float *ptr = (float *)calloc(10,
*)malloc(sizeof(float)); sizeof(float));

218
Note : malloc(n * sizeof(int)); and calloc(n, sizeof(int)); both allocates the same amount of memory,
but malloc() function does't initialize the elements in the memory(garbage values), while the calloc()
function initializes all the element in the memory to 0.

12.7 SUMMARY

In this unit we have studied dynamic memory allocation in detail. We also learnt malloc() method and
calloc() method. At the end of this unit explained free() method and realloc() method.

12.8 KEYWORDS

 Dynamic memory allocation,


 Static memory allocation,
 malloc(),
 calloc(),

12.9 QUESTIONS

1. Differentiate dynamic memory allocation and static memory allocation


2. How does memory management in C works?.
3. Explain malloc() method with program.
4. Discuss free() method.
5. Describe realloc() method().

12.10 REFERENCES

1. "Structured Programming Approach in C" by Forouzan and Gilberg

2. "Programming with C" by E. Balagurusamy


3. "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
4. "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

219
UNIT 13

LINKED LISTS

Structure:
13.0 Objectives
13.1 Introduction
13.2 Singly Linked list
13.3 Circular linked List
13.4 Doubly linked list
13.5 Summary
13.6 Keywords
13.7 Questions for self study
13.8 References

13.0 OBJECTIVES

After studying this unit, you will be able to


 Explain the different types of linked list
 Distinguish between singly linked list and circular linked list
 List the advantages of circular linked list

13.1 INTRODUCITON
A linked list is a linear data structure, in which the elements are not stored at contiguous memory
locations. The elements in a linked list are linked using pointers. In simple words, a linked list
consists of nodes where each node contains a data field and a reference (link) to the next node in
the list. Types of linked list are singly linked list, doubly linked list, priority linked list, circular
linked list. In general, the elements of linked list need not be in contiguous memory locations;
hence there will a pointer field in every node storing the address of next adjacent element
which will be

220
stored elsewhere in memory. So the logically adjacent elements need not be physically adjacent
in linked list. Here insertion, deletion are very easy.
13.2 SINGLY LINKED LIST
A linked list is a non-sequential collection of data items. It is a dynamic data [Link]
every data item in a linked list, there is an associated pointer that would give the memory location
of the next data item in the linked list.
The data items in the linked list are not in consecutive memory locations. They may be anywhere,
but the accessing of these data items is easier as each data item contains the addressof the next
data item.
Advantages of linked lists:
Linked lists have many advantages. Some of the very important advantages are:
1. Linked lists are dynamic data structures. i.e., they can grow or shrink during the execution
of a program.
2. Linked lists have efficient memory utilization. Here, memory is not preallocated. Memory is
allocated whenever it is required and it is de-allocated (removed) when it is no longer needed.
3. Insertion and Deletions are easier and efficient. Linked lists provide flexibility in inserting a
data item at a specified position and deletion of the data item from the given position.
4. Many complex applications can be easily carried out with linked lists.
Disadvantages of linked lists:
1. It consumes more space because every node requires a additional pointer to store address of
the next node.
2. Searching a particular element in list is difficult and also time consuming.

Types of Linked Lists:


Basically we can put linked lists into the following four items:
1. Single Linked List.
2. Double Linked List.
3. Circular Linked List.
4. Circular Double Linked List.
A single linked list is one in which all nodes are linked together in some sequential manner.
Hence, it is also called as linear linked list.
Applications of linked list:

221
1. Linked lists are used to represent and manipulate polynomial. Polynomials are expression
containing terms with non zero coefficient and exponents. For example:
P(x) = a0 Xn + a1 X n-1 + a n-1 X + an
2. Represent very large numbers and operations of the large number such as addition,
multiplication and division.
3. Linked lists are to implement stack, queue, trees and graphs.
4. Implement the symbol table in compiler construction

Comparison between array and linked list:

SINGLY LINKED LIST:


Here each node has two fields. Info and link field. Info field contains data and link field contains
address of the next element.

222
Each node is allocated in the heap using malloc(), so the node memory continues to exist until it
is explicitly de-allocated using free(). The front of the list is a pointer to the “start” node. The link
field of the last node will store NULL value.

The beginning of the linked list is stored in a "start" pointer which points to the first node. The first
node contains a pointer to the second node. The second node contains a pointer to the third node,
... and so on. The last node in the list has its next field set to NULL to mark the end of the list.
Code can access any node in the list by starting at the start and following the next pointers.
The start pointer is an ordinary local pointer variable, so it is drawn separately on the left top to
show that it is in the stack. The list nodes are drawn on the right to show that they are allocated
in the heap.
Implementation of Single Linked List:
Before writing the code to build the above list, we need to create a start node, used to create and
access other nodes in the linked list. The following structure definition will do (see figure):

223
Creating a structure with one data item and a next pointer, which will be pointing to next node of
the list. This is called as self-referential structure. Initialise the start pointer to be NULL.

The basic operations in a single linked list are:


 Creation.
 Insertion.
 Deletion.
 Traversing.
Creating a node for Single Linked List:
Creating a singly linked list starts with creating a node. Sufficient memory has to be allocated for
creating a node. The information is stored in the memory, allocated by using the malloc() function.
The function getnode(), is used for creating a node, after allocating memory for the structure of
type node, the information for the item (i.e., data) has to be read from the user, set next field to
NULL and finally returns the address of the node. Figure illustrates the creation of anode for single
linked list.

224
The following steps are to be followed to create ‘n’ number of nodes:

Get the new node using getnode().


 newnode = getnode();
 If the list is empty, assign new node as start.
 start = newnode;
 If the list is not empty, follow the steps given below:
 The next field of the new node is made to point the first node ([Link] node) in the list by
assigning the address of the first node.
 The start pointer is made to point the new node by assigning the address of the new node.
 Repeat the above steps n times

Function to create n nodes of a singly linked list:


void createlist(int n)
{
int i;
node * new node;
node *temp;
for(i = 0; i < n ; i+ +)
{
new node = getnode();
if(start = = NULL)
{
start = new node;
}
else
{
temp = start;
while(temp - > next != NULL)
temp = temp - > next;
temp - > next = new node;
}
}
}

225
INSERTION OPERATION TO SINGLY LINKED LIST:
We can insert a new element to already created singly linked list by three ways
1. Inserting an element at the beginning of the list
2. Inserting an element at the end of the list
3. Inserting an element any where in the middle of the list
Inserting an element at the beginning of the list:
The following steps are to be followed to insert a new node at the beginning of the list:
 Get the new node using getnode().
 newnode = getnode();
 If the list is empty then start = newnode.
 If the list is not empty, follow the steps given below:
 newnode -> next = start;
 start = newnode;

The function insert_at_beg(), is used for inserting a node at the beginning


void insert_at_beg()
{
node *newnode;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}

226
else
{
newnode -> next = start;
start = newnode;
}
}

Inserting a node at the end:


The following steps are followed to insert a new node at the end of the list:
 Get the new node using getnode()
 newnode = getnode();
 If the list is empty then start = newnode.
 If the list is not empty follow the steps given below:
 temp = start;
 while(temp -> next != NULL)
 temp = temp -> next;
 temp -> next = newnode;

The function insert_at_end(), is used for inserting a node at the end.


void insert_at_end()
{
node *newnode, *temp;
newnode = getnode();

227
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}

The following steps are followed, to insert a new node in an intermediate position in the
list:
 Get the new node using getnode().
 newnode = getnode();
 Ensure that the specified position is in between first node and last node.
 If not, specified position is invalid. This is done by countnode() function.
 Store the starting address (which is in start pointer) in temp and prev pointers. Then
traverse the temp pointer upto the specified position followed by prev pointer.
 After reaching the specified position, follow the steps given below:
 prev -> next = newnode;

228
 newnode -> next = temp;

The function insert_at_mid(), is used for inserting a node in the intermediate position.
void insert_at_mid()
{
node *newnode, *temp, *prev;
int pos, nodectr, ctr = 1;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr++;
}
prev -> next = newnode;
newnode -> next = temp;
}
else
{
printf("position %d is not a middle position", pos);
}
}

229
Deletion
In a single linked list, the deletion operation can be performed in three ways. They are as
follows...
Deleting from Beginning of the list
Deleting from End of the list
Deleting a Specific Node
Deleting from Beginning of the list
We can use the following steps to delete a node from beginning of the single linked list...
Step 1: Check whether list is Empty (head == NULL)
Step 2: If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate
the function.
Step 3: If it is Not Empty then, define a Node pointer 'temp' and initialize with head.
Step 4: Check whether list is having only one node (temp → next == NULL)
Step 5: If it is TRUE then set head = NULL and delete temp (Setting Empty list conditions)
Step 6: If it is FALSE then set head = temp → next, and delete temp.

Deleting from End of the list


We can use the following steps to delete a node from end of the single linked list...

230
Step 1: Check whether list is Empty (head == NULL)
Step 2: If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate
the function.

Step 3: If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and initialize
'temp1' with head.
Step 4: Check whether list has only one Node (temp1 → next == NULL)
Step 5: If it is TRUE. Then, set head = NULL and delete temp1. And terminate the function.
(Setting Empty list condition)
Step 6: If it is FALSE. Then, set 'temp2 = temp1 ' and move temp1 to its next node. Repeat
the same until it reaches to the last node in the list. (until temp1 → next == NULL)
Step 7: Finally, Set temp2 → next = NULL and delete temp1.

Deleting a Specific Node from the list


We can use the following steps to delete a specific node from the single linked list...
Step 1: Check whether list is Empty (head == NULL)
Step 2: If it is Empty then, display 'List is Empty!!! Deletion is not possible' and terminate
the function.
Step 3: If it is Not Empty then, define two Node pointers 'temp1' and 'temp2' and initialize
'temp1' with head.
Step 4: Keep moving the temp1 until it reaches to the exact node to be deleted or to the last
node. And every time set 'temp2 = temp1' before moving the 'temp1' to its next node.
Step 5: If it is reached to the last node then display 'Given node not found in the list!
Deletion not possible!!!'. And terminate the function.
Step 6: If it is reached to the exact node which we want to delete, then check whether list is
having only one node or not
Step 7: If list has only one node and that is the node to be deleted, then set head = NULL and
delete temp1 (free(temp1)).

231
Step 8: If list contains multiple nodes, then check whether temp1 is the first node in the list
(temp1 == head).
Step 9: If temp1 is the first node then move the head to the next node (head = head → next)
and delete temp1.
Step 10: If temp1 is not first node then check whether it is last node in the list (temp1 →next ==
NULL).
Step 11: If temp1 is last node then set temp2 → next = NULL and delete temp1 (free(temp1)).
Step 12: If temp1 is not first node and not last node then set temp2 → next = temp1 →next and
delete temp1 (free(temp1)).

Displaying a Single Linked List


We can use the following steps to display the elements of a single linked list...
Step 1: Check whether list is Empty (head == NULL)
Step 2: If it is Empty then, display 'List is Empty!!!' and terminate the function.
Step 3: If it is Not Empty then, define a Node pointer 'temp' and initialize with head.
Step 4: Keep displaying temp → data with an arrow (--->) until temp reaches to the last node
Step 5: Finally display temp → data with arrow pointing to NULL (temp → data --->NULL).
C program to create a linked list and to perform insertion, deletion, display and traverse
operations:
# include <stdio.h>
# include <conio.h>
# include <stdlib.h>
struct slinklist
{

232
int data;
struct slinklist *next;
};
typedef struct slinklist node;
node *start = NULL;
int menu()
{
int ch;
clrscr();
printf("\n [Link] a list ");
printf("\n ");
printf("\n [Link] a node at beginning ");
printf("\n [Link] a node at end");
printf("\n [Link] a node at middle");
printf("\n ");
printf("\n [Link] a node from beginning");
printf("\n [Link] a node from Last");
printf("\n [Link] a node from Middle");
printf("\n ");
printf("\n [Link] the list (Left to Right)");
printf("\n [Link] the list (Right to Left)");
printf("\n ");
printf("\n 10. Count nodes ");
printf("\n 11. Exit ");
printf("\n\n Enter your choice: ");
scanf("%d",&ch);
return ch;
}
node* getnode()
{
node * newnode;

233
newnode = (node *) malloc(sizeof(node));
printf("\n Enter data: ");
scanf("%d", &newnode -> data);
newnode -> next = NULL;
return newnode;
}
int countnode(node *ptr)
{
int count=0;
while(ptr != NULL)
{
count++;
ptr = ptr -> next;
}
return (count);
}
void createlist(int n)
{
int i;
node *newnode;
node *temp;
for(i = 0; i < n; i++)
{
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;

234
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
}
void traverse()
{
node *temp;
temp = start;
printf("\n The contents of List (Left to Right): \n");
if(start == NULL)
{
printf("\n Empty List");
return;
}
else
{
while(temp != NULL)
{
printf("%d-->", temp -> data);
temp = temp -> next;
}
}
printf(" X ");
}
void rev_traverse(node *start)
{
if(start == NULL)
{
return;

235
}
else
{
rev_traverse(start -> next);
printf("%d -->", start -> data);
}
}
void insert_at_beg()
{
node *newnode;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
newnode -> next = start;
start = newnode;
}
}
void insert_at_end()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{

236
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
void insert_at_mid()
{
node *newnode, *temp, *prev;
int pos, nodectr, ctr = 1;
newnode = getnode();
printf("\n Enter the position: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr++;
}
prev -> next = newnode;
newnode -> next = temp;
}
else
printf("position %d is not a middle position", pos);
}
void delete_at_beg()
{

237
node *temp;
if(start == NULL)
{
printf("\n No nodes are exist..");
return ;
}
else
{
temp = start;
start = temp -> next;
free(temp);
printf("\n Node deleted ");
}
}
void delete_at_last()
{
node *temp, *prev;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
temp = start;
prev = start;
while(temp -> next != NULL)
{
prev = temp;
temp = temp -> next;
}

238
prev -> next = NULL;
free(temp);
printf("\n Node deleted ");
}
}
void delete_at_mid()
{
int ctr = 1, pos, nodectr;
node *temp, *prev;
if(start == NULL)
{
printf("\n Empty List..");
return ;
}
else
{
printf("\n Enter position of node to delete: ");
scanf("%d", &pos);
nodectr = countnode(start);
if(pos > nodectr)
{
printf("\nThis node doesnot exist");
}
if(pos > 1 && pos < nodectr)
{
temp = prev = start;
while(ctr < pos)
{
prev = temp;
temp = temp -> next;
ctr ++;

239
}
prev -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
}
else
{
printf("\n Invalid position..");
getch();
}
}
}
void main(void)
{
int ch, n;
clrscr();
while(1)
{
ch = menu();
switch(ch)
{
case 1:
if(start == NULL)
{
printf("\n Number of nodes you want to create: ");
scanf("%d", &n);
createlist(n);
printf("\n List created..");
}
else
printf("\n List is already created..");

240
break;
case 2:
insert_at_beg();
break;
case 3:
insert_at_end();
break;
case 4:
insert_at_mid();
break;
case 5:
delete_at_beg();
break;
case 6:
delete_at_last();
break;
case 7:
delete_at_mid();
break;
case 8:
traverse();
break;
case 9:
printf("\n The contents of List (Right to Left): \n");
rev_traverse(start);
printf(" X ");
break;
case 10:
printf("\n No of nodes : %d ", countnode(start));
break;
case 11 :

241
exit(0);
}
getch();
}
}

13.3 CIRCULAR LINKED LIST


In single linked list, every node points to its next node in the sequence and the last node points
NULL. But in circular linked list, every node points to its next node in the sequence but the last
node points to the first node in the list.
Circular linked list is a sequence of elements in which every element has link to its next element
in the sequence and the last element has a link to the first element in the sequence.

Header is the pointer pointing to the beginning node of the list.


A circular linked list is one, which has no beginning and no end. A single linked list can be made
a circular linked list by simply storing address of the very first node in the link field of the last
node.

The basic operations in a circular single linked list are:


Creation.
Insertion.
Deletion.
Traversing.
Creation of circular linked list:
 Get the new node using getnode().

242
 newnode = getnode();
 If the list is empty, assign new node as start.
 start = newnode;
 If the list is not empty, follow the steps given below:
 temp = start;
 while(temp -> next != NULL)
 temp = temp -> next;
 temp -> next = newnode;
 repeat the above steps n times
 newnode -> next = start;

TO INSERT A NODE AT THE BEGINNING:

The following steps are to be followed to insert a new node at the beginning of the
circular list:
 Get the new node using getnode().
newnode = getnode();
 If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
 If the list is not empty, follow the steps given below:
last = start;
while(last -> next != start)
last = last -> next;
newnode -> next = start;
start = newnode;
last -> next = start;

243
The following steps are followed to insert a new node at the end of the list:
 Get the new node using getnode().
newnode = getnode();
 If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
 If the list is not empty follow the steps given below:
temp = start;
while(temp -> next != start)
temp = temp -> next;
temp -> next = newnode;
newnode -> next = start;

244
The following steps are followed, to delete a node at the beginning of the list:
 IF the list is empty, Display the message “ circular linked list is empty”
 If the list is not empty, follow the steps given below:
 last = temp = start;
 while(last -> next != start)
 last = last -> next;
 start = start -> next;
 last -> next = start;
 After deleting the node, if the list is empty then start = NULL.

The following steps are followed to delete a node at the end of the list:
 IF the list is empty, Display the message “ circular linked list is empty”
 If the list is not empty, follow the steps given below:
 temp = start;
 prev = start;
 while(temp -> next != start)
 {
 prev = temp;
 temp = temp -> next;
 }
 prev -> next = start;
 After deleting the node, if the list is empty then start = NULL.

245
13.4 DOUBLY LINKED LIST
A double linked list is a two-way list in which all nodes will have two links. This helps in accessing
both successor node and predecessor node from the given node position. It provides bi-directional
traversing. Each node contains three fields:
Left link.
Data.
Right link.
The left link points to the predecessor node and the right link points to the successor node. The
data field stores the required data.

Here, 'link1' field is used to store the address of the previous node in the sequence, 'link2' field is
used to store the address of the next node in the sequence and 'data' field is used to store the
actual value of that node.

 In double linked list, the first node must be always pointed by head.
 Always the previous field of the head node must be NULL.
 Always the next field of the last node must be NULL.

246
Many applications require searching forward and backward thru nodes of a list.
For example searching for a name in a telephone directory would need forward and backward
scanning thru a region of the whole list.
The basic operations in a double linked list are:
Creation.
Insertion.
Deletion.
Traversing.
To create a node, the structure is :

The following steps are to create a doubly linked list:


 Get the new node using getnode().
 newnode =getnode();
 If the list is empty then start = newnode.
 If the list is not empty, follow the steps given below:
 The left field of the new node is made to point the previous node.

247
 The previous nodes right field must be assigned with address of the new node.
 Repeat the above steps n times.

13.5 SUMMARY

In this unit, we studied about variants of linked list like singly linked list, doubly linked list, circular
linked list and the operations that are performed on these data structures. The implementation of
singly linked list is also studied. The common operations performed on linked list are creation,
insertion, deletion, display operations. Linked List is a very commonly used linear data structure
which consists of set of nodes in a sequence. Each node has two fields known as data and link.
Data field stores actual data and link contains address of next node to point to the next node.
Linked Lists are used to create trees and graphs.

13.6 SUMMARY

 Linked list,
 singly linked list,
 doubly linked list,
 circular linked list,

13.7 QUESTION FOR SELF STRUDY

1. Explain singly linked list.

2. Write the structure of a node of singly linked list and its implementation in C .

3. Write an algorithm to create singly linked list. Explain with example.

4. Explain the steps to insert an element at the beginning of a singly linked list with example.

248
5. Explain the steps to insert an element at the end of a singly linked list with example.

6. Explain the steps to insert an element at the middle of a singly linked list with example.

7. How do you delete an element from singly linked list? Explain.

8. Explain doubly linked list with example.

9. Explain circular linked list with example.

10. Distinguish between array and linked list.

13.8 REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg


 "Programming with C" by E. Balagurusamy
 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

249
UNIT 14

STACKS AND QUEUES

Structure:

14.0 Objectives

14.1 Introduction

14.2 Stack

14.3 QUEUE

14.4 Implementation of Stack and QUEUE using array

14.5 Implementation of stack and queue using linked list

14.6 Summary

14.7 Keywords

14.8 Questions for self-study

14.9 References

14.0 OBJECTIVES

After studying this unit, you will be able to

 Explain the operations performed on stack


 Explain the operations performed on queue
 Describe implementation of stack and queue using arrays
 Describe implementation of stack and queue using linked list

14.1 INTRODUCTION

There are certain situations in computer science that one wants to restrict insertions and deletions so that
they can take place only at the beginning or the end of the list, not in the middle. Two of such data
structures that are useful are: Stack.
Queue.

250
Linear lists and arrays allow one to insert and delete elements at any place in the list i.e., at the beginning,
at the end or in the middle. Stack follows FIFO rule. The insertion and deletion is restricted to one end.
The operation of insertion is called PUSH and deletion operation is called POP. There will be a pointer
called TOP pointing to the top most element of the stack which will be the element to be deleted from
stack. During insertion, the top pointer will be increment by one and the element is inserted. After deletion,
the top pointer will be decremented by one.

Queue is a data structure which follows LIFO rule. The insertion will be from the rear end and deletion
will be from the front end. Hence there are two pointers front and rear pointing to front and rear end.
During insertion, rear pointer is incremented by one. After deleting the front element, the front pointer is
updated to point to the next element.

14.2 STACK

A stack is a list of elements in which an element may be inserted or deleted only at one end, called
the top of the stack. Stacks are sometimes known as LIFO (last in, first out) [Link] the items can be
added or removed only from the top i.e. the last item to be added to a stack is the first item to be removed.
The two basic operations associated with stacks are: Push: is
the term used to insert an element into a stack. Pop: is the
term used to delete an element from a stack. Fig 14.2.1

251
All insertions and deletions take place at the same end, so the last element added to the stack will be the
first element removed from the stack. When a stack is created, the stack base remains fixed while the
stack top changes as elements are added and removed. The most accessible element is the top and the least
accessible element is the bottom of the stack. Let us consider a stack with 6 elements capacity. This is
called as the size of the stack. The number of elements to be added should not exceed the maximum size of
the stack. If we attempt to add new element beyond the maximum size, we will encounter a stack
overflow condition. Similarly, you cannot remove elements beyond the base of the stack. If such is the
case, we will reach a stack underflow condition. When an element is added to a stack, the operation is
performed by push (). Figure shows the creation of a stack and addition of elements using push (). During
insertion, the top pointer is incremented and to the new location, element is pushed. Fig 14.2.2

When an element is taken off from the stack, the operation is performed by pop (). Figure shows a stack
initially with three elements and shows the deletion of elements using pop (). The element pointed by top
pointer is deleted. Fig 14.2.3

252
Applications of stacks:
1. Stack is used by compilers to check for balancing of parentheses, brackets and braces.
2. Stack is used to evaluate a postfix expression.
3. Stack is used to convert an infix expression into postfix/prefix form.
4. In recursion, all intermediate arguments and return values are stored on the stack.
5. During a function call the return address and arguments are pushed onto a stack and on return
they are popped off.
Algorithm for PUSH:

begin procedure push: stack, data if


stack is full
return “stack overflows”
endif
top ← top + 1
stack[top] ← data end
procedure

NOTE:During insertion, we check for overflow condition. This condition arises if stack is [Link] the stack
is not full, then top pointer is incremented by one. The element is inserted.

Algorithm for POP:

begin procedure pop: stack if


stack is empty
return “Stack underflows”
endif
data ← stack[top]
top ← top - 1
return data
end procedure

NOTE:During deletion, we check for underflow condition. This condition arises if the stack is empty. If
the stack is note empty, then the element pointed by top pointed is accessed and copied to data. Top
pointer is decremented by one.

253
14.3 QUEUE

Queue is a data structure. Unlike stacks, a queue is open at both its ends. One end is always used to insert
data (enqueue) and the other is used to remove data (dequeue). Queue follows First-In- First-Out
methodology, i.e., the data item stored first will be accessed first. Fig 14.3.1

We shall use the following operations on queues:


enqueue: which inserts an element at the end of the queue.
dequeue: which deletes an element at the start of the queue.

Here two pointers front and rear are used. During insertion, rear pointer is incremented by one and the
element is inserted. During deletion, the front pointer is incremented to point to the next element after
[Link] stack, during insertion we have to check form overflow condition and during deletion, we
have to check for queue underflow condition.

OVERFLOW condition occurs when rear pointer value is equal to maximum size of queue.

UNDERFLOW condition occurs when both front and rear pointers have same value.

Applications of Queue:
1. It is used to schedule the jobs to be processed by the CPU.
2. When multiple users send print jobs to a printer, each printing job is kept in
the printing queue. Then the printer prints those jobs according to first in
first out (FIFO) basis.
3. Breadth first search uses a queue data structure to find an element from a
graph.

254
QUEUE Representation:

Let us consider a queue, which can hold maximum of five elements. Initially the queue is empty. So both

F and R pointers have value zero. Fig 14.3.2

1. Insert 11.

2. Insert 22

3. insert 33

4. Delete 11

5. Delete 22

255
6. Insert 44 and 55

7. Insert 66
It is not possible , because Rear pointer has reached the end. So even though , space is available
in the front end, we cannot insert the element, once the rear pointer reaches the end. This type of
queue is called linear queue.

Algorithm for Queue insertion:

The following steps should be taken to enqueue (insert) data into a queue −
Step 1 − Check if the queue is full.
Step 2 − If the queue is full, produce overflow error and exit.
Step 3 − If the queue is not full, increment rear pointer to point the next empty space.
step 4- If the queue is empty, then increment front pointer also.
Step 5 − Add data element to the queue location, where the rear is pointing.
Step 6 − Return success.

QUEUE DELETION:

Accessing data from the queue is a process of two tasks − access the data where front is
pointing and remove the data after access. The following steps are taken to perform dequeue
operation −
Step 1 − Check if the queue is empty.
Step 2 − If the queue is empty, produce underflow error and exit.

256
Step 3 − If the queue is not empty, access the data where front is pointing.
Step 4- If the queue has only one element, set both front and rear pointer to zero after deletion.

Step 5 − Otherwise;Increment front pointer to point to the next available data element.

Step 6 − Return success.

14.4 IMPLEMENTATION OF STACK AND QUEUE USING ARRAY

Stack implementation using array:

# include <stdio.h> #
include <conio.h> #
include <stdlib.h> #
define MAX 6
int stack[MAX];
int top = 0;
int menu()
{
int ch;
clrscr();
printf("\Stack operation using array\n”); printf("\n
-----------********** ------------------------------ \n");
printf("\n 1. Push ");
printf("\n 2. Pop ");
printf("\n 3. Display");
printf("\n 4. Quit ");
printf("\n Enter your choice: ");
scanf("%d", &ch);
return ch;
}
void display()
{
int i;
if(top == 0)
{
printf("\n\nStack empty..");

return;
}
else
{
printf("\n\nElements in stack:");

257
for(i = 0; i < top; i++)
printf("\t%d", stack[i]);
}
}
void pop()
{
if(top == 0)
{
printf("\n\nStack Underflow..");
return;
}
else
printf("\n\npopped element is: %d ", stack[--top]);
}
void push()
{
int data;
if(top == MAX)
{
printf("\n\nStack Overflow..");
return;
}
else
{
printf("\n\nEnter data: ");
scanf("%d", &data);
stack[top] = data;
top = top + 1;
printf("\n\nData Pushed into the stack");
}
}
void main()
{
int ch;
do
{
ch = menu();
switch(ch)
{
case 1:
push();
break;
case 2:
pop();
break;
case 3:

258
display();
break;
case 4:
exit(0);
}
getch();
} while(1);
}

 QUEUE IMPLEMENTATION USING ARRAY:

In order to create a queue we require a one dimensional array Q(1:n) and two variables front and rear.
The conventions we shall adopt for these two variables are that front is always 1 less than the actual front of
the queue and rear always points to the last element in the queue. Thus, front =rear if and only if there are
no elements in the queue. The initial condition then is front = rear =
0. The various queue operations to perform creation, deletion and display the elements in a queue
are as follows:
1. insertQ(): inserts an element at the end of queue Q.
2. deleteQ(): deletes the first element of Q.
3. displayQ(): displays the elements in the queue.
# include <conio.h>
# define MAX 6
int Q[MAX]; int
front, rear; void
insertQ()
{
int data;
if(rear == MAX)
{
printf("\n Linear Queue is full");
return;
}
else
{
printf("\n Enter data: ");
scanf("%d", &data);
Q[rear] = data;
rear++;
printf("\n Data Inserted in the Queue ");

259
}
}
void deleteQ()
{
if(rear == front)
{
printf("\n\n Queue is Empty..");
return;
}
else
{
printf("\n Deleted element from Queue is %d",
Q[front]); front++;
}
}
void displayQ()
{
int i;
if(front == rear)
{
printf("\n\n\t Queue is Empty");
return;
}
else
{
printf("\n Elements in Queue are: ");
for(i = front; i < rear; i++)

{
printf("%d\t", Q[i]);
}
}
}
int menu()
{
int ch;
clrscr();
printf("\n \tQueue operations using ARRAY..");
printf("\n -----------********** ------------------ \n");
printf("\n 1. Insert ");
printf("\n 2. Delete ");
printf("\n 3. Display");
printf("\n 4. Quit ");
printf("\n Enter your choice: ");
scanf("%d", &ch);
return ch;

260
}
void main()
{
int ch;
do
{
ch = menu();
switch(ch)
{
case 1:
insertQ();
break;
case 2:
deleteQ();
break; case
3:
displayQ();
break;
case 4:
return;
}
getch();
} while(1);
}

14.5 IMPLEMENTATION OF STACK AND QUEUE USING LINKED LIST

We can represent a stack as a linked list. In a stack push and pop operations are performed at one end
called top. We can perform similar operations at one end of list using top pointer. The linked stack looks
as shown in figure 14.5.1

# include <conio.h> #
include <stdlib.h>

261
struct stack
{
int data;
struct stack *next;
};
void push();
void pop(); void
display();
typedef struct stack node; node
*start=NULL;
node *top = NULL;
node* getnode()
{
node *temp;
temp=(node *) malloc( sizeof(node)) ;
printf("\n Enter data ");
scanf("%d", &temp -> data);
temp -> next = NULL; return
temp;
}
void push(node *newnode)
{
node *temp;
if( newnode == NULL )
{
printf("\n Stack Overflow..");
return;
}

{
start = newnode;
top = newnode;
}
else
{
temp = start;
while( temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
top = newnode;
}
printf("\n\n\t Data pushed into stack");
}
void pop()
{
node *temp;

262
if(top == NULL)
{
printf("\n\n\t Stack underflow");
return;
}
temp = start;
if( start -> next == NULL)
{
printf("\n\n\t Popped element is %d ", top -> data); start =
NULL;
free(top); top
= NULL;
}
else
{
while(temp -> next != top)
{
temp = temp -> next;
}
temp -> next = NULL;
printf("\n\n\t Popped element is %d ", top -> data); free(top);
top = temp;
}
}
void display()
{
node *temp;
if(top == NULL)
{
printf("\n\n\t\t Stack is empty ");
}
else
{
temp = start;
printf("\n\n\n\t\t Elements in the stack: \n");
printf("%5d ", temp -> data);
while(temp != top)
{
temp = temp -> next; printf("%5d
", temp -> data);
}
}
}
char menu()
{

263
char ch;
clrscr();
printf("\n \tStack operations using pointers.. ");
printf("\n -----------********** ------------------ \n");
printf("\n 1. Push ");
printf("\n 2. Pop ");
printf("\n 3. Display");
printf("\n 4. Quit ");
printf("\n Enter your choice: "); ch
= getche();
return ch;
}
void main()
{
char ch;
node *newnode;
do
{
ch = menu();
switch(ch)
{
case '1' :
newnode = getnode();
push(newnode); break;
case '2' :
pop();
break;
case '3' :
display();
break;
case '4':
return;
}
getch();
} while( ch != '4' );
}
 QUEUE IMPLEMENTATION USING LINKED LIST:

We can represent a queue as a linked list. In a queue data is deleted from the front end and inserted at the
rear end. We can perform similar operations on the two ends of a list. We use two pointers front and rear
for our linked queue implementation
14.5.2

264
# include <stdlib.h> #
include <conio.h>
struct queue
{
int data;
struct queue *next;
};
typedef struct queue node;
node *front = NULL; node
*rear = NULL; node*
getnode()
{
node *temp;
temp = (node *) malloc(sizeof(node)) ;
printf("\n Enter data ");
scanf("%d", &temp -> data);
temp -> next = NULL; return
temp;
}
void insertQ()
{
node *newnode;
newnode = getnode();
if(newnode == NULL)
{
printf("\n Queue Full");
return;
}
if(front == NULL)
{
front = newnode;
rear = newnode;
}
else
{
rear -> next = newnode;
rear = newnode;
}
printf("\n\n\t Data Inserted into the Queue..");

265
}
void deleteQ()
{
node *temp; if(front
== NULL)
{
printf("\n\n\t Empty Queue..");
return;
}
temp = front;
front = front -> next;
printf("\n\n\t Deleted element from queue is %d ", temp -> data);
free(temp);
}
void displayQ()
{
node *temp; if(front
== NULL)
{
printf("\n\n\t\t Empty Queue ");
}
else
{
temp = front;
printf("\n\n\n\t\t Elements in the Queue are: ");
while(temp != NULL )
{
printf("%5d ", temp -> data); temp
= temp -> next;
}
}
}
char menu()
{
char ch;
clrscr();
printf("\n \t..Queue operations using pointers.. ");
printf("\n\t -----------**********-------------
\n"); printf("\n 1. Insert ");
printf("\n 2. Delete ");
printf("\n 3. Display");
printf("\n 4. Quit ");
printf("\n Enter your choice: "); ch
= getche();
return ch;
}

266
void main()
{
char ch;
do
{
ch = menu();
switch(ch)
{
case '1' :
insertQ();
break; case
'2' :
deleteQ();
break; case
'3' :
displayQ();
break;
case '4':
return;
}
getch();
} while(ch != '4');
}

14.6 SUMMARY
In this unit, we studied about stack, queue and their implementation using array and linked
[Link] queue which we studied is called linear queue. The stack has only one pointer called
top. It points to the top most element of the stack. Insertion is called PUSH and deletion
operation is called POP. Whereas queue has two pointers front and [Link] stack, insertion and
deletion operations are done from only one end.

14.7 KEYWORDS

 Stack
 queue
 top
 rear

267
14.8 QUESTIONS FOR SELF STUDY

1. Explain stack push and pop operations with example.

2. Explain queue with insertion and deletion operations.

3. How do you implement stack using array? Explain with program.

4. Write the algorithm for PUSH and POP operation.

5. Write the algorithm for insertion and deletion operations to queue.

14.9 REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg


 "Programming with C" by E. Balagurusamy
 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

268
UNIT 15

RECURSION

Structure:

15.0 Objectives

15.1 Introduction

15.2 Recursion

15.3 Recursion function

15.4 Summary

15.5 Keywords

15.6 Questions for self-study

15.7 References

15.0 OBJECTIVES

After studying this unit, you will be able to

 Explain Recursion
 Explain recursive algorithm to find factorial of a number
 Write recursive algorithm to find GCD of a number

15.1 INTRODUCTION

A function is recursive if a statement in the body of the function calls itself. Recursion is the process of
defining something in terms of itself. For a computer language to be recursive, a function must be able to
call itself.

Differences between recursion and iteration:

Both involve repetition.

Both involve a termination test.

Both can occur infinitely.

269
15.2 RECURSION

A function is recursive if a statement in the body of the function calls itself. Recursion is the process of
defining something in terms of itself. For a computer language to be recursive, a function must be able to
call itself.
Recursive function: calling a function by itself until the given terminal condition is satisfied is called
recursion and the function is called recursive function.
When a function calls itself, new local variables and parameters are allocated storage on the stack
and the function code is executed with these new variables from the start.
A recursive call does not make a new copy of the function. Only the arguments and variables are new. As
each recursive call returns, the old local variables and parameters are removed from the stack and
execution resumes at the point of the function call inside the function.
When writing recursive functions, you must have an exit or terminal condition somewhere to force the
function to return without the recursive call being executed. If you do not have an exit condition, the
recursive function will recurse forever until you run out of stack space and indicate error about lack of
memory, or stack overflow.
Syntax
void recurse()
{
… .. …
recurse(); /* calling of the function by itself */
… .. …
}

270
int main()
{
… .. …
recurse();
… .. …
}

For example, let us compute factorial of an integer using recursion. #include


<stdio.h>

int factorial(int x)

if(x <= 1)

return 1;

return x * factorial(x – 1);

int main()

int x = 12;

printf(“The factorial of the number %d is equal to %d\n”, x, factorial(x)); return

0;

OUTPUT:
The factorial of the number 12 is equal to 479001600

271
Here the function factorial is called recursively until the terminal condition (x<=1) is satisfied. Recursion

Factorials:
5! =5 * 4! = 5 * = factorial (5) = 5 * factorial (4) =
4! = 4 *3! = 4 * = _ factorial (4) = 4 * factorial (3) =
3! = 3 * 2! = 3 * = _ factorial (3) = 3 * factorial (2) =
2! = 2 * 1! = 2 * = _ factorial (2) = 2 * factorial (1) =
1! = 1
5! = 5*4! = 5*4*3! = 5*4*3*2! = 5*4*3*2*1! = 5*4*3*2*1*0! = 5*4*3*2*1*1=120

Example 2:

Program to calculate GCD of two numbers #include


<stdio.h>
int hcf(int n1, int n2); int
main()
{
int n1, n2;
printf("Enter two positive integers: "); scanf("%d
%d", &n1, &n2);
printf("G.C.D of %d and %d is %d.", n1, n2, hcf(n1, n2)); return
0;
}

int hcf(int n1, int n2)


{
if (n2 != 0)
return hcf(n2, n1 % n2);
else
return n1;
}

OUTPUT:
Enter two positive integers: 366 60
G.C.D of 366 and 60 is 6.

Example 3:
To print Fibonacci series using recursion
#include<stdio.h>
void printFibonacci(int n){
static int n1=0,n2=1,n3;

272
if(n>0){
n3 = n1 + n2;
n1 = n2;
n2 = n3; printf("%d
",n3);
printFibonacci(n-1);
}
}
int main(){
int n;
printf("Enter the number of elements: ");
scanf("%d",&n);
printf("Fibonacci Series: ");
printf("%d %d ",0,1);
printFibonacci(n-2);//n-2 because 2 numbers are already printed return
0;
}

OUTPUT:
Enter the number of elements: 10 Fibonacci
Series: 0 1 1 2 3 5 8 13 21 34

15.3 RECURSION FUNCTION

Recursion is a programming concept where a function calls itself to solve a problem by


breaking it down into smaller, simpler versions of the same problem. It involves defining a base
case to stop the recursive calls and a recursive step that reduces the problem size until the base
case is reached. This approach allows elegant and concise solutions for certain problems, like
traversing tree structures or calculating factorials. However, it requires careful handling to
prevent infinite loops and efficient use of system resources.
o Base case: Recursion involves a base case that stops the recursive calls to prevent
infinite loops, ensuring program termination.
o Recursive call The recursive call is the code executed repeatedly inside the
recursive function while making recursive calls.

273
Syntax

void recursive_fun() //recursive function


{
Base_case; // Stopping Condition

recursive_fun(); //recursive call


}

int main()
{

recursive_fun(); //function call

}
The function call inside the main function is normal call, it calls the recursive fun () function
inside which there is another function call recursive fun (); which is termed as recursive call and
the whole recursive fun () function is recursive function. Base case is the stopping condition for
the recursive function.
 How does Recursion in C work?
The recursion is possible using a method or function in C language. The recursive function or
method has two main parts in its body, i.e., the base case and the recursive case. While
the recursive method is executed, first, the base case is checked by the program. If it turns out
true, the function returns and quits; otherwise, the recursive case is executed. Inside the
recursive case, we have a recursive call that calls the function inside which it is present. The
representation of recursion in the program is as follows.

recursive_function()
{
//base case
if base_case = true;
return;

else
//recursive case
return code_for_recursion; //includes recursive call
}

In the following image, there is a recursive function inside which there is a recursive call that
calls the recursive function until the condition of the problem is true. If the condition gets
satisfied, then the condition is false, and the program control goes for the remaining statements
and stops the program. Fig 15.3.1

274
 Types of Recursions in C

There are two types of recursions in the C language.

1. Direct Recursion
2. Indirect Recursion

1. Direct Recursion

Direct recursion in C occurs when a function calls itself directly from inside. Such functions are also called
direct recursive functions. Following is the structure of direct recursion.

function_01()
{
//some code
function_01();
//some code
}

275
In the direct recursion structure, the function_01() executes, and from inside, it calls
itself recursively.
2. Indirect Recursion
Indirect recursion in C occurs when a function calls another function and if this
function calls the first function again. Such functions are also called indirect
recursive functions. Following is the structure of indirect recursion.

function_01()
{
//some code
function_02();
}

function_02()
{
//some code
function_01();
}

In the indirect recursion structure, the function_01() executes and


calls function_02(). After calling now, function_02 executes where inside it there is
a call for function_01, which is the first calling function.
15.4 SUMMARY

In this unit, we studied about recursion. Recursion is calling a function by itself repeatedly till some exit
condition is satisfied. When a function calls itself, new local variables and parameters are allocated
storage on the stack and the function code is executed with these new variables from the start. A recursive
call does not make a new copy of the function. Only the arguments and variables are new. As each
recursive call returns, the old local variables and parameters are removed from the stack and execution
resumes at the point of the function call inside the function.

15.5 KEYWORDS

 Recursion

 exit

 condition

276
15.6: QUESTION FOR SELF STUDY

1. Define recursion.

2. Write the syntax of recursive function

3. Explain recursive function to find factorial of a number with program.

4. Write a program to find GCD of two numbers using recursion.

5. Write a program to generate Fibonacci series using recursion.

15.7: REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg


 "Programming with C" by E. Balagurusamy
 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

277
UNIT -16
STRUCTURE AND UNION

Structure:

16.0 Objectives

16.1 Introduction

16.2 Structure

16.3 Union

16.4 function pointers

16.5 Handling errors and exceptions

16.6 Summary

16.7 Keywords

16.0 OBJECTIVES

After studying this unit, you will be able to

 Explain structure and union


 Distinguish between structure and union
 Distinguish between array and structure
 Create structure to accept and print student details
 Explain function pointer
 Explain error and exception handling in C

16.1 INTRODUCTION

Structure is a collection of data items of different data types under a common name. Whereas array is a
collection of data items of same data type. Union is a collection of data items of different data types
similar to structure but in this case all the members share a common memory location. The size of the
union corresponds to the length of the largest member. Although C does not provide direct support to
error handling (or exception handling), there are ways through which error handling can be done in C. A
programmer has to prevent errors in the first place and test return values from the functions.

278
When the address of the value is passed to the function it is called call by reference. In call by
reference since the address of the value is passed any changes made to the value reflects in the calling
function. In call by reference, pointers are used to refer to the address of values.
16.2 STRUCTURE

A structure is a user defined data type. We know that arrays can be used to represent a group of data items
that belong to the same type, such as int or float. However, we cannot use an array if we want to represent
a collection of data items of different types using a single name.A structure is a convenient tool for
handling a group of logically related data items. Structure is a user defined data type used to represent a
group of data items of different types using a single name.
The syntax of structure declaration is

struct structure_name

type element 1;

type element 2;

……………..

type element n;

};

In structure declaration the keyword struct appears first, this followed by structure name. The
member of structure should be enclosed between a pair of braces and it defines one by one each ending
with a semicolon. It can also be array of structure. There is an enclosing brace at the end of declaration
and it end with a semicolon.
We can declare structure variables as follows struct
structure_name var1,var2,…..,var n; Example:
To store the names, roll number and total mark of a student you can declare 3 variables. To store
this data for more than one student 3 separate arrays may be declared. Another choice is to make a
structure. No memory is allocated when a structure is declared. It just defines the “form” of the structure.
When a variable is made then memory is allocated. This is equivalent to

279
saying that there's no memory for “int”, but when we declare an integer that is int var; only then memory
is allocated.
The structure for the abovementioned case will look like struct
student
{
int rollno;
char name[25];
float totalmark; };
We can now declare structure variables stud1, stud2 as follows struct
student stud1,stud2;

Accessing structure Variable


The different variable types stored in a structure are called its members. The structure member can be
accessed by using a dot (.) operator, so the dot operator is known as structure member operator. Example:
In the above example stud1 is a structure variable of type student. To access the member name, we would
write [Link]. Similarly, stud1’s rollno and stud1’s totalmark can be accessed by writing [Link]
and [Link] respectively.
Initializing Structure Members
Structure members can be initialized at declaration. This much the same manner as the element of an
array; the initial value must appear in the order in which they will be assigned to their corresponding
structure members, enclosed in braces and separated by commas.
The general form is
struct structure_name var={val1,val2,val3…..};
Example:
#include <stdio.h>
#include<conio.h>
void main()
{
struct student

280
{
char *name;
int rollno;
float totalmark;
};
struct student stud1={"Venkat",1,98}; struct
student stud3= {"Shweta",3,97}; struct
student stud2={"Arpita",2,99}; clrscr();
printf(“STUDENTS DETAILS:\n”);
printf(“\n\n Roll number:%d\n Name:%s\n Total Marks:%f”, [Link], [Link], [Link]);
printf(“\n\n Roll number:%d\n Name:%s\n Total Marks:%f”, [Link], [Link], [Link]);
printf(“\n\n Roll number:%d\n Name:%s\n Total Marks:%f”, [Link], [Link], [Link]);
getch();
}
Output
STUDENTS DETAILS:
Roll number: 1 Name:
Venkat
Total Marks:98.000000
Roll number: 2
Name: Arpita
Total Marks:99.000000
Roll number: 2
Name:Shweta
Total Marks:99.000000
Array of structures:

281
It is possible to store a structure has an array element. i.e., an array in which each element is a structure.
Just as arrays of any basic type of variable are allowed, so are arrays of a given type of structure.
Although a structure contains many different types, the compiler never gets to know this information
because it is hidden away inside a sealed structure capsule, so it can believe that all the elements in the
array have the same type, even though that type is itself made up of lots of different types.

The declaration statement is given below.


struct struct_name
{
type element 1;
type element 2;
……………..
type element n;
}array name[size];
Example:
struct student
{
int rollno;
char name[25];
float totalmark;
} stud[100];
In this declaration stud is a 100-element array of structures. Hence, each element of stud is a separate
structure of type student. An array of structure can be assigned initial values just as any other array. So
the above structure can hold information of 100 students.

Program to demonstrate use of array of structure


#include <stdio.h>
#include <conio.h>
void main()

282
{
struct student
{
int rollno;
char name[25];
int totalmark;
}stud[100];
int n,i;
clrscr();
printf("Enter total number of students\n\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter details of %d-th student\n",i+1);
printf("Name:\n"); scanf("%s",&stud[i].name);
printf("Roll number:\n");
scanf("%d",&stud[i].rollno);
printf("Total mark:\n");
scanf("%d",&stud[i].totalmark);
}
printf("STUDENTS DETAILS:\n");
for(i=0;i<n;i++) { printf("\nRoll number:%d\n",stud[i].rollno);
printf("Name:%s\n",stud[i].name);
printf("Total mark:%d\n",stud[i].totalmark);
}
getch();
}
OUTPUT
Enter total number of students: 3

283
Enter details of 1-th student
Name:SUBAHAS
Roll number:11
Total mark:589
Enter details of 2-th student
Name:RUKSANA
Roll number:12
Total mark:594
Enter details of 3-th student
Name:SANA
Roll number:13
Total mark:595
STUDENTS DETAILS:
Roll number:11
Name: SUBAHAS
Total mark:589 Roll
number:12 Name:
RUKSANA
Total mark:594
Roll number:13
Name: SANA
Total mark:595

16.3 UNION

Union is a user created data type similar to structure but in this case all the members share a common
memory location. The size of the union corresponds to the length of the largest member. Since the
member share a common location, they have the same starting address. The real purpose of unions is to
prevent memory fragmentation by arranging for a standard size for data in the memory. By having a
standard data size, we can guarantee that any hole left when dynamically allocated memory is freed will
always be reusable by another instance of the same type of union. This is a natural strategy in system
programming where many instances of different kinds of variables with a related purpose and stored
dynamically.

284
A union is declared in the same way as a structure. The syntax of union declaration is
union union_name
{
type element 1;
type element 2;
……………..
type element n;
};
This declares a type template.
Variables are then declared as:
union union_name x,y,z;
For example, the following code declares a union data type called Student and a union variable called
stud:
union student
{
int rollno;
float totalmark;
};
union student stud;
It is possible to combine the declaration of union combination with that of the union variables, as shown
below.
union union_name
{
type element 1;
type element 2;
……………..
type element n;
}var1,var2,…,varn;
The following single declaration is equivalent to the two declaration presented in the previous example.
union student

285
{
int rollno;
float totalmark;
}x,y,z;

 A union is a user defined data type like structure.


 The union groups logically related variables into a single unit.
 The union data type allocates the space equal to space needed to hold the largest data
member of union.
 The union allows different types of variable to share same space in memory.

Accessing Union Members


 Individual union members can be used in the same way that structure members can be used by
using the member dot operator (.).
 Only one union member should be accessed at a time, as different variable share same space in
memory.

Example
union shared
{
char c;
int i;
};
shared.c =’a’;
shared.d=1;
In this case, value assignment to member variable (d) overwrites the member variable(c).

286
Difference between Structure and Union

16.4 FUNCTION POINTERS

 C Pointer is a variable that stores/points the address of another variable.


 C Pointer is used to allocate memory dynamically i.e., at run time.
 The variable might be any of the data type such as int, float, char, double, short etc.

287
 Syntax
data_type *var_name;
Example :
int *p; char *p;
Where, * is used to denote that ―p is pointer variable and not a normal variable.
Key points to remember about pointers in C:
 Normal variable stores the value whereas pointer variable stores the address of the variable.
 The content of the C pointer always be a whole number i.e. address.
 Always C pointer is initialized to null, i.e. int *p = null.
 The value of null pointer is 0.
 & symbol is used to get the address of the variable.
 symbol is used to get the value of the variable that the pointer is pointing to.
 If pointer is assigned to NULL, it means it is pointing to nothing.
 The size of any pointer is 2 byte (for 16 bit compiler).
 No two pointer variables should have the same name.
 But a pointer variable and a non-pointer variable can have the same name.
Pointer –Initialization:
Assigning value to pointer:
It is not necessary to assign value to pointer. Only zero (0) and NULL can be assigned to a pointer
no other number can be assigned to a pointer.
Consider the following examples; int
*p=0;
int *p=NULL; The above two assignments are valid. int
*p=1000; This statement is invalid.
Assigning variable to a pointer:
int x; *p;
p = &x;
This is nothing but a pointer variable p is assigned the address of the variable x. The address of the
variables will be different every time the program is executed.
Reading value through pointer:
int x=123; *p; p
= &x;

288
Here the pointer variable p is assigned the address of variable x.
printf(―%d‖, *p); will display value of x 123. This is reading value through pointer
printf(―%d‖, p); will display the address of the variable x.
printf(―%d‖, &p); will display the address of the pointer variable p.
printf(―%d‖,x); will display the value of x 123.
printf(―%d‖, &x); will display the address of the variable x.
Note: It is always a good practice to assign pointer to a variable rather than 0 or NULL.
Pointer Assignments:
We can use a pointer on the right-hand side of an assignment to assign its value to another
variable.
Example:
int main()
{
int var=50;
int *p1, *p2;
p1=&var;
p2=p1;
}
Function pointer in C:
In C, like normal data pointers (int *, char *, etc), we can have pointers to functions. Following is a
simple example that shows declaration and function call using function pointer.
#include <stdio.h>
// A normal function with an int parameter
// and void return type void
fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
// fun_ptr is a pointer to function fun()

289
void (*fun_ptr)(int) = &fun;
/* The above line is equivalent of following two void
(*fun_ptr)(int);
fun_ptr = &fun;
*/
// Invoking fun() using fun_ptr
(*fun_ptr)(10);
return 0;
}
Output:
Value of a is 10
1) Unlike normal pointers, a function pointer points to code, not data. Typically a function
pointer stores the start of executable code.
2) Unlike normal pointers, we do not allocate de-allocate memory using function pointers.
3) A function’s name can also be used to get functions’ address. For example, in the below
program, we have removed address operator ‘&’ in assignment. We have also changed
function call by removing *, the program still works.
#include <stdio.h>
// A normal function with an int parameter
// and void return type void
fun(int a)
{
printf("Value of a is %d\n", a);
}

int main()
{
void (*fun_ptr)(int) = fun; // & removed
fun_ptr(10); // * removed
return 0;
}

290
Output:
Value of a is 10

16.5 HANDLING ERRORS AND EXCEPTIONS

As such C programming does not provide direct support for error handling but being a system
programming language, it provides you access at lower level in the form of return values. Most of the C
or even Unix function calls return -1 or NULL in case of any error and sets an error code errno is
set which is global variable and indicates an error occurred during any function call. You can find
various error codes defined in <error.h> header file.
So a C programmer can check the returned values and can take appropriate action depending on the return
value. As a good practice, developer should set errno to 0 at the time of initialization of the program. A
value of 0 indicates that there is no error in the program.
The errno, perror and strerror
The C programming language provides perror and strerror functions which can be used to display
the text message associated with errno.
The perror function displays the string you pass to it, followed by a colon, a space, and then the textual
representation of the current errno value.
The strerror function, which returns a pointer to the textual representation of the current errno value.
Let's try to simulate an error condition and try to open a file which does not exist. Here I'm using both the
functions to show the usage, but you can use one or more ways of printing your errors. Second important
point to note is that you should use stderr file stream to output all the errors. #include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ; int
m ain ()
{
FILE * pf;
int errnum ;
pf = fopen ("[Link]", "rb");

291
if (pf == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("Error printed by perror");
fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
}
else
{
fclose (pf);
}
return 0;
}
When the above code is compiled and executed, it produces the following result: Value of
errno: 2
Error printed by perror: No such file or directory Error
opening file: No such file or directory Divide by zero
errors
It is a common problem that at the time of dividing any number, programmers do not check if a divisor is
zero and finally it creates a runtime error.
The code below fixes this by checking if the divisor is zero before dividing: #include
<stdio.h>
#include <stdlib.h>
main()
{
int dividend = 20;
int divisor = 0; int
quotient;
if( divisor == 0){
fprintf(stderr, "Division by zero! Exiting...\n");
exit(-1);

292
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient ); exit(0);
}
When the above code is compiled and executed, it produces the following result: Division by
zero! Exiting...

 Program Exit Status


It is a common practice to exit with a value of EXIT_SUCCESS in case of programming is coming out after
a successful operation. Here, EXIT_SUCCESS is a macro and it is defined as [Link] you have an error
condition in your program and you are coming out then you should exit with a status EXIT_FAILURE
which is defined as -1.
So let's write above program as follows:
#include <stdio.h>
#include <stdlib.h>
m ain()
{
int dividend = 20;
int divisor = 5; int
quotient;
if( divisor == 0){
fprintf(stderr, "Division by zero! Exiting...\n");
exit(EXIT_FAILURE);
}
quotient = dividend / divisor;
fprintf(stderr, "Value of quotient : %d\n", quotient ); exit(EXIT_SUCCESS);
}
When the above code is compiled and executed, it produces the following result: Value
ofquotient : 4

293
16.6 SUMMARY

In this unit, we studied about structure, union, error handling and pointer to function. Structure
is a special data type. Multiple members of various data kinds can be held in a single structure.
Structure elements are stored in contiguous memory regions and may be accessed and retrieved
at any time. A member or field is a data object in a structure. A union is a data type that has
been specified by the user. It’s similar to the structure, except that all of its members begin at
the same memory position.

16.7 KEYWORDS

 Structure
 union
 pointer
 function pointer

16.8 QUESTIONS FOR SELF STUDY

1. Explain structure with its syntax.


2. How do you declare structure and access its elements in C ? explain.

3. Write a program to illustrate structure in C.

4. Explain union with its syntax.

5. Distinguish between structure and union with example.

6. Write a note on function pointer.

7. Write about error handling in C.

16.9 REFERENCES

 "Structured Programming Approach in C" by Forouzan and Gilberg


 "Programming with C" by E. Balagurusamy
 "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie
 "C Programming Absolute Beginner's Guide" by Greg Perry and Dean Miller

294
295

You might also like