0% found this document useful (0 votes)
46 views

C Programming

Uploaded by

hraikar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
46 views

C Programming

Uploaded by

hraikar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 300

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 Languahe, 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.

176
A computer or a system is operated by given a set of rules and instruction to perform
some task. These sat 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:

 Machine Languages
 Assembly Languages
 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.
Eg; 101100111 is considered as a machine language instruction.
Advantages of machine level language:

 Machine level languages are directly interacting with computer system.


 There is no requirement of language translators.
 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.
 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.
177
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 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.
178
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

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.

179
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 world.

The 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
particular block of statements. This structure also follows single entry and single exit concept.

180
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. Easier to Debug

181
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), or it might require linking with other object code files (e.g. libraries) to produce a
complete executable program.
182
The 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 codes
in 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

183
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 addresses.
There 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 shuld 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
184
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
185
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:
 Precision – the steps are precisely stated (defined).

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

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

 Input – the algorithm receives input.

 Output – the algorithm produces output.

 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

186
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
are two alternatives, true and false.
Decision
Used to join different flowline
On-page Connector
Used to connect flowchart portion on different
page.
Off-page Connector
Used to represent a group of statements
performing one processing task. (for function
Predefined Process/Function description)

187
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.

188
1.2 OVERVIEW OF THE C LANGUAGE, HISTORY AND FEATURES

C is a general-purpose, procedural programming language that has had a profound impact on the
field of computer science and software development. Here's an overview of the C language,
including its history and key features:

History: C was originally developed by Dennis Ritchie at Bell Labs in the early 1970s. It was
created as an evolution of the B programming language (a simpler predecessor) and was aimed at
implementing the UNIX operating system. Dennis Ritchie, along with Ken Thompson, also
contributed to the development of UNIX, which became one of the most influential operating
systems in history.

C was designed to be a low-level language, allowing direct access to the computer's hardware
and providing efficient memory manipulation. Its design and flexibility made it suitable for
systems programming, and its portability across different platforms played a significant role in
the widespread adoption of C.

In the late 1970s and early 1980s, C was standardized by the American National Standards
Institute (ANSI) and later by the International Organization for Standardization (ISO). The
standardized version, known as ANSI C or ISO C, brought uniformity to the language and
allowed it to be used across different systems and compilers.

Features:

1. Procedural Language: C follows a procedural programming paradigm, which means it


is organized around functions or procedures that manipulate data. It doesn't support
object-oriented features like classes and inheritance, unlike languages such as C++ or
Java.

189
2. Portability: C programs can be written once and run on multiple platforms with minimal
modifications, making it highly portable. This portability was crucial for the development
of UNIX and other cross-platform software.
3. Efficiency and Performance: C allows direct memory manipulation through pointers,
which gives developers fine-grained control over memory usage and performance
optimizations. This efficiency makes it a popular choice for systems programming,
embedded systems, and resource-constrained environments.
4. Static Typing: C is statically typed, which means variable types need to be explicitly
declared during the compilation phase. This feature helps catch type-related errors at
compile time, leading to more robust code.
5. Rich Standard Library: C comes with a standard library that provides essential
functions for tasks like input/output operations, string manipulation, memory allocation,
mathematical computations, and more. It makes C programs more concise and efficient.
6. Pointers: C is known for its powerful pointer arithmetic, allowing developers to work
directly with memory addresses and data structures. While powerful, pointers can also be
a source of bugs and require careful management.
7. Modularity and Reusability: C supports modularity through functions and user-defined
data types, promoting code reusability and maintainability.
8. Widespread Adoption: Due to its historical significance, efficiency, and portability, C
has been used in various domains, such as operating systems, embedded systems, game
development, system-level programming, and more.

Although C has stood the test of time and remains relevant, it is not without its challenges. Being
a low-level language, C exposes developers to potential pitfalls, such as buffer overflows and
undefined behavior, which require careful coding practices and testing.

Despite these challenges, C continues to be a vital language in the software industry, and many
modern languages and frameworks have been influenced by its design principles and syntax.
Learning C provides a solid foundation for understanding programming concepts and working
closer to the hardware.

190
1.3 SUMMARY

In this unit, you have studied the Overview of the C Language, History and Features

1.4 KEYWORDS

Overview , C Language, History , Features

1.6 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 characterisitcs.
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.7 REFERENCES

1. Programming In ANSI C by E Balagurusamy


2. The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
3. Expert C Programming: Deep C Secrets by Peter Van, Der Linden
4. Programming in C - Gottfried B.S., TMH
5. Programming in ANSI C - Balaguruswami, TMH
6. C The Complete Reference - H.Sohildt, TMH
7. Let us C - Y.Kanetkar, BPB Publications

191
8. A Structured Programming Approach using C – B.A. Forouzan& R.F. Gillberg,
THOMSON Indian Edition
9. Computer fundamentals and programming in C – PradipDey&Manas Ghosh, OXFORD
10. P. K. Sinha &PritiSinha , “Computer Fundamentals”, BPB Publications, 2007.
11. Dr. Anita Goel, Computer Fundamentals, Pearson Education, 2010.
UNIT-2

C LANGUAGE FUNDAMENTALS, CONSTANTS, VARIABLES AND DATA TYPES

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
 Describe the data types available in C
 Declare variables and constants
 List the rules to form variable name
 Know c tokens, identifiers
192
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. 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.2 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.

193
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 feature
it 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.3 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 of
the main function. The main ( ) function can be preceded by documentation, preprocessor
statements and global declarations.

194
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.

195
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 by
semicolon. Main ( ) executes user defined program statements, library functions and user defined
functions 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 the
beginning 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. These
two 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.

196
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.4 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

197
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.5 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");


198
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 entity.

For example, following are two different statements:

printf("Hello, World! \n");


return 0;

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

auto double int struct

break else long switch

case enum register typedef


Whitespace in C
char extern return union
A line containing only whitespace,
const float short unsigned
possibly with a comment, is known
as a blank line, and a continue for signed void C compiler totally
ignores it.
default goto sizeof volatile
Whitespace is the term used in C to
do if static while
describe blanks, tabs, newline
characters and comments.
Whitespace separates one part of a statement from another and enables the compiler to identify
where one element in a statement, such as int, ends and the next element begins. Therefore, in
the following statement:

int age;

There must be at least one whitespace character (usually a space) between int and age for the
compiler to be able to distinguish them. On the other hand, in the following statement:

fruit = apples + oranges; // get the total fruit

No whitespace characters are necessary between fruit and =, or between = and apples, although
you are free to include some if you wish for readability purpose.

200
2.6 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 discusses 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.
 In c, there are three types of data-primary, derived and user-defined
 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.
 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

201
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 sizes
and 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

202
Long 8 bytes or (4bytes for 32 bit -9223372036854775808 to
OS) 9223372036854775807

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 byte 1.2E-38 to 3.4E+38 6 decimal places

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

long double 10 byte 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 Memory Format


Type (bytes) 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';

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

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;

204
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 int.

You 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 or
a 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;
205
printf("value of f : %f \n", f);
return 0;
}

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'.
206
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 are
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.

207
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 days_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
readable.
The 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.

208
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. The variables and constants declared in global declaration can be accessed
by all user-defined functions and the main program. Where as the variables and constants
declared in local declaration part are local to the section.

2.11 KEYWORDS
I
dentifier, Variable, Keyword, int, float, const, extern, user defined function, char,global
declaration, local declaration,tokens

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.

209
2..13 REFERENCES
1. Programming In ANSI C by E Balagurusamy
2. The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
3. Expert C Programming: Deep C Secrets by Peter Van, Der Linden
4. Programming in C - Gottfried B.S., TMH
5. Programming in ANSI C - Balaguruswami, TMH
6. C The Complete Reference - H.Sohildt, TMH
7. Let us C - Y.Kanetkar, BPB Publications
8. A Structured Programming Approach using C – B.A. Forouzan& R.F. Gillberg,
THOMSON Indian Edition
9. Computer fundamentals and programming in C – PradipDey&Manas Ghosh, OXFORD
10. P. K. Sinha &PritiSinha , “Computer Fundamentals”, BPB Publications, 2007.
11. Dr. Anita Goel, Computer Fundamentals, Pearson Education, 2010.

210
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 operators precedence rule
 Explain Expression in C
 Describe size of () operator

211
 Elucidate library functions
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:

212
 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.

213
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 puts B's value into A. This destroys A's original value
3. 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

S.no 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.

214
6 Conditional (ternary) Conditional operators return one value if
operators condition is true and returns another value
is condition is false.
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
215
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,
216
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

217
*, / 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);
218
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 1.The 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

219
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 value.ie, 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

220
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

221
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:

222
/* 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 +,-,*, /, %.

223
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);
}

224
3.3.7 INCREMENT AND DECREMENT OPERATORS
In C, ++ and -- are called increment and decrement operators respectively. Both of these
operators are unary operators, i.e, used on single operand. ++ adds 1 to operand and -- subtracts 1
from 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.
225
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 according
to 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>

226
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

227
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>
228
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 predefined
rule 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)

229
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

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

< <= Relational less than/less than or equal to left-to-right


> >= Relational greater than/greater than or equal to

== != Relational is equal to/is not equal to left-to-right

& Bitwise AND left-to-right

^ Bitwise exclusive OR left-to-right

| Bitwise inclusive OR left-to-right

&& Logical AND left-to-right

|| Logical OR left-to-right

?: Ternary conditional right-to-left

= Assignment right-to-left
+= -= Addition/subtraction assignment
*= /= Multiplication/division assignment
%= &= Modulus/bitwise AND assignment
^= |= Bitwise exclusive/inclusive OR assignment
<<= >>= Bitwise shift left/right assignment

Comma (separate expressions) left-to-right


,

3.4 LIBRARY FUNCTIONS


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.

231
All C standard library functions 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 −

 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 functions.Built 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.

232
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

233
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:

234
(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 C.The 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, decrement, bitwise,
logical, special operator, comma operator, library functions, math.h, string.h, implicit type
conversion, explicit type conversion
235
3.8 QUESTIONS FOR SELF STUDY

1. Explain assignment statement with example.


2. Explain different types of operators supported by C.
3. Explain the operators 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

1. Programming In ANSI C by E Balagurusamy


2. The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
3. Expert C Programming: Deep C Secrets by Peter Van, Der Linden
4. Programming in C - Gottfried B.S., TMH
5. Programming in ANSI C - Balaguruswami, TMH
6. C The Complete Reference - H.Sohildt, TMH
7. Let us C - Y.Kanetkar, BPB Publications
8. A Structured Programming Approach using C – B.A. Forouzan& R.F. Gillberg,
THOMSON Indian Edition
9. Computer fundamentals and programming in C – PradipDey&Manas Ghosh, OXFORD

236
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
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

237
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.

238
Fig 9.1: Shows Flowchart of goto statement

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;
239
}

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: 19

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.

240
Fig 9.2: Shows flow chart of If statement

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;
241
printf (“ enter a number:”\n);
scanf(“%d”,&x);
If (x>20)
Printf(“ number is greater”);
}
Output:

Enter a number:22

Number is greater

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 9.3: Shows flowchart of If-else statement

Syntax:
if (condition)
242
{
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

243
The value is less than 20

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
on 1
False

True

Condit
ion 2 False

True

Statement block2

244
Next statement
Fig 9.4 : Shows flowchart of Nesting of if statements

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.
245
If a case match is NOT found, then the default statement is executed, and the control goes out of
the switch block.

Fig 9.5: Shows flowchart of switch statement

Syntax:
switch( choice )
{
case 1:
statement 1;
break;
246
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;

247
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 condition is satisfied.

Three types of loops in C are:


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

While loop
Syntax:-
248
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 used.Initialy
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 will get
executed repeatedly.

Do while loop
This (do while loop) statement is also used for looping. The body of this loop may
249
contain single statement or block of statement. The syntax for writing this statement is:
Syntax:-
Do

Statement;

while(condition);

Example:
#include <stdio.h>
int main()
{
int j=0;
do
{
printf("Value of variable j is: %d\n", j);
j++;
}while (j<=3);
return 0;
}

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 thecondition
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 forfirst time. It
means do while loop always executes at least once.
250
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 –).

251
Fig 9.6: Shows flowchart of For loop

Syntax:-
for(exp1;exp2;exp3)

Statement;
}

or

for(initialized counter; test counter; update counter)

Statement;

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

Output:
1
2
3

253
Here exp1 is an initialization expression, exp2 is test expression or condition and exp3 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 updation part executed only when afterbody of the loop is executed.

4.8 BREAK AND CONTINUE STATEMENT

Break statement(break)
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 cause immediate exit from that loop in whichit 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 ifstatement.
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;
}

101
Output:

value of variable num is: 0


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

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 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;

102
}

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, counter, continue


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

1. Programming in ANSI C by E Balagurusamy


2. The C Programming Language (Ansi C Version) by Brian W. Kernighan,
Dennis M. Ritchie
3. Expert C Programming: Deep C Secrets by Peter Van, Der Linden
4. Computer concepts and programming in c by M.A.Jayaram and D.S.Rajendra Prasad
5. http://www.cprogrammingexpert.com/C/Tutorial

103
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

104
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 bellow illustrate how function can be used in programming

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

105
#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 definitation
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 analysing 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.

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

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

 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 again.

107
 Frequency Table – The table shows the number of pieces of data that falls within the
given interval.

 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.

 Stem and Leaf Plot – In the stem and leaf plot, the data are organised 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.

108
 Box and Whisker Plot – The plot diagram summarises the data by dividing into four
parts. Box and whisker show the range (spread) and the middle ( median) of the data.

 General Rules for Graphical Representation of Data

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

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

 Graphical Representation in Maths

109
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:

 Time Series Graphs – Example: Line Graph


 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.

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

o Histogram

110
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.

111
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:

o Functions can be executed as many times as necessary from different points in a


program.
o 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.
o But the real reason that you need functions is to modularize your program into easily
manageable chunks.
o 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.
o 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.
o 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 C standard library functions 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

112
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 functions.Built functions in stdio.h

For example:
main()
The execution of every C program starts from this main.
printf()
prinf() is 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(){

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

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.

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.
 Example of user defined function
/*Program to demonstrate the working of user defined function*/

114
#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 call
printf("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.
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.

115
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 to
define 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 to
a 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 with
arguments, 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);
}
}
exit(EXIT_SUCCESS);
}

116
/*
* Function pmax.
* Returns: void
* Prints larger of its two arguments.
*/
void
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
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

117
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 the
function)”,x);
}
change(x)
int x;
{
x=x+3;
printf(“\nx=%d(from the function, after being
modified)”,x);
return;
}

118
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 main
from 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.

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

119
}
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
auto keyword. 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.
 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

120
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 to
as 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 just say that when you need it, you really do need it, and since it doesn't cost much to
put into a language, as you would expect, C supports recursion.

121
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 to
find 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 declared
in stdio.h.

122
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 */
} else{
printf("result is %d\n", val);
}

123
}
exit(EXIT_SUCCESS);
}

int
expr(void){
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(void){
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;

124
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:
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;

125
}
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


Every variable and function in C programming has 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:

 automatic
 external
 static
 register

 Automatic storage class


Keyword for automatic variable
auto
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 are rarely
used.

 External storage class

126
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
only.If 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 register in processor and if it
couldn't store the variable in register, it will automatically store it in memory.

 Static Storage Class


The value of static variable persists until the end of the program. A variable can be declared
static using keyword: static.
For example:
static int i;
Here, i is a static variable.

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

127
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?
8. Write a program for
a) Program to reverse number using functions

b) Program to find power of number using recursion

c) Program to find highest common factor using recursion

5.10 Reference
1. Programming In ANSI C by E Balagurusamy
2. The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
3. Expert C Programming: Deep C Secrets by Peter Van, Der Linden

128
Unit - 6

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 Pointers & Array
6.8 Summary
6.9 Key words
6.10 Questions
6.11 References

6.0 Objectives

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

 Understand the concepts of Array

129
 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.

 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 th at illustrates
the 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.

130
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.

/* 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

131
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
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)

132
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;
{
*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

133
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>

 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

134
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]

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:

135
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, *struct.pointer

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:

136
PRINT, *45

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()

137
IDL prints:
A EQ B: 1
A NE B: 0
A EQ C: 0
C EQ NULL: 1
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 language. It'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 memory.Unfortunately, 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.

138
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 pointers.Consider 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 )
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.

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?

139
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 arr.The idea is to have arr + i point
to i elements after arr regardless of what type of element the array holds.Suppose 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).

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 size.You can find out the data type's size with
the sizeof() operator.

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 type.Here'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 ]

140
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 ) {

141
// code here
}
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.

142
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 ] ;

// 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.

143
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.

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.

144
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
when p2 and p1 contain invalid addresses (because they contain some address).

145
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 visualized
with a suitable examples. In subsequent stages we have discussed about the role of & and *
operators. In the later stages we had list out various arithmetic operations which can be
performed using pointer. In the last section of the unit we have seen how exactly arrays can
be handled using pointer.

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?
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 Reference
1. "Common Pointer Pitfalls" by Dave Marshall
2. C Programming: A Modern Approach by K.N. King
3. C Programming in 12 Easy Lessons by Greg Perry
4. C for Dummies Vol. II by Dan Gookin

146
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

147
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
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

148
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.

#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

149
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.

#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:

150
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
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.

151
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;

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

answer = val1 + val2;


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

152
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

strlen() Calculates the length of string


strcpy() Copies a string to another string
strcat() Concatenates(joins) two strings

153
Function Work Of Function

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.
printf("Name: ");
puts(name); //Function to display string.

154
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, gets(), puts(), string.h

7.9 Questions
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 Reference

1. Programming In ANSI C by E Balagurusamy


2. The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
3. Expert C Programming: Deep C Secrets by Peter Van, Der Linden

155
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

156
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 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;
.
.

157
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
{
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

158
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: p2.salary

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",&d1.feet); //input of feet structure for d1
printf("Enter inch: ");
scanf("%f",&d1.inch); //input of inch structure for d1
printf("2nd distance\n");
printf("Enter feet: ");
scanf("%d",&d2.feet); //input of feet for structure variable d2
printf("Enter inch: ");
scanf("%f",&d2.inch); //input of inch for structure variable d2
sum.feet=d1.feet+d2.feet;
sum.inch=d1.inch+d2.inch;
if (sum.inch>12){ //If inch is greater than 12, changing it to feet.
++sum.feet;
sum.inch=sum.inch-12;
}
printf("Sum of distances=%d\'-%.1f\"",sum.feet,sum.inch); //printing sum of distance d1 and d2
return 0;
}

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:

159
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
member.Structures 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
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.

160
8.5 Structure and function

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


 Passing by value (passing actual value as argument)
 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",&s1.name);
printf("Enter roll number:");
scanf("%d",&s1.roll);
Display(s1); //passing structure variable s1 as argument
return 0;
}
void Display(struct student stu){
printf("Output\nName: %s",stu.name);
printf("\nRoll: %d",stu.roll);
}
Output
Enter student's name: Kevin Amla
Enter roll number: 149
Output
Name: Kevin Amla
Roll: 149

161
 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",&dist1.feet);
printf("Enter inch: ");
scanf("%f",&dist1.inch);
printf("Second distance\n");
printf("Enter feet: ");
scanf("%d",&dist2.feet);
printf("Enter inch: ");
scanf("%f",&dist2.inch);
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\"",dist3.feet, dist3.inch);


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=d1.feet+d2.feet;
d3->inch=d1.inch+d2.inch;
if (d3->inch>=12) {
//if inch is greater or equal to 12, converting it to feet.

162
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.

163
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,
 Passing the members of the structures as an argument.
 Passing the entire structure as an argument.
 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;
};

164
union car c1, c2, *c3;

In both cases union variables c1, c2 and union pointer variable c3 of type union car is
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
c1.price. 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

165
There is difference of memory allocation between union and structure as suggested in above
example. The amount of memory required to store a structure variables is the sum of memory
size of all members.

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",&u.name);
printf("Enter salary: \n");
scanf("%f",&u.salary);
printf("Displaying\nName :%s\n",u.name);
printf("Salary: %.1f",u.salary);
return 0;
}
Output
Enter name
Hillary
Enter salary
1234.23
Displaying
Name: f%Bary
Salary: 1234.2

166
Note: You may get different garbage value of name.

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

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];

167
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);
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].age);
}

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. */

168
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 pass a pointer to that structure. This is just like passing a pointer to an int type argument
whose value we wish to change.

If 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 it.

When 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;

169
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));
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

170
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 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 */

171
/* 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 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.

172
 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 (account.balance) (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, 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 etc.

173
Like 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
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?

174
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
1. C Programming: A Modern Approach by K.N. King
2. C Programming in 12 Easy Lessons by Greg Perry
3. C for Dummies Vol. II by Dan Gookin

175
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
 Getchar() and Putchar() function
 Gets() and puts() function
 File handling in C

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

176
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 program
reading 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:

177
 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.

178
 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 Studytonight

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>

179
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 num1 is: 15.500000

180
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

181
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.

182
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>

183
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);

184
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;

185
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:

186
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

187
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:

188
Enter a string: Studytonight

Studytonight

 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

189
The string is: abcdefghij
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.

190
 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

191
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()

192
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

193
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
r+ up 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
a+ 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 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”.

Example of Opening a File

194
// 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("filename.txt", "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("filename.txt", "w");

195
Example of Opening a File

// C Program to create a file


#include <stdio.h>
#include <stdlib.h>
int main()
{
// file pointer
FILE* fptr;
// creating file using fopen() access mode "w"
fptr = fopen("file.txt", "w");
// checking if the file is created
if (fptr == NULL) {
printf("The file is not opened. The program will "
"exit now");
exit(0);
}
else {
printf("The file is created Successfully.");
}
return 0;
}

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:

Function Description

196
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(“fileName.txt”, “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:

Function Description

197
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(“fileName.txt”, “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(“fileName.txt”, “w”);

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

fclose(fptr);

198
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

I/O, Input, Output, printf(), scanf(), getchar() and putchar().

9.10 QUESTIONS

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

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

199
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.

200
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 with

the enum keyword, and is an ordered collection of names that represent integer values.

Unless 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:

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

201
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;

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.

202
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:

1. struct student s1;

203
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;
int main()

204
{
stud s1;
printf("Enter the details of student s1: ");
printf("\nEnter the name of the student:");
scanf("%s",&s1.name);
printf("\nEnter the age of student:");
scanf("%d",&s1.age);
printf("\n Name of the student is : %s", s1.name);
printf("\n Age of the student is : %d", s1.age);
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
variable of type int* by simply using the 'ptr' variable as shown in the below statement:

205
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

0123456

206
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, TUE
gets 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

207
0123456

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.

208
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 is
an 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

209
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:

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);

210
cur_cont = cont1;
printf("Value of hearts is = %d \n", cur_cont);
return 0;
}
Output:

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, and
South 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){

211
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:

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
};

212
int main() {
int myExample = ROTATE | SAVE;
printf("%d", myExample);
return 0;
}
Output:

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:

213
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:

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:

214
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

215
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.

10.6 KEYWORDS

Typedef, Enum, Macro and Struct.

10.7 QUESTIONS

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

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

UNIT 11: BITWISE OPERATORS

Structure:

11.0 Objectives
11.1 Introduction
11.2 Bitwise operation
11.3 Bitwise operators
11.4 Summary

216
11.5 Keywords
11.6 Questions
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 (&)


· Bitwise OR operator (|)
· Bitwise exclusive OR operator (^)
· Binary One’s Complement or Bitwise NOT operator (~)
· Bitwise Left shift operator (<<)
· Bitwise Right shift operator (>>)

217
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 one
of 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
218
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.

219
Arithmetic logic unit, part of a computer CPU, is where bitwise operators used to perform
mathematical operations.

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

220
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 OR exists in either operand. So, if variables without using a
(XOR) one of the operands is TRUE, third temporary variable
the result is TRUE. If neither To find specific types of
operand is TRUE, the result is numbers (e.g., odd) in a
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.

221
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

222
Operator Name Type Action

<< Left shift Binary Shifts first operand a number


of bits to the left as specified in
the second operand, shifting in
zeros from the right

>> Right shift Binary Shifts first operand a number


of bits to the right as specified
in the second operand, and
discards displaced bits

>>> Zero-fill right shift Binary Shifts first operand a number


of 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 exfiltration.
The 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
 converting text cases, such as uppercase to lowercase or lowercase to uppercase.

223
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.

224
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.

225
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.

226
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)

227
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, bitwise NOT, bitwise left shift
and bitwise right shift.

11.6 QUESTIONS

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

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

228
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:

 Representation of a polynomial using linked lists.


 Addition of two polynomials using linked lists.
 Construction of a dictionary using linked lists
 Representation of a sparse matrix using linked lists
 Multiplication of sparse matrix 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

229
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, free). 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.

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 pool
of memory. This is enough as an introduction. The list of dynamic memory management
functions.

230
Now, Let us see the definition, syntax and some examples of each library functions below.

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 functions
like malloc(), calloc(), realloc(), and free() to allocate and deallocate a memory block during
run-time.
It is considered as a very important topic because almost every Data Structure (such as
Linked Lists, Stack, Queue, Trees, etc.) is associated with the concept of Dynamic Memory
Allocation in C.

To 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 one
is 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

231
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 Allocation.

Now, let us see some differences in Static Memory Allocation and Dynamic Memory
Allocation.

Static Memory Allocation Dynamic Memory Allocation

Constant (Invariable) memory is reserved


Dynamic (Variable) memory is reserved at run-
at compile-time of our program that can't be
time of our program that can be modified.
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 We can allocate and deallocate a memory block
during run-time. during run-time.

Heap space is used in Dynamic Memory


Stack space is used in Static Memory Allocation.
Allocation.

It doesn't provide reusability of memory, while the It provides reusability of memory, while the
program is running. So, it is less efficient. program is running. So, it is more efficient.

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 program.

There are further four components in which our system's memory is divided:

232
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
application.
o We can't allocate or deallocate memory during execution.

Heap

233
 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;
}

234
}
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.

235
 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 use
Heap Memory in which we can vary the size of a variable or Data Structure (such as an
Array) 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.

236
 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 :

237
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));

238
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));
}
}

239
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 example
output.
 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:

240
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

241
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()

242
// 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)

Explanation :

243
 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() function.

Now, 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().

244
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 allocated
using 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 :

245
// 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));
}

printf("\n");

// printing array arr2 using pointer


for (int i = 0; i < 2 * n; i++) {
printf("%d ", *(arr4 + i));
}
}
}

246
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()

#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 {

247
*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:

7
15078952
Memory freed using realloc()!

(output garbage values are compiler dependent)

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.

248
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));

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.7SUMMARY

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(), free() and
realloc().

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.

249
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

250
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
 Explain doubly linked list
 Distinguish between singly linked list and doubly 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
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 structure.For
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 address
of 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:
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.
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):
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 a
node for single linked list.
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 (i.e.start 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;
}
}
}
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;
}
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();
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;
 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);
}
}
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...
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)).
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
{
int data;
struct slinklist *next;
};
typedef struct slinklist node;
node *start = NULL;
int menu()
{
int ch;
clrscr();
printf("\n 1.Create a list ");
printf("\n--------------------------");
printf("\n 2.Insert a node at beginning ");
printf("\n 3.Insert a node at end");
printf("\n 4.Insert a node at middle");
printf("\n--------------------------");
printf("\n 5.Delete a node from beginning");
printf("\n 6.Delete a node from Last");
printf("\n 7.Delete a node from Middle");
printf("\n--------------------------");
printf("\n 8.Traverse the list (Left to Right)");
printf("\n 9.Traverse 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;
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;
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;
}
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
{
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()
{
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;
}
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 ++;
}
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..");
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 :
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().
 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;
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;
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.
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.
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.
 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.
Advantages of Linked Lists
● They are a dynamic in nature which allocates the memory when required.
● Insertion and deletion operations can be easily implemented.
● Size of linked list can grow or shrink in size during the execution of a program.
● In Linked Lists we don't need to know the size in advance
● Stacks and queues can be easily implemented using linked list.
Applications of Linked Lists
● Linked lists are used to implement several other common abstract data types (data structures),
including lists , stacks , queues , associative arrays , and S-expressions .
● Linked lists let you insert elements at the beginning and end of the list.
13.6 KEYWORDS
Linked list, singly linked list, doubly linked list, circular linked list, insertion, deletion,creation,
traverse

13.7 QUESTIONS FOR SELF STUDY

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.

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

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
UNIT 14

STACKS AND QUEUES

Structure:

14.0 Objectives

14.1 Introduction

14.2 Stack

14.3 QUEUE

14.4Implementation 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.
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 datastracture 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) lists.
As 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.
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.

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.
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 full.IF
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.
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.

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 deletion.

Like 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.
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.

1. Insert 11.

2. Insert 22

3. insert 33

4. Delete 11

5. Delete 22
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.
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:");
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:
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 ");
}
}
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;
}
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

# include <conio.h>
# include <stdlib.h>
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;
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()
{
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
# 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..");
}
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;
}
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 list.

The 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. Where as queue has two pointers front and rear.

In stack, insertion and deletion operations are done from only one end. In queue , insertion is
from rear end and deletion is from front end.

During insertion operation, we check for overflow condition and during deletion operation, the
data structures are checked for underflow condition.

After performing desired operation, the pointers are properly set.

14.7 KEYWORDS

Stack, queue, top, rear, front, underflow, overflow


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

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
UNIT 15

RECURSION

Structure:

15.0 Objectives

15.1 Introduction

15.2 Recursion

15.3 Summary

15.4 Keywords

15.5 Questions for self study

15.6 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.


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 */
… .. …
}
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
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;
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 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.
When writing recursive functions, you must have a exit 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.
15.4 KEYWORDS
Recursion, exit condition

15.5 QUESTIONS 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.6 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
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.
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
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 stud1.name. Similarly, stud1’s rollno and stud1’s totalmark can be accessed by
writing stud1.rollno and stud1.totalmark 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
{
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”, stud1.rollno, stud1.name,
stud1.totalmark);
printf(“\n\n Roll number:%d\n Name:%s\n Total Marks:%f”, stud2.rollno, stud2.name,
stud2.totalmark);
printf(“\n\n Roll number:%d\n Name:%s\n Total Marks:%f”, stud3.rollno, stud3.name,
stud3.totalmark);
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:
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()
{
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
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.
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
{
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).
Difference between Structure and Union

16.4 FUNCTION POINTERS

 C Pointer is a variable that stores/points the address of the 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.
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;
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()
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;
}
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 ("unexist.txt", "rb");
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);
}
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
0.If 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
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. The union stores a collection of items of
diverse data kinds in the same memory region. A user can create a union with numerous
members, but only one member can hold a value at any given moment. The total storage space
required by the union’s biggest data member is equal to the storage space allotted for the union
variable.
16.7 KEYWORDS
Structure, union, pointer, function pointer, error handling,struct,union
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.8 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

You might also like