Você está na página 1de 97

FUNDAMENTALS OF C

PROGRAMMING

003-00002 Page-1

Copyright CoreEL Technologies (I) Pvt. Ltd.


INDEX
INDEX __________________________________________________________________________ 2
Chapter 1 _______________________________________________________________________ 7
INTRODUCTION TO PROGRAMMING _________________________________________________ 7
1.1 Program........................................................................................................................................... 7
1.2 Software .......................................................................................................................................... 7
1.3 Types of languages used to write software ....................................................................................... 7
1.3.1 Machine language ........................................................................................................................................7
1.3.2 Assembly language .......................................................................................................................................7
1.3.3 High level languages .....................................................................................................................................8
1.4 Translators....................................................................................................................................... 8
1.4.1 Assembler .........................................................................................................................................................8
1.4.2 Compiler............................................................................................................................................................9
1.4.3 Interpreter ....................................................................................................................................................9
1.5 THE ASCII CODE ............................................................................................................................. 10
Chapter 2 ______________________________________________________________________ 11
INTRODUCTION TO C PROGRAMMING_______________________________________________ 11
Introduction ........................................................................................................................................ 11
2.1 History .............................................................................................................................................................11
2.2 Features of C ...................................................................................................................................................11
2.3 Applications of C .............................................................................................................................................11
2.4 Typical C / C++ development environment ....................................................................................................12
2.5 The C Preprocessor .........................................................................................................................................14
2.6 Compiler .........................................................................................................................................................14
2.7 Assembler .......................................................................................................................................................14
2.8 Linker ..............................................................................................................................................................14
2.9 Loader .............................................................................................................................................................14
2.10 The C Program structure ............................................................................................................................15

Chapter 3 ______________________________________________________________________ 18
BASIC PROGRAM ELEMENTS IN C ___________________________________________________ 18
Introduction ........................................................................................................................................ 18
3. 1 Identifiers ..................................................................................................................................... 18
3.2 Keywords....................................................................................................................................... 18
3.2.2 Variable and Datatypes ...................................................................................................................... 18
3.3 Constants....................................................................................................................................... 20
3.3.1 Integer constants ............................................................................................................................... 21
3.3.2 Character constants ........................................................................................................................... 21
3.3.3 Floating constants .............................................................................................................................. 21
3.4 String literals.................................................................................................................................. 21
3.5 Operators ...................................................................................................................................... 21

003-00002 Page-2

Copyright CoreEL Technologies (I) Pvt. Ltd.


3.5.1 Operators available in C ..................................................................................................................... 21
3.5.1.1 Assignment Operator = ..........................................................................................................................22
3.5.1.2 Arithmetic Operator ...............................................................................................................................22
3.5.1.3 Relational Operator................................................................................................................................23
3.5.1.4 Logical Operator !, &&, || ......................................................................................................................24
3.5.1.5 Increment and Decrement Operators ++ -- ........................................................................................25
3.5.1.6 Bitwise Operators (&, |, ^, ~, <<, >> ) ...........................................................................................................25
3.5.1.7 Conditional Operator ( ?: ) ............................................................................................................................28
3.5.1.6 Comma Operator ( , ) ............................................................................................................................29
3.5.1.7 sizeof () Operator ...................................................................................................................................29
3.5.1.8 Type cast Operator.................................................................................................................................29
3.5.2 Precedence and Associativity...................................................................................................... 29
3.6 Standard input output functions in C ........................................................................................ 30
3.7 Formatted I/O Functions – Printf and Scanf ............................................................................... 31
3.7.1 printf () ........................................................................................................................................ 31
3.7.2 scanf().......................................................................................................................................... 31

GOOD TO KNOW ________________________________________________________________ 32


Chapter 4 ______________________________________________________________________ 33
STATEMENTS IN C _______________________________________________________________ 33
Introduction ........................................................................................................................................ 33
4.1 Selection statements ................................................................................................................ 33
4.1.1 if statement ................................................................................................................................. 33
4.1.2 Switch statement ............................................................................................................................... 35
4.2 Iteration statements ................................................................................................................ 36
4.2.1 while statement ................................................................................................................................. 37
4.2.2 The do while statement ..................................................................................................................... 37
4.2.3 for statement .................................................................................................................................... 38
Infinite loops ............................................................................................................................................... 39
4.3 Jump statements............................................................................................................................ 40
4.3.1 The break statement .......................................................................................................................... 40
4.3.2 The continue statement ..................................................................................................................... 41
4.3.3 The goto statement............................................................................................................................ 42
4.3.4 The return statement ......................................................................................................................... 42

GOOD TO KNOW ________________________________________________________________ 43


Character manipulation functions .............................................................................................................. 43

Chapter 5 ______________________________________________________________________ 44
FUNCTIONS IN C _________________________________________________________________ 44
Introduction ........................................................................................................................................ 44

003-00002 Page-3

Copyright CoreEL Technologies (I) Pvt. Ltd.


5.1 What are Functions? ...................................................................................................................... 44
5.2 Advantages of Functions ................................................................................................................ 44
5.3 Parts of Function ............................................................................................................................ 44
5.3.1 Function Definition ..................................................................................................................... 45
5.3.2 Function Declaration .......................................................................................................................... 45
5.3.3 Function Call....................................................................................................................................... 45
5.4 Passing values to Functions ............................................................................................................ 46
5.4.1 Passing Arguments by Value .............................................................................................................. 46
5.4.2 Passing Arguments by Address .......................................................................................................... 46
5.5 Stack Frames ................................................................................................................................. 48
Chapter 6 ______________________________________________________________________ 49
STORAGE CLASSES IN C ___________________________________________________________ 49
Introduction ........................................................................................................................................ 49
6.1 Storage class specifiers ................................................................................................................... 49
6.1.1 Auto / Automatic variables ................................................................................................................ 49
6.1.2 Register variables ............................................................................................................................... 49
6.1.4 Static Variables................................................................................................................................... 52
6.2 Storage classes for functions .......................................................................................................... 54
Chapter 7 ______________________________________________________________________ 55
THE PREPROCESSOR DIRECTIVES IN C ________________________________________________ 55
Introduction ........................................................................................................................................ 55
7.1 Preprocessor Directives .................................................................................................................. 55
7.1.1 Macros ............................................................................................................................................... 55
7.1.1.1 Macro without parameters...........................................................................................................................56
7.1.1.2 Macro without parameters...........................................................................................................................57
7.1.1.3 Macros versus Functions................................................................................................................. 58
7.1.1.4 Scope of Macro Names (#undef) .................................................................................................... 58

Chapter 8 ______________________________________________________________________ 59
Arrays in C _____________________________________________________________________ 59
Introduction ........................................................................................................................................ 59
8.1 Overview of arrays ......................................................................................................................... 59
8.2 Declaration of arrays ...................................................................................................................... 59
8.3 Memory layout and accessing the array elements ........................................................................... 59
8.4 Initialization of arrays .................................................................................................................... 61
8.5 Bounds Checking ............................................................................................................................ 61

003-00002 Page-4

Copyright CoreEL Technologies (I) Pvt. Ltd.


8.6 Passing array as argument to function ............................................................................................ 61
8.7 Searching Algorithm ....................................................................................................................... 62
8.7.1 Linear Search ...................................................................................................................................... 62
8.7.2 Binary Search ..................................................................................................................................... 63
8.8 Sorting ........................................................................................................................................... 64
8.8.1 Bubble sort ......................................................................................................................................... 65
8.8.2 Selection Sort ..................................................................................................................................... 66

Chapter 9 ______________________________________________________________________ 68
Strings – Character arrays _________________________________________________________ 68
Introduction ........................................................................................................................................ 68
9.1 Initializing Strings ........................................................................................................................... 68
9.2 String Library Functions .................................................................................................................. 69
9.2.1 Strcpy and Strncpy ............................................................................................................................. 69
9.2.3 Strcmp ................................................................................................................................................ 70
9.2.4 Strlen .................................................................................................................................................. 71
9.2.5 Strcat .................................................................................................................................................. 71
9.3 String input and output .................................................................................................................. 73
9.3.1 Character level I/O ............................................................................................................................. 73
Output: ....................................................................................................................................................... 73
9.3.2 Fgets ................................................................................................................................................... 74
Output: .................................................................................................................................................... 74
9.3.3. Sscanf ................................................................................................................................................ 74
9.3.4 sprintf ................................................................................................................................................. 75

GOOD TO KNOW ________________________________________________________________ 76


Chapter 10 _____________________________________________________________________ 77
POINTERS IN C __________________________________________________________________ 77
Introduction ........................................................................................................................................ 77
10.1 Pointer declaration ...................................................................................................................... 77
10.2 Reference operator (&) ................................................................................................................ 77
10.3 Dereference operator (*) .............................................................................................................. 77
Declaring and assigning values to pointers. ......................................................................................................78
10.4 Permissible pointer operations ..................................................................................................... 78
10.4.1 Pointer Arithmetic........................................................................................................................... 78
10.5 Non Permissible pointer operations .............................................................................................. 79
10.6 Pointer and arrays ........................................................................................................................ 79

003-00002 Page-5

Copyright CoreEL Technologies (I) Pvt. Ltd.


10.7 Disadvantages of pointers ............................................................................................................ 80
Chapter 11 _____________________________________________________________________ 81
STRUCTURES ___________________________________________________________________ 81
Introduction ........................................................................................................................................ 81
11.1 Syntax of a structure ................................................................................................................ 81
11.2 Initializing a structure variable .................................................................................................. 82
11.3 Accessing structure elements ................................................................................................... 82
11.4 Operations on Structures ............................................................................................................. 83
11.4.1 Assigning one structure variable to another................................................................................... 83
11.4.2 Comparison of structure variables................................................................................................... 83

Chapter 12 _____________________________________________________________________ 84
Advanced STRUCTURES, UNIONS and enumerated data types____________________________ 84
Introduction ........................................................................................................................................ 84
12.1 Arrays of Structure ....................................................................................................................... 84
12.2 Nested structures ......................................................................................................................... 85
12.3 Structure pointers ........................................................................................................................ 85
12.4 Self-referential structures ............................................................................................................. 86
12.5 Passing structures to Functions .................................................................................................... 87
12.5.1 Passing individual structure elements to function .......................................................................... 87
12.5.2 Passing entire structure to function ................................................................................................ 87
12.6 Memory saving structures using C Bit fields .................................................................................. 88
12.7 Structure padding ........................................................................................................................ 89
12.8 Unions ......................................................................................................................................... 92
12.8.1 Syntax of union ................................................................................................................................ 92
12.9 Enumerated data types ................................................................................................................ 92
12.9.1 Syntax of enum ................................................................................................................................ 93
12.9.2 Uses of enumerated data types ....................................................................................................... 93
Good to know...................................................................................................................................... 95
Typedef ....................................................................................................................................................... 95

REFERENCES ____________________________________________________________________ 97

003-00002 Page-6

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 1

INTRODUCTION TO PROGRAMMING

This chapter gives a brief introduction about computer programs. Also, the different types of programming
languages and language translators are illustrated here.

1.1 Program

A program is a sequence of instructions that a computer can interpret and execute. It is developed using high
level computer languages.

1.2 Software

Software is computer program or a set of programs, which provides the instructions that enable the computer
hardware to work. Two main types of software are system software (operating systems), which control the
workings of the computer, and applications, such as word processing programs, spreadsheets, and databases.

1.3 Types of languages used to write software

 Machine Language
 Assembly Language
 High Level Language

1.3.1 Machine language

 A set of machine instructions written using binary code that a processor can understand.
 A processor interprets and translates machine instructions into HW signals.

Example: The instruction to add 2 numbers stored in registers A and B might look like this:

00000011 11000011
Problems:

 Binary representation of instructions and data are not easily generated, manipulated, or understood by
humans.
 The languages are machine dependent.
 Writing program in machine language requires the knowledge of the internals of the computer.

1.3.2 Assembly language

 A symbolic form of machine language


 Allows alphabetic mnemonics for operation codes and storage locations
 There exists one-to-one correspondence between assembly instructions and machine instructions.

003-00002 Page-7

Copyright CoreEL Technologies (I) Pvt. Ltd.


Example:
M. L. Instruction: 00000011 11000011

Equivalent A.L. Instruction: ADD A, B


Advantages

 Ease: Because of the use of mnemonics it is more understandable and easy to remember than a
machine language code.
 Speed: programs in AL run faster than those written in high level languages.
 Compactness: routines include only code that programmers want to include.
 Versatility: anything that can be done with a computer can be done with AL

1.3.3 High level languages

 Use English like codes that are easier to remember.


 Generally machine (architecture) independent.
 Provides language constructs for specifying and manipulating complex data structures.
 Supports a variety of programming styles (i.e. linear, object oriented)
 Hides the low level architectural details from the programmer i. e. dose not normally require the
knowledge of the internal architecture of the computers.

Example:

C, C++, Pascal, COBOL, Java

1.4 Translators

 Used to translate other forms of languages into machine language.


 Three types of commonly used translators are
o Assembler
o Compiler
o Interpreter

1.4.1 Assembler

 A program that converts assembly code into machine code


 After translation creates object module i.e. the machine language representation of a program.

003-00002 Page-8

Copyright CoreEL Technologies (I) Pvt. Ltd.


The working of an assembler is depicted in Figure 1.2.

Figure 1.2 Working of assembler


1.4.2 Compiler

 Translates high-level code into machine language code.


 Produces object code (Translated Instructions ready for computer) by translating the source code
(high-level language instruction).
 Object code is stored in the machine and can be used repeatedly.

1.4.3 Interpreter

 Like compiler; translates a high level language into machine language.


 Unlike compiler; translates the program at the time of executing the program instruction by instruction.
 The translated code is not stored permanently in computer’s memory; hence before each execution
interpretation becomes necessary.
 As object code is not stored in the computer, execution of the program becomes slower because of the
need for interpretation before each execution.
 Normally it is easier to design an interpreter than a compiler.

Figure 1.4 Working of interpreter

003-00002 Page-9

Copyright CoreEL Technologies (I) Pvt. Ltd.


1.5 THE ASCII CODE

ASCII stands for American Standard Code for Information Interchange. Computers can only understand
numbers, so an ASCII code is the numerical representation of a character such as 'a' or '@' or an action of
some sort. A few examples are given in Table 1.1.

 Standard ASCII is a 7-bit code (127 characters)

Extended ASCII (IBM ASCII), an 8-bit code, is also very popular

BIT ASCII CODE CHARACTER


PATTERN

01000001 65 A

01100001 97 a

00110001 49 1

00101011 43 +

Table 1.1 ASCII character sets- Example

So in the above example, ‘A’ is a character constant; in the ASCII character set its value is 65, the internal
representation of the character A.

003-00002 Page-10

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 2

INTRODUCTION TO C PROGRAMMING

Introduction

C is a general purpose programming language. C can be used to perform anything from writing small
programs for personal amusement to writing complex applications. C, on the other hand, was designed to
give access to any level of the machine code and because of this it is perhaps the most flexible of all high
level languages. A brief overview of C programming language is given in this chapter.

2.1 History
 The C programming language was designed by Dennis Ritchie at Bell Laboratories in the early 1970s.
 influenced by
o ALGOL 60 (1960),
o CPL (Cambridge, 1963)
o BCPL (Martin Richard, 1967)
o B (Ken Thompson, 1970)
 Traditionally used for systems programming, though this may be changing in favor of C++
 Traditional C
o Referred to as K&R
 Standardized in 1989 by ANSI (American National Standards Institute) known as ANSI C
 International standard (ISO) in 1990 which was adopted by ANSI and is known as C89
 As part of the normal evolution process the standard was updated in 1995 (C95) and 1999 (C99)
 C++ and C
o C++ extends C to include support for Object Oriented Programming and other features that
facilitate large software development projects
o C is not strictly a subset of C++, but it is possible to write “Clean C” that conforms to both the
C++ and C standards.

2.2 Features of C
 Middle level language: C combines the features of high level language and low level machine
language.
 Structured programming language: C is a structured programming language, which means that it
allows you to develop programs using well-defined control structures, and provides modularity
(breaking the task into multiple sub tasks that are simple enough to understand and to reuse).
 Portability-C is not tied to any particular hardware or system and it is relatively easy to write programs
that will run without change on any machine that supports C.
 Efficiency
 Powerful data structures

2.3 Applications of C

 System software
 Embedded programming
 Real-time applications
 Device drivers
 Application programming

003-00002 Page-11

Copyright CoreEL Technologies (I) Pvt. Ltd.


2.4 Typical C / C++ development environment

C/C++ systems generally consist of three parts: a program development environment, the language and the
C/C++ Standard Library. C++ programs typically go through six phases: edit, preprocess, compile, link, load
and execute. The following discussion explains a typical C/C++ program development environment.

Figure 2.1 C Program Development Environment

003-00002 Page-12

Copyright CoreEL Technologies (I) Pvt. Ltd.


2.4.1 Phase 1 : Editing

It consists of editing a file with an editor program (normally known simply as an editor). You type a C/C++
program (typically referred to as source code) using the editor, make any necessary corrections and save the
program on a secondary storage device, such as your hard drive. C/C++ source code file names often end
with the .c/.cpp extension which indicates that a file contains C/C++ source code. Editor example. VI

2.4.2 Phases 2 & 3: Preprocessing and compiling a C program

In phase 2, the programmer gives the command to compile the program. In a C/C++ system, a preprocessor
program executes automatically before the compiler's translation phase begins (so we call preprocessing
phase 2 and compiling phase 3). The C/C++ preprocessor obeys commands called preprocessor directives,
which indicate that certain manipulations are to be performed on the program before compilation. These
manipulations usually include other text files to be compiled and perform various text replacements. In phase
3, the compiler translates the C++ program into machine-language code (also referred to as object code).

2.4.3 Phase 4: Linking

Phase 4 is called linking. C/C++ programs typically contain references to functions and data defined
elsewhere, such as in the standard libraries or in the private libraries of groups of programmers working on a
particular project. The object code produced by the C/C++ compiler typically contains "holes" due to these
missing parts. A linker links the object code with the code for the missing functions to produce an executable
image (with no missing pieces). If the program compiles and links correctly, an executable image is produced.

2.4.4 Phase 5 : Loading

Phase 5 is called loading. Before a program can be executed, it must first be placed in memory. This is done
by the loader, which takes the executable image from disk and transfers it to memory. Additional components
from shared libraries that support the program are also loaded.

2.4.5 Phase 6: Execution

Finally, the computer, under the control of its CPU, executes the program one instruction at a time.

003-00002 Page-13

Copyright CoreEL Technologies (I) Pvt. Ltd.


2.5 The C Preprocessor

The C Preprocessor does the following jobs

 File inclusion
 Conditional compilation
 Macro substitution
 Also , removes the comments

2.6 Compiler

 C compiler compiles the given C program, checks for errors, and tries to optimize if required and finally
generates the code.
 If compiler finds any errors, then it reports failure, so the next process (linking) is not carried out.

2.7 Assembler

 After the compiler generates the code in assembly language, the assembler translates the program into
the object code.
 An assembler dumps the object code onto a file called object file (usually have .o as suffix).

2.8 Linker

 If a source file references library functions or functions defined in other source files the linker combines
these functions to create an executable file. External Variable references are also resolved here.
 After resolving, if it finds undefined objects/functions, then it reports a failure. Otherwise, the linker
links the c-library to the object-file generated, and dumps it onto a file called executable file (a.out in
UNIX/Linux by default).

2.9 Loader

• Loader is a program which loads the executable program(binary file) from disk to the memory, and
st st
places the address of the 1 byte of the 1 instruction onto the PC (a register of CPU).

Figure 2.2 Loader

003-00002 Page-14

Copyright CoreEL Technologies (I) Pvt. Ltd.


2.10 The C Program structure

A C program basically has the following form

 Comments (/*……………*/
 Preprocessor directives, #include and #define
 Type definitions (struct , typedef)
 Function prototypes.
 Global Variables
 Function Definitions.

2.10.1 Comments

 Comments are a way of inserting remarks and reminders into a program without affecting its content.
 Comments do not have a fixed place in a program
 Comments are marked out or delimited by the following pairs of characters /* */
Example,

/* TYPE YOUR COMMENT HERE*/

2.10.2 Preprocessor directives

A preprocessor performs macro substitution, conditional compilation, and inclusion of named files. Lines
beginning with # communicate with the preprocessor.

003-00002 Page-15

Copyright CoreEL Technologies (I) Pvt. Ltd.


The common preprocessor directives are

#include include file for linking

#define define a preprocessor symbol/macro

#undef un-define a previously defnined symbol

#if test for conditional compilation

#ifdef (ditto)

#ifndef (ditto)

#else (ditto)

#endif (ditto)

#line debug tool

#error debug tool

2.10.3 Type definitions

C supports the idea of programmers creating their own data types. Example, structures, arrays, pointers,
typedef, enumerations etc.

2.10.4 Function prototypes

A function prototype is a declaration in C and C++ of a function, its name, parameters and return type. Unlike
a full definition, the prototype terminates in a semi-colon.

int getsum(float * value) ;


Prototypes are used in header files so that external functions in other files can be called and the compiler can
check the parameters during compilation.

2.10.5 Global variables

Global variables can be referred from anywhere in the code, even inside functions, Whenever
it is after its declaration.

2.10.6 Function definitions

A function definition specifies the name of the function, the types and number of parameters it expects to
receive, and its return type. A function definition also includes a function body with the declarations of its local
variables, and the statements that determine what the function does.

003-00002 Page-16

Copyright CoreEL Technologies (I) Pvt. Ltd.


2.10.7 Header files and libraries

Header files contain macro definitions, type definitions and variable/ function declarations which are used in
connection with standard libraries. They supplement the object code libraries which are linked at compile time
for standard library functions. Some library facilities are not available unless header files are included. Typical
names for header files are:

stdio.h Standard I/O (libc).

ctype.h Macro for character types.

math.h Mathematical definitions (libm)

2.10.8 The main() function


Every C program has a primary (main) function that must be named main. The main function serves as the
starting point for program execution. It usually controls program execution by directing the calls to other
functions in the program. A program usually stops executing at the end of main, although it can terminate at
other points in the program for a variety of reasons. At times, perhaps when a certain error is detected, you
may want to force the termination of a program. To do so, use the exit function.

A sample C Program
/* Program to print welcome*/
#include<stdio.h>
#include<stdlib.h>
int main()
{

system(“clear”);
printf(“WELCOME”);
return 0;

}
You may have noticed that there is a return statement at the end of main function. Like any other function,
main also returns a value to its caller, which is in effect the environment in which the program was executed. A
return value of 0 indicates normal termination and non-zero values signals unusual or erroneous termination
conditions.

003-00002 Page-17

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 3

BASIC PROGRAM ELEMENTS IN C

Introduction

This chapter introduces you to the basic programming elements or tokens in C. They are
1. Identifiers
2. Keywords
3. Constants
4. String literals
5. Operators

It also deals with variables, different data types, type specifiers and qualifiers, operator precedence and
standard input/output functions in C.

3. 1 Identifiers

Identifiers are names given to variables, functions, arrays etc. It is a must that the first character in the identifier
is a letter or in rare cases underscore( _ ). The subsequent characters must be either letters, digits or
underscores. Upper and lower cases are different. Hence count, Count, COUNT, are three separate identifiers.

3.2 Keywords

Identifiers which are reserved for special purpose is known as keywords (also known as reserved words). The
following are the keywords supported in ANSI C.

auto double if sizeof


break else int static
case enum long struct
char extern void switch
const float register typedef
continue for return union
default while short unsigned
do goto signed volatile

3.2.2 Variable and Datatypes


A variable is a meaningful name of data storage location in computer memory that can change value during
execution. All variables must be declared before use.

The syntax of variable declaration is


type variablename1,..,..,variablenameN;

A variable may also be initialized in its declaration.


type variablename1= value;

003-00002 Page-18

Copyright CoreEL Technologies (I) Pvt. Ltd.


The type of a variable conveys to the compiler what sort of data will be stored in it. So this type is termed as
data type. The basic data types available in C are
1. char

A single byte capable of holding one character in the local character set

2. int
A standard integer. int data type’s size is usually chosen as natural size of the ALU. Width of ALU = Size of
operand. Popular ALU’s are 16 bits OR 32 bits. int is a non-portable data type. For example, a program
running on a 32-bit compiler may not work if compiled on a 16-bit compiler. To develop portable programs, two
suffixes are used viz., short and long.
Ex: short int num;
long int sum;
The word int can be omitted in such declarations. The intent is that short and long should provide different
lengths of integers where practical; short int is 16 bits and long int is 32 bits and int is either 16 or 32 bits. Each
compiler is free to choose appropriate sizes for its own hardware.
The term signed or unsigned may be applied to char or any integer. Unsigned numbers are always positive
n
or 0, and they obey the laws of arithmetic modulo 2 , where n is the number of bits in this type. For example, if
chars are 8 bits, unsigned char variables can have values between 0 and 255, while signed chars can have
values between -128 and 127. –ve numbers are always stored as 2’s compliment

3. float

A floating point or real number (single precision) , 32 bits

4. double

A double-precision point number which occupies 64 bits. We can even have long double specifies extended-
precision floating point number.

Type qualifiers may appear with any of the above type specifiers to indicate the special properties of the
objects being declared. The type qualifiers are
1. const
2. volatile.

The qualifier const can be applied to the declaration of any variable to specify that its value will not be
changed. For an array, the const qualifier says that the elements will not be altered.

const float pi=3.14;


const char msg[]=”warning”;`

003-00002 Page-19

Copyright CoreEL Technologies (I) Pvt. Ltd.


The purpose of const is to announce that objects may be placed in read only memory and perhaps to increase
the optimization.
Declaring an object as volatile tells the compiler that the object is subject to sudden change for reasons which
cannot be predicted from a study of the program itself, and forces every reference to such object to be a
genuine reference. The volatile modifier requires the compiler to actually access the variable every time it is
read. This means that if you reference the variable, the program should always check the physical address,
and not use it in a cached way. The volatile qualifier alters the default behavior of the variable and does not
attempt to optimize the storage referenced by it. This is mainly used for multithreading and interrupt processing
purposes etc., things you needn't worry about yet.

3.3 Constants

Constants are names given to entities that cannot be modified during the execution of program. They are fixed
values. The different kinds of constants in C are
1. Integer constant

2. Character constant

3. Floating point constant

4. String constant

5. Enumeration constant

003-00002 Page-20

Copyright CoreEL Technologies (I) Pvt. Ltd.


3.3.1 Integer constants

Integer constants are further divided into 3.


1. Decimal integer constants- integer constant consisting of a sequence of digits from 0-9.
2. Octal constant- integer constant that begins with digit 0 and that do not contain digits 8 and 9
3. Hexa decimal constant- a sequence of digits preceded by 0x or 0X. Hexadecimal digits include digits 0
to 9 and letters a/A through f/F with values 10 through 15.
An integer constant may be suffixed by the letter u or U, to specify that it is unsigned. It may also be suffixed
by the letter l or L to specify that it is long.

3.3.2 Character constants

A character constant is a sequence of one or more characters enclosed within single quotes, for example, ‘a’.
The value of a character constant with only one character is the numeric value of the character in the
machine’s character set (ASCII) at the execution time. The value of a multi-character constant is
implementation different.

3.3.3 Floating constants

A floating constant consists of an integer part, a decimal point, a fraction part, an e or E, an optionally signed
integer exponent and an optional suffix, one of f, F, l or L. The integer part and fraction parts both consist of a
sequence of digits. Either the integer part or fraction part (not both) may be missing; either the decimal point or
the e and the exponent(not both) may be missing. The type is determined by the suffix; F or f makes it float, L
or l makes it long double, otherwise it is double.

3.4 String literals

A string literal also known as a string constant is a sequence of characters surrounded by double quotes, as in
“hello”. A string has type array of characters and storage class static. Adjacent string literals are concatenated
into a single string. After any concatenation, a null byte \0 is appended to the string so that programs that scan
the string can find its end.

3.5 Operators
An operator is a symbol which takes one or more values and operates on those values to produce a result.

Few terminologies
1. Operator- Something which operates on something.
2. Operand- Each thing which is operated upon by an operator is called an operand. Operation- The
action which was carried out upon the operands by the operator
3. Expression- An expression is simply the name for any string of operators, variables and numbers.

3.5.1 Operators available in C

1. Assignment Operator

2. Arithmetic Operator

3. Relational Operator

003-00002 Page-21

Copyright CoreEL Technologies (I) Pvt. Ltd.


4. Logical Operator

5. Increment and Decrement Operator

6. Bitwise Operator

7. Conditional Operator

8. Comma Operator

9. sizeof Operator

10. Type cast Operator

3.5.1.1 Assignment Operator =

The assignment operator assigns a value to a variable.


a=5;
This statement assigns the integer value 5 to the variable a. The part at the left of the assignment operator (=)
is known as the lvalue (left value) and the right one as the rvalue
(right value). The lvalue has to be a variable whereas the rvalue can be a constant, a variable, the result of
an operation or any combination of these.The most important rule when
assigning is the right-to-left rule: The assignment operation always takes place from right to left.

3.5.1.2 Arithmetic Operator

The five arithmetical operations supported by the C language are:


+ addition

- subtraction

* multiplication

/ division

% modulo

Operations of addition, subtraction, multiplication and division literally correspond with their respective
mathematical operators. The only one that you might not be so used to see is modulo; whose operator is the
percentage sign (%). Modulo is the operation that gives the remainder of a division of two integer values. For
example, if we write:
a = 11 % 3
The variable a will contain the value 2, since 2 is the remainder from dividing 11 between 3.

#include <stdio.h> Page-22


003-00002
int main( )
{
int num1 = 3,num2 = 5,num3
Copyright = Technologies
CoreEL 8; (I) Pvt. Ltd.
OUTPUT:
Total = 16
Avg = 5.0

Observe the avg is 5.0 and not 5.33, because when both the operands are integers, integer division is
performed. In other words, integer division discards the part after the decimal point. So, 10/3 is 3 (not
3.3333…), 5/2 is 2 (not 2.5). To get the accurate result, we need to typecast. A type cast is a way of changing
a value of one type to another type.

In some situations, you might want the answer to be the double value 5.33. You can get a result of 5.33 by
using the “equivalent” floating-point value 3.0 in place of the integer value 3, as in 16/3.0, which evaluates to
5.33. But what if the 3 is the value of variables of type int named count? Then total/count yields 5. If you want
floating-point division in this case, you must do a type cast from int to float (or another floating-point type), such
as in the following:
avg = (float)total / count;

3.5.1.3 Relational Operator

In order to evaluate a comparison between two expressions we can use the relational and equality operators.
By definition, the numeric value of a relational or logical operator is 1
If the relation is true and 0 if the relation is false. Here is a list of the relational and equality operators that can
be used in C:

== Equal to

!= Not equal to

> Greater than

< Less than

>= Greater than or equal to

<= Less than or equal to

003-00002 Page-23

Copyright CoreEL Technologies (I) Pvt. Ltd.


Program to demonstrate relational operator
int main( )
{
int a = 10,b = 50,res;
printf(“Enter the values of a and b :”);
scanf(“%d%d”,&a,&b);
res = a > b;
printf(“The result of comparison is %d\n”, res);
}

Compound assignment / Short hand operators (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)
When we want to modify the value of a variable by performing an operation on the value currently stored in
that variable we can use compound assignment operators:
Expression Is equivalent to
value += increase; value = value + increase;
a -= 5; a = a - 5;
a /= b; a = a / b;
price *= units + 1; price = price * (units + 1);

3.5.1.4 Logical Operator !, &&, ||


The logical operators are used to combine expressions.
Truth Tables

AND NOT
Exp_1 Exp_2 Exp_1&&Exp_2
true true true
Exp !(Exp)
true false false
false true false true false
false false false
false true
OR
Exp_1 Exp_2 Exp_1||Exp_2
true true true
true false true
false true true
false false false

Program to demonstrate logical operators


int main( )
{
int marks1,marks2,marks3;
printf(“Enter the marks of 3 subjects :”);
scanf(“%d%d%d”,&marks1,&marks2,&marks3);
if( marks1 > 40 && marks2 > 40 && marks3 > 40)
printf(“PASS”);
else
printf(“FAIL”);
}

003-00002 Page-24

Copyright CoreEL Technologies (I) Pvt. Ltd.


3.5.1.5 Increment and Decrement Operators ++ --

C provides another set of shortcuts: the increment and decrement operators. In their simplest forms, they look
like this:
++i; add 1 to i
--j; subtract 1 from j
The ++ and – operators apply to one operand (they’re unary operators). The expression ++i adds 1 to i, and
stores the incremented result back in i. This means that these operators don’t just compute new values; they
also modify the value of some variable.
Both the ++ and – operators have an unusual property: they can be used in two ways; depending on whether
they are written to the left or the right of the variable they’re operating on. The prefix form ++i increments i and
returns the incremented value. The postfix form i++ increments i, but returns the prior, non-incremented
value. Rewriting our previous example slightly, the expression

k = 2 * i++;

means, take i’s old value and multiply it by 2, increment i, store the result of the multiplication in k.

Program to demonstrate pre increment and post increment operators


int main( ) int main( )
{ {
int a = 5 , x ; int a = 5 , x;
x = ++a; x = a++;
printf("a = %d ",a); printf("a = %d ",a);
printf("x = %d ",x); printf("x = %d ",x);
} }

3.5.1.6 Bitwise Operators (&, |, ^, ~, <<, >> )

• The bitwise operators allow you to manipulate individual bits


• We can check, clear, set, or invert any bit or group of bits.
• We can also shift the bit pattern of an integer to the left or right.
• Can be applied to integral operands only
• C provides six operators for bit manipulation

003-00002 Page-25

Copyright CoreEL Technologies (I) Pvt. Ltd.


Symbol Meaning Description

& Bitwise AND Compares each bit of its first operand to the corresponding bit of its
second operand.
If both bits are 1, the corresponding result bit is set to 1. Otherwise, the
corresponding result bit is set to 0.

| Bitwise OR Compares each bit of its first operand to the corresponding bit of its
second operand.
If either bit is 1, the corresponding result bit is set to 1. Otherwise, the
corresponding result bit is set to 0.

^ Bitwise XOR Compares each bit of its first operand to the corresponding bit of its
second operand. If one bit is 0 and the other bit is 1, the corresponding
result bit is set to 1. Otherwise, the corresponding result bit is set to 0.

~ Compliment flips every bit

>> Right Shift right shifts of their left operand by the number of bit positions given by the
right operand

<< Left Shift Left shifts of their left operand by the number of bit positions given by the
right operand

One must distinguish the bitwise operators & and | from the logical operators && and ||, which imply left to
right evaluation of a truth value. For eg., if x is 1 and y is 2, then x & y is zero while x && y is one.

Program to demonstrate bit-wise operators


int main( )
{
unsigned int a = 0x3C; = 0011 1100
unsigned int b = 0xD; = 0000 1101

printf(“ a & b = %x “, a & b); = 0000 1100


printf(“ a & b = %x “, a | b); = 0011 1101
printf(“ a & b = %x “, a ^ b); = 0011 0001
}

003-00002 Page-26

Copyright CoreEL Technologies (I) Pvt. Ltd.


Program to check the number is even or odd
int main( )
{
int num ;
printf(“Enter the number : ”);
scanf(“%d”, &num);
if((num & 1) == 1)
printf(“The number %d is odd “,num);
else
printf(“The number %d is even “,num);
}

Program to Convert uppercase alphabet to lowercase


int main( )
{
char alpha;
printf("\n n ENTER A Alphabet : ");
scanf(“%c", &alpha);
alpha = (alpha | 0x20) ;
printf(“ %c ”,alpha);
return 0;

The shift operators << and >> perform left and right shifts of their left operand by the number of bit positions
given by the right operand, which must be non negative. Thus x << 2 shifts the value of x by two positions,
filling vacated bits with zero; this is equivalent to multiplication by 4. Right shifting an unsigned quantity
always fits
its the vacated bits with zero. Right shifting a signed quantity will fill with bit signs (``arithmetic shift”)
on some machines and with 0 bits (``logical shift”) on others.
The unary operator ~ yields the one’s complement of an integer; that is, it conve
convertsrts each 1x bit into a 0x bit
and vice versa.

Right Shift by 1

003-00002 Page-27

Cop
opyright CoreEL Technologies (I) Pvt. Ltd.
Left Shift by 1

Clear/reset a bit
Logic to reset LSB Logic to reset nth bit of a number

a=a&1 a = a & (~ (1 << pos))

Set a bit
Logic to set LSB Logic to set nth bit of a number

a=a|1 a = a | (1 << pos)

Toggle a bit
Logic to toggle LSB Logic to toggle nth bit of a number

a=a^1 a = a ^ (1 << pos))

3.5.1.7 Conditional Operator ( ?: )

The conditional operator evaluates an expression returning a value if that expression is true and a different
one if the expression is evaluated as false. Its format is:

condition ? result1 : result2

If condition is true then the expression will return result1, if it is not it will return result2.

Example int x=100;

y = ( x > 90 ) ? 1 : 2 ; will result y=1

003-00002 Page-28

Cop
opyright CoreEL Technologies (I) Pvt. Ltd.
3.5.1.6 Comma Operator ( , )

The comma operator (,) is used to separate two or more expressions that are included where only one
expression is expected. When the set of expressions has to be evaluated for a value, only the rightmost
expression is considered.

For example, the following code:

a = ( b = 3 , b + 2 ) ; would first assign the value 3 to b, and then assign b+2 to variable a. So, at the end,
variable a would contain the value 5 while variable b would contain value 3.

3.5.1.7 sizeof () Operator

This operator accepts one parameter, which can be either a type or a variable itself and returns the size in
bytes of that type or object:
a=sizeof(char)
This will assign the value 1 to a because char is a one-byte long type.

3.5.1.8 Type cast Operator

Type casting operators allow you to convert a datum of a given type to another. There are several ways to do
this in C++. The simplest one, which has been inherited from the C language, is to precede the expression to
be converted by the new type enclosed between parentheses (()):
int i;
float f = 3.14;
i = (int) f;
This converts the float number 3.14 to an integer value (3), the remainder is lost. Here, the typecasting
operator was (int).

3.5.2 Precedence and Associativity

Operator precedence describes the order in which C reads expressions. For example, the expression
a=4+b*2 contains two operations, an addition and a multiplication. Does the C compiler evaluate 4+b first,
then multiply the result by 2, or does it evaluate b*2 first, then add 4 to the result? The operator precedence
chart contains the answers. Operators higher in the chart have a higher precedence, meaning that the C
compiler evaluates them first. Operators on the same line in the chart have the same precedence, and the
"Associativity" column on the right gives their evaluation order.
The following table from Kernigan and Richie shows the precedence hierarchy in C. The top line has the
highest precedence.

003-00002 Page-29

Copyright CoreEL Technologies (I) Pvt. Ltd.


3.6 Standard input output functions in C

Streams are a portable way of reading and writing data. A stream is a source or destination of data that may
be associated with a disk or other peripheral. A stream is connected to a file or device by opening it; the
connection is broken by closing the stream. Opening a file returns a pointer to an object type FILE which
records whatever information is necessary to control the stream.

When a C program is started, the operating system environment is responsible for opening 3 files and
providing file pointers to them. These
hese files are the standard input, the standard output and the standard error;
the corresponding file pointers are called stdin, stdout and stderr, and are declared in <stdio.h>. Normally
stdin is connected to the keyboard and stdout and stderr are connect
connected
ed to the screen, but they can also be
redirected to files or pipes.

There is a couple of function that provides basic I/O facilities.The basic I/O functions are: getchar() and
putchar(). They are defined and used as follows:

int getchar(void) -- reads a char from stdin


int putchar(int) -- writes a char to stdout, returns character written.

Example,
char ch;
ch = getchar();
putchar(ch);

003-00002 Page-30

Cop
opyright CoreEL Technologies (I) Pvt. Ltd.
3.7 Formatted I/O Functions – Printf and Scanf

3.7.1 printf ()

The function is defined as follows:


int printf(const char *format, arg list ...)

It prints to stdout the list of arguments according specified format string. It returns the number of characters
printed.
The format string has 2 types of object:
1. Ordinary characters -- these are copied to output.
2. Conversion specifications -- denoted by % and listed in Table

Specifiers

3.7.2 scanf()

This function is defined as follows:


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

It reads from stdin and puts input in address of variables specified in args list. Returns number of chars read.
Format control string is similar to printf .

Note: The ADDRESS of variable or a pointer to one is required by scanf. scanf (``%d'',&i);

003-00002 Page-31

Copyright CoreEL Technologies (I) Pvt. Ltd.


GOOD TO KNOW

Some useful gcc compiler options

$ gcc –E program.c
Dumps the preprocessor output to stdout.
$ gcc –S program.c
Creates an assembly file program.s from the source file program.c.
$ gcc –c program.c
Creates an object file program.o from the source file program.c.
$ gcc -o program program.c
Create an executable called program from the source file program.c

Executing a C Program

$ ./program

You need to enter the name of the executable file to run the program

003-00002 Page-32

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 4

STATEMENTS IN C

Introduction

C Program is made up of statements. Statement is a part of a program that can be executed. C provides
variety of statements to help you attain any function with maximum flexibility and efficiency.

Statements in C are categorized into following types-

1. Selection/Decision control instructions - They decide the flow of statements based on the evaluation
of results of conditions. if - else and switch statements come under this category.

2. Iteration Statements - These are used to run a particular block of statements repeatedly, or in other
words to form a loop. for, while and do-while statements come under this category.

3. Jump Statements - They are used to make the flow of your statements from one point to another.
break, continue, goto and return come under this category.

This chapter gives a picture about the different statements in C language.

4.1 Selection statements

4.1.1 if statement

The if-else statement directs the computer to select a sequence of one or more instructions based on the
result of comparison.
The condition is checked if the result is true the statement(s) following if are executed, otherwise the
statement(s) following the else part are executed.

if(condition)
{
statement(s) if condition is true.
}
else
{
Statement(s) if condition is false
}

003-00002 Page-33

Copyright CoreEL Technologies (I) Pvt. Ltd.


Example : Program to check whether the number is a perfect square.
#include <math.h>
#include <stdio.h>
int main( )
{
int num;
float sq;
printf(“\nEnter a positive number :”);
scanf (“%d”, &num);
sq = sqrt(num);
if (sq – (int)sq == 0.0f)
printf(“The number is perfect square”);
else
printf(“The number is not a perfect square”);
return 0;
}

Note: Math library must be explicitly linked while compiling

Program to test whether a given number is power of 2


#include <stdio.h>
int main( )
{
int num;
printf(“Enter a Number: “);
scanf(“%d”, &num);
if((num & (num – 1)) == 0)
printf(“The number is a power of two \n”);
else
printf(“The number is not a power of two \n”) ;
return 0;
}

The else if ladder


When a series of many conditions have to be checked we may use the ladder else if statement which takes
the following general form.

if(condition 1)
{
Statemnets;
}
else if (condition 2)
{
Statements;
}
else
{
Statements;
}

003-00002 Page-34

Copyright CoreEL Technologies (I) Pvt. Ltd.


The conditions are evaluated from the top of the ladder to downwards. As soon as the true condition is found,
the statement associated with it is executed. When all the condition becomes false, the final else containing
the default statement will be executed.

4.1.2 Switch statement

The switch statement provides an alternative to the if-else chain for cases that compare the value of an
integer expression to a specific value. The general form is
switch (expression)
{
case value1:
statement(s);
break;
case value2:
statement(s);
break;
case valueN:
statement(s);
break;
.
default:
statement(s);
break; /* Optional */
}

The switch statement uses four keywords switch, case, default and break. The keyword switch identifies
the start of the switch statement. The expression in parentheses following switch word is evaluated and the
result of the expression is compared to various alternative values contained in the case within the switch
statement.

The keyword case is used to identify label values that are compared to the value of the switch expression.
The switch expression’s value is compared to each of these case values in the order that these values are
listed until a match is found.

When a match occurs, execution begins with the statement immediately following the match until the break
statement occurs or until the end of switch. Any number of case labels may be contained within a switch
statement in any order. The word default is optional and operates like the last else in an if-else chain. If the
value of the expression does not match with any of the case values, program execution begins with the
statement following the word default.

The break statement signals the end of the particular case, and causes the switch statement to be
terminated. At the end of every case, there should be a break statement. Otherwise, it will result in causing
the program execution to continue into the next case whenever the case gets executed.

003-00002 Page-35

Copyright CoreEL Technologies (I) Pvt. Ltd.


Note
• Any number of case labels may be contained within a switch statement in any order.
• Even if there are multiple statements to be executed in each case there is no need to enclose these
within a pair of braces
• If there is no default case, and if none of the case is matched, then the program simply falls through
the entire switch and continuous with next instruction that follows the control structure.
• The disadvantage in switch is that one cannot have a case in a switch which looks like case i < = 2,
even float is not allowed
• The case can be an int constant, a char constant or it can be a constant expression like 1 * 2 + 4 as
cases..
• No two constant expressions in case statements can evaluate to the same value
• The switch statement is very useful while writing menu driven programs.

Program to implement a simple calculator


#include <stdio.h>
#include <stdio_ext.h>
int main( )
{
int num1,num2,res;
char op ;
printf(“ ENTER THE FIRST OPERAND “);
scanf(“%d”,&num1);
printf(“\n ENTER THE OPERATOR : “);
__fpurge(stdin);
op = getchar( );
printf(“ ENTER THE SECOND OPERAND “);
scanf(“%d”,&num2);
switch(op)
{
case ‘+’ : res = num1 + num2; break;
case ‘-‘ : res = num1 – num2; break;
case ‘*’ : res = num1 * num2; break;
case ‘/’ : res = num1 / num2; break;
}
printf(“\n The result of %d %c %d = \ %d”,num1,op,num2,res);
return 0;
}

4.2 Iteration statements


4.3
The versatility of the computer lies in its ability to perform a set of instructions repeatedly. This involves
repeating some portion of the problem either a specified number of times or until a particular condition is
being satisfied.

This repetitive operation is done through a loop control structure.


There are three looping statements in C
• while loop
• do-while loop
• for loop

003-00002 Page-36

Copyright CoreEL Technologies (I) Pvt. Ltd.


4.2.1 while statement

The syntax of while loop is

while (condition)
{
statements;

}
The loop is executed as long as the expression is true and exits when the condition is false. The condition
being tested may use relational or logical operators

Program to Count number of digits in a given number using while loop


#include <stdio.h>
int main( )
{
int num, i, count;
printf(“\n ENTER A NUMBER : “);
scanf(“%d”,&num);
count = 0;
while(num != 0)
{
count++;
num /= 10;
}
printf(“\n The no of digits = %d”,count);
return 0;
}

Program to Count Number of digits, Alphabets and words


#include <stdio.h>
int main( )
{
int countdigit = 0, countalpha = 0, countword = 0, c;
while(( c = getchar()) != EOF)
{
if(isdigit(c))
countdigit++;
if(isalpha(c))
countalpha++;
if(isspace(c))
countword++;
}
printf(“NUMBER OF DIGITS = %d”,countdigit);
printf(“NUMBER OF ALPHABETS = %d”,countalpha);
printf(“NUMBER OF WORDS = %d”,countword + 1);
return 0;
}

4.2.2 The do while statement

003-00002 Page-37

Copyright CoreEL Technologies (I) Pvt. Ltd.


The do...while loop resembles closely the “repeat…until” loops of Pascal and BASIC except that it is the
`logical opposite'. The do loop has the form:

do
{
statements;
}while (condition);

The loop body statement is executed once before the controlling expression is evaluated for the first time.
Unlike the while and for statements, do ... while ensures that at least one iteration of the loop body is
performed. If the controlling expression yields true, then another iteration follows. If false, the loop is finished.

int main()
{
int num ;
int repeat;
do
{
printf(“Enter a number : “);
scanf(“%d”,&num);
if(num > 0)
printf(“Positive”);
else
printf(“Negative”);
printf(“Do you want to check another number(0-No 1-Yes) “);
scanf(“%d”,&repeat);
}while(repeat !=0);
}

4.2.3 for statement

for loop allows us to specify three things about a loop in a single line:
• Setting the loop counter to an initial value
• Testing the loop counter to determine whether its value has reached the number of repetitions
desired.
• Updating the value of loop counter each time the program segment within the loop has been reached.
The general form of for statement is
for (initialization; expression; Update_counter)
statement(s);
Initialization: This is usually an assignment statement that is used to set the loop control variable.
Expression: This is usually a relational expression that determines when the loop should terminate.
Update: This defines how the loop control variable should change each time the loop is repeated.
The three expressions must be separated by a semicolon.

Program to Count number of digits in a given number using for loop

#include <stdio.h>

003-00002 Page-38

Copyright CoreEL Technologies (I) Pvt. Ltd.


int main( )
{
int num, count;
printf(“\n ENTER A NUMBER : “);
scanf(“%d”,&num);
for(count = 0; num != 0 ; count++)
{
num /= 10;
}
printf(“\n The no of digits = %d”,count);
return 0;
}

Program to print a given number in binary.

#include <stdio.h>
int main( )
{
int num, i;
printf(“\n ENTER A NUMBER : “);
scanf(“%d”,&num);
for(i = 15 ; i >= 0 ; i--)
{
if(num & (1 << i))
printf(“1”);
else
printf(“0”);
}
return 0;
}

Infinite loops

A while loop, do-while loop, or for loop does not terminate as long as the controlling Boolean expression is
true. This Boolean expression normally contains a variable that will be changed by the loop body, and usually
the value of this variable is changed in a way that eventually makes the Boolean expression false and
therefore terminates the loop. However, if you make a mistake and write your program so that the Boolean
expression is always true, then the loop will run forever. A loop that runs forever is called an infinite loop.
Unfortunately, examples of infinite loops are not hard to come by. First let’s describe a loop that does
terminate. The following C code will write out the positive even numbers less than 12. That is, it will output the
numbers 2, 4, 6, 8, and 10, one per line, and then the loop will end.

003-00002 Page-39

Copyright CoreEL Technologies (I) Pvt. Ltd.


x = 2;
while (x != 12)
{
printf(“ %d”,x);
x = x + 2;
}
The value of x is increased by 2 on each loop-iteration, until it reaches 12. At that point, the Boolean
expression after the word while is no longer true, so the loop ends. Now suppose you want to write out the
odd numbers less than 12, rather than the even numbers. You might mistakenly think that all you need do is
change the initializing statement to
x = 1;

But this mistake will create an infinite loop. Because the value of x goes from 11 to 13, the value of x is never
equal to 12; thus, the loop will never terminate. This sort of problem is common when loops are terminated by
checking a numeric quantity using == or !=. When dealing with numbers, it is always safer to test for passing
a value. For example, the following will work fine as the first line of our while loop:
while (x < 12)

With this change, x can be initialized to any number and the loop will still terminate.

4.3 Jump statements

4.3.1 The break statement


The break statement can occur only in the body of a loop or a switch statement, and causes a jump to the first
statement after the loop or switch statement in which it is immediately contained:

break;
Thus the break statement can be used to end the execution of a loop statement at any position in the loop
body.

Program to check if a given number is prime or not with and without break
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
int main( ) { int main( ) {
int num,i , flag ; int num,i;
printf(“\n ENTER A NUMBER : “); printf(“\n ENTER A NUMBER : “);
scanf(“%d”,&num); scanf(“%d”,&num);
flag = 0;
for(i = 2 ; i <= sqrt(num); i++) for(i = 2; i <= sqrt(num); i++)
if(num % i == 0) if(num % i == 0)
{ {
flag = 1; break;
} }
if(flag == 0) if(i <= sqrt(num))
printf(“\n PRIME “); printf(“\n PRIME “);
else else
printf(“\n NOT PRIME”); printf(“\n NOT PRIME”);
return 0; return 0;
} }

003-00002 Page-40

Copyright CoreEL Technologies (I) Pvt. Ltd.


4.3.2 The continue statement
The continue statement is used when it is required to bypass a part of looping statements. Continue behavior
in loops as follows

while(Expr){ do{ for(init;condition;Update){


…….. …….. ……..
…….. …….. ……..
continue; continue; continue;
…….. …….. ……..
.……. .……. .…….
} } while(Expr); }

When the keyword continue is encountered inside the loop the control automatically passes to the beginning
of the loop. The continue will take the control to the condition block of the while and do-while loop where as in
for loop the control will be taken to the update part as shown in the above diagram. Continue is usually
associated with an if.

#include <stdio.h>
int main( )
{
int number, sum = 0, count = 0;
printf(“Enter 4 positive numbers, ONE PER LINE:\n”);
while (count < 4)
{
scanf(“%d”,&number);
if (number < 0)
{
printf(”ERROR: Enter positive number ! \
Reenter that number and continue:\n”);
continue;
}
sum = sum + number;
count++;
}
printf(“ %d is the sum of the %d numbers”,sum, count);
return 0;
}

A break causes the innermost enclosing loop or switch to be exited immediately. The break statement
provides an early exit from for, while, and do loops, just as it does for switch

003-00002 Page-41

Copyright CoreEL Technologies (I) Pvt. Ltd.


4.3.3 The goto statement

The goto statement is perhaps the most controversial feature in C. It is used for jumping from one point to
another point in our function. Jump points or way points for goto are marked by label statements. Label
statement can be anywhere in the function above or below the goto statement. General form of goto
statement is

goto label1;

…..

label1 :
To further clarify the concpet of goto statement study

int main ()
{
int a = 1; loop:
printf ("\n%d",a); a++;
if (a < 10) goto loop ;
return 0;
}

4.3.4 The return statement


The return is used to return from the calling function to the caller function. Return statement also has a special
property that it can return a value with it to the calling function if the function is declared non - void.
return expression;

In such a statement the value of the expression is returned. Value can also be explicitly mentioned making a
function

003-00002 Page-42

Copyright CoreEL Technologies (I) Pvt. Ltd.


GOOD TO KNOW

Some commonly used mathematical functions


double sqrt( double x ); Calculates the square root
double pow( double x, double y ); Calculates x raised to the power of y
double log( double x ); Calculates logarithms.
double log10( double x );
double ceil( double x ); Calculates the ceiling of a value.
double floor( double x ); Calculates the floor of a value.
int abs( int n ); Calculates the absolute value of integer.
double fabs( double x ); Calculates the absolute value of double.
int rand( void ); Generates a pseudorandom number.
void srand( unsigned int seed ); Sets a random starting point.

Character manipulation functions

int isalpha(int c); checks for an alphabetic character


int isdigit(int c); checks for a digit (0 through 9)
int isalnum(int c); checks for an alphanumeric character; it is equivalent to
(isalpha(c) || isdigit(c))
int isascii(int c); checks whether c is a 7-bit unsigned char value that fits
into the ASCII character set.
int isblank(int c); checks for a blank character;
int islower(int c); checks for a lower-case character
int isupper(int c); checks for a upper-case character
int isspace(int c); checks for a lower-case character
int isxdigit(int c); checks for a white-space character(‘ ‘,’\n’,’\t’)
checks for a hexadecimal digits
int toupper(int c); toupper() converts the letter c to upper case.
int tolower(int c); tolower() converts the letter c to lower case.

003-00002 Page-43

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 5

FUNCTIONS IN C

Introduction

Functions in C are the key to manageable structured programming. Every good program is written by taking
the task and dividing it up into pieces, each of which becomes a function. Thus, function is the fundamental
modular unit in C. This chapter examines the important aspects of functions such as arguments, call by value
and call by reference, variable length function and recursion.

5.1 What are Functions?

Function can be defined as a self contained block of code that is designed for a specific task. Or, it can even
be defined as a set of statements grouped under a particular name which perform a specific task. Every C
program can be thought as a collection of functions.

C functions can be classified into two categories.


1. Library functions (Functions defined in the C Standard Library) : These are the predefined functions
stored in what is called as library. These are available on the system and are written by the people
who develop compilers.
Ex: printf( ), sqrt ( ), scanf ( )…
2. User-defined functions. : These are developed by the programmers when the built in function will not
support the desired task. However, a user defined function can latter be made as part of the C library.

5.2 Advantages of Functions

The use of functions in C serves many advantages:

1. It facilitates top-down modular programming. In this programming style, the high level of the overall
problem is solved first, while the details of each lower-level function are addressed later.
2. The length of a source program can be reduced by using functions at appropriate places.
3. It is easy to locate and isolate a faulty function for further investigations.
4. A function may be used by many other programs. This means that a C programmer can build
on what others have already done, instead of starting from scratch.

5.3 Parts of Function

Functions have 3 parts.


1. Function Definition
2. Function Declaration
3. Function Call

Sometimes the definition can serve as a declaration if the declaration appears before the function is called.

003-00002 Page-44

Copyright CoreEL Technologies (I) Pvt. Ltd.


5.3.1 Function Definition

The definition is the place where the actual function program statements or in other words the program code
is placed. The syntax is

return_type function_name(argument declarations)


{
declarations and statements
}

Return type indicates the type of value which the function wants to return to the caller. A function can return
one value of any type, except arrays. A function may return address like a pointer to function, or a pointer to
the first element of an array. To indicate that the function does not return a value, declare return type as void.

A called function returns a value to the caller using return statement. A function can return only one value per
call. The return statement can take one of the following forms

• return; (only return, does not return any value, acts like a closing brace of function)
or
• return expression or return (expression); (returns the value of the expression or variable enclosed
within ( ) to the caller.

5.3.2 Function Declaration

A function declaration establishes the name, return type, and attributes of a function that is defined elsewhere
in the program. A function declaration must precede the call to the function. This is why the header files
containing the declarations for the run-time functions are included in your code before a call to a run-time
function. If the declaration has information about the types and number of parameters, the declaration is a
prototype. The compiler uses the prototype to compare the types of arguments in subsequent calls to the
function with the function's parameters and to convert the types of the arguments to the types of the
parameters whenever necessary. The syntax is

return_type function_name (datatype parameter(s));

5.3.3 Function Call

The function must be called for it to get executed. The general format for making the function call would be as
follows:

Function_name (argument(s));

When the function is called the control, transfers to the function and all the statements present in the function
definition gets executed and after which the control, returns back to the statement following the function call.

003-00002 Page-45

Copyright CoreEL Technologies (I) Pvt. Ltd.


Note :

1. Every function in a program must be called directly or indirectly by main( ).


2. A function is defined when function name is followed by a pair of braces in which one or more
statements are present.
3. Any function can be called from any other function except those functions which are static in some
modules from some other module
4. A function can be called any number of times
5. The order in which the functions are defined in a program and the order in which they are called
need not be same.
6. A function cannot be defined in other function

The Functions can take the following form


• Function with no arguments and no return value.
• Function with arguments and return value.
• Function with return value and no arguments
• Function with arguments and no return value.

5.4 Passing values to Functions

Arguments are passed to functions in two ways.


1. Call by value.
2. Call by address

5.4.1 Passing Arguments by Value


In C, all function arguments are passed ``by value.” This means that the called function is given the values of
its arguments in temporary variables rather than the originals. Call by value is an asset, however, not a
liability. It usually leads to more compact programs with fewer extraneous variables, because parameters can
be treated as conveniently initialized local variables in the called routine.

5.4.2 Passing Arguments by Address


Passing by address refers to a method of passing arguments where the value of an argument in the calling
function can be modified in the called function. This concept will be discussed later with pointer.

003-00002 Page-46

Copyright CoreEL Technologies (I) Pvt. Ltd.


Program to calculate nCr without using function
int main()
{
int n, r , i;
int nf , rf , nrf , ncr;

printf(“Enter values of n and r :”);


scanf(“%d%d”,&n,&r);

for(i = 1 , nf = 1 ; i <= n ;i++)


nf = nf * i;

for(i = rf = 1 ; i <= r ;i++)


rf = rf * i;
for(nrf = i = 1 ;i <= (n – r) ;i++)
nrf = nrf * i;

ncr = nf / (rf *nrf) ;


printf(“ ncr = %d\n”, ncr);
}

By using function

int main( )
{
int n, r , i;
int nf , rf , nrf , ncr;

printf(“Enter values of n and r :”);


scanf(“%d%d”,&n,&r);

nf = fact(n);
rf = fact(r);
nrf = fact(n-r);

ncr = nf / (rf * nrf);


printf(“ ncr = %d\n”, res);
}
int fact(int n)
{
int i , f = 1;

for(i = 0; i <= n; i++)


f = f * i;

return f;
}

003-00002 Page-47

Copyright CoreEL Technologies (I) Pvt. Ltd.


5.5 Stack Frames

In computer science, a stack data structure that stores information about the active subroutines (functions) of
a computer program. This kind of stack is also known as an execution stack, control stack, function stack, or
run-time stack, and is often shortened to just "the stack".
A call stack is used for several related purposes, but the main reason for having one is to keep track of the
point to which each active subroutine should return control when it finishes executing. A call stack is
composed of stack frames (sometimes called activation records). These are machine dependent data
structures containing subroutine state information. Each stack frame corresponds to a call to a subroutine
which has not yet terminated with a return. Thus,

Stack frame is the data structure containing all the data (arguments, local variables, return address,
etc) needed each time a procedure or function is called.

Almost invariably, programs compiled from modern high level languages (even C!) make use of a stack frame
for the working memory of each procedure or function invocation. When any procedure or function is called, a
number of words - the stack frame - is pushed onto a program stack. The attributes pushed into the stack are
1. Function parameters
2. Return address
3. Local variable

When the procedure or function returns, this frame of data is popped off the stack.

As a function calls another function, first its arguments, then the return address and finally space for local
variables is pushed onto the stack. Since each function runs in its own "environment" or context, it becomes
possible for a function to call itself - a technique known as recursion. This capability is extremely useful and
extensively used - because many problems are elegantly specified or solved in a recursive way.

When you call a function there is an overhead of putting all the variables into stack, defining the return
location, passing the parameter and they are all termed as function call overheads.

003-00002 Page-48

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 6

STORAGE CLASSES IN C

Introduction

Every C variable has a storage class and a scope. The storage class determines the part of memory where
storage is allocated for an object and how long the storage allocation continues to exist. It also determines the
scope which specifies the part of the program over which a variable name is visible, i.e. the variable is
accessible by name. This chapter deals with the various storage classes available in C.

6.1 Storage class specifiers


C supports the following four different storage classes

1. Auto / Automatic
2. Register
3. External
4. Static

6.1.1 Auto / Automatic variables


They are declared at the start of a block. Memory is allocated automatically upon entry to a block and freed
automatically upon exit from the block. The scope of automatic variables is local to the block in which they are
declared, including any blocks nested within that block. For these reasons, they are also called local
variables. No block outside the defining block may have direct access to automatic variables, i.e. by name.
Of course, they may be accessed indirectly by other blocks and/or functions using pointers.

Automatic variables may be specified upon declaration to be of storage class auto. However, it is not
required; by default, storage class within a block is auto. Automatic variables declared with initializers are
initialized each time the block in which they are declared is entered.

6.1.2 Register variables

Register variables are a special case of automatic variables. Automatic variables are allocated storage in the
memory of the computer; however, for most computers, accessing data in memory is considerably slower
than processing in the CPU. These computers often have small amounts of storage within the CPU itself
where data can be stored and accessed quickly. These storage cells are called registers.

Normally, the compiler determines what data is to be stored in the registers of the CPU at what times.
However, the C language provides the storage class register so that the programmer can ``suggest'' to the
compiler that particular automatic variables should be allocated to CPU registers, if possible. Thus, register
variables provide a certain control over efficiency of program execution. Variables which are used repeatedly
or whose access times are critical may be declared to be of storage class register.

Register variables behave in every other way just like automatic variables. They are allocated storage upon
entry to a block; and the storage is freed when the block is exited. The scope of register variables is local to
the block in which they are declared. Rules for initializations for register variables are the same as for
automatic variables.

003-00002 Page-49

Copyright CoreEL Technologies (I) Pvt. Ltd.


int main()
{
register float a=0;
auto int bb=1;
auto char cc=’w’;
/* rest of the program*/
}

The above program shows a code fragment for a main() function that uses register as well as auto storage
class. The class specifier simply precedes the type specifier in the declaration. Here, the variable, a, should
be allocated to a CPU register by the compiler, while bb and cc will be allocated storage in memory. Note, the
use of the auto class specifier is optional.

Finally, even the availability of register storage does not guarantee faster execution of the program. For
example, if too many register variables are declared, or there are not enough registers available to store all of
them, values in some registers would have to be moved to temporary storage in memory in order to clear
those registers for other variables. Thus, much time may be wasted in moving data back and forth between
registers and memory locations. In addition, the use of registers for variable storage may interfere with other
uses of registers by the compiler, such as storage of temporary values in expression evaluation. In the end,
use of register variables could actually result in slower execution. Register variables should only be used if
you have a detailed knowledge of the architecture and compiler for the computer you are using.

6.1.3 External variable

All variables we have seen so far have had limited scope (the block in which they are declared) and limited
lifetimes (as for automatic variables). However, in some applications it may be useful to have data which is
accessible from within any block and/or which remains in existence for the entire execution of the program.
Such variables are called global variables.

Global variables may be declared outside any function block in a source code file the same way any other
variable is declared; by specifying its type and name. Memory for such variables is allocated when the
program begins execution, and remains allocated until the program terminates. For most C implementations,
every byte of memory allocated for an external variable is initialized to zero.

All functions following the declaration may access the global variable by using its name. However, if a local
variable having the same name is declared within a function, references to the name access the local variable
cell. The following program shows an example of external / global variables and their scope

003-00002 Page-50

Copyright CoreEL Technologies (I) Pvt. Ltd.


#include<stdio.h>
#include<stdlib.h>
void next(void); void next1(void);

int a1=1; global scope*/ /*scope main(), next(), next1()*/


int main()
{
system("clear");
printf("Scope of external variable
variable\n"); a1=2;
printf("a1=%d\n",a1);
n",a1);
next();
n",a1);
printf("a1=%d\n",a1);
next1(); printf("a1=%d
printf("a1=%d\n", a1);
return 0;
}
int b1=0; /* global variable, sscope:
cope: global to next , next1 */
/* main can't access b1*/
void next(void)
{
char a1; /*auto var. scope loacl to next()*/
/*next canntot access external a1*/
a1='a'; /* loal auto var*/
b1=77; /* external var */
printf("a1=%c, b1=%d
b1=%d\n",a1,b1);
a1='a';
}
void next1(void)
{
float b1; /*auto var scope loacl to next1()*/
/*next1() cannot access global b1*/
b1=19.2; /*auto var*/
a1=13;
}
Storage allocations for global variables

Global variables may be initialized in declarations just as automatic variables; however, the initializers must
be constant expressions. The initialization is done only once at compile time, i.e. when memory is allocated
for the variables.

Variable Definition vs Declaration

When we have ``declared'' a variable, we have meant that we have told the compiler about the variable; i.e.
its type and its name, as well as allocated a memory cell for the variable (either locally or globally). This latter
la
action of the compiler, allocation of storage, is more properly called the definition of the variable. The stricter
definition of declaration is simply to describe information ``about'' the variable.

For automatic and register variables, there is no difference between definition and declaration. The process of
declaring an automatic or a register variable defines the variable name and allocates appropriate memory.
However, for external variables, these two operations may occur independently. This is important
i because
memory for a variable must be allocated only once, to ensure that access to the variable always refers to the

003-00002 Page-51

Cop
opyright CoreEL Technologies (I) Pvt. Ltd.
same cell. Thus, all variables must be defined once and only once. If an external variable is to be used in a
file other than the one in which it is defined, a mechanism is needed to ``connect'' such a use with the
uniquely defined external variable cell allocated for it. This process of connecting the references of the same
external variable in different files is called resolving the references.

External variables may be defined and declared with a declaration statement outside any function, with no
storage class specifier. Such a declaration allocates memory for the variable. A declaration statement may
also be used to simply declare a variable name with the extern storage class specifier at the beginning of the
declaration. Such a declaration specifies that the variable is defined elsewhere, i.e. memory for this variable is
allocated in another file. Thus, access to an external variable in a file other than the one in which it is defined
is possible if it is declared with the keyword extern; no new memory is allocated. Such a declaration tells the
compiler that the variable is defined elsewhere, and the code is compiled with the external variable left
unresolved. The reference to the external variable is resolved during the linking process.

Here are some examples of declarations of external variables that are not definitions:

extern char stack[10];

extern int stkptr;

These declarations tell the compiler that the variables stack[] and stkptr are defined elsewhere, usually in
some other file. If the keyword extern were omitted, the variables would be considered to be new ones and
memory would be allocated for them. Remember, access to the same external variable defined in another file
is possible only if the keyword extern is used in the declaration.

6.1.4 Static Variables

External variables have global scope across the entire program (provided extern declarations are used is files
other than where the variable is defined), and a lifetime over the entire program run. The storage class, static,
similarly provides a lifetime over the entire program, however; it provides a way to limit the scope of such
variables, and Static storage class is declared with the keyword static as the class specifier when the variable
is defined. These variables are automatically initialized to zero upon memory allocation just as external
variables are. Static storage class can be specified for automatic as well as external variables.

Static automatic variables continue to exist even after the block in which they are defined terminates. Thus,
the value of a static variable in a function is retained between repeated function calls to the same function.
The scope of static automatic variables is identical to that of automatic variables, i.e. it is local to the block in
which it is defined; however, the storage allocated becomes permanent for the duration of the program. Static
variables may be initialized in their declarations; however, the initializers must be constant expressions, and
initialization is done only once at compile time when memory is allocated for the static variable.

Example : Program to count the no. Of times a function is called.

003-00002 Page-52

Copyright CoreEL Technologies (I) Pvt. Ltd.


#include <stdio.h>
void funcallcount(void);

int main( )
{
char ch ;
do
{
funcallcount ( );
printf(“\nDo you want to call again. \
Enter y to continue :”);
c = getchar( );
} while (ch == ‘y’);
return 0;
}
void funcallcount(void)
{
static int count;
count++;
printf(“Function invoked %d times”, count);
}

Static storage class designation can also be applied to global variables. The only difference is that static
global variables can be accessed only in the file in which they are defined. No other source file can access
static variables that are defined in another file.

Storage class
specifier Scope Lifetime Storage Default value Linkage
area
within block stack segment garbage value
auto block no

within block CPU registers garbage value


register block no

Local static throughout data segment


block program 0 no

Global static throughout data segment internal linkage


file program 0

entire program throughout data segment external


extern program 0 linkage

003-00002 Page-53

Copyright CoreEL Technologies (I) Pvt. Ltd.


Few rules for usage of storage classes

1. Use static storage class only if you want the value of a variable to persist between different function
calls.
2. Use register storage class for only those variables which are being used very often in the program.
Application of register storage class is loop counters which get used a number of times in a program.

6.2 Storage classes for functions

Like variables, functions in C have a storage class and scope. All functions in C are external by default and
are accessible to all source files. However, functions may be declared to be of static class, in which case they
are accessible only to functions in the file in which they are defined, not to functions in other files. This is
another way of hiding information. Information hiding makes these static function names invisible to all other
files; thus, these names may be used to define other functions elsewhere. You can declare a function as
static by using the keyword static.

003-00002 Page-54

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 7

THE PREPROCESSOR DIRECTIVES IN C

Introduction

The preprocessor is a program that is invoked by the compiler to process code before compilation.
Commands for that program, known as directives, are lines of the source file beginning with the character #,
which distinguishes them from lines of source program text. The effect of each preprocessor directive is a
change to the text of the source code, and the result is a new source code file, which does not contain the
directives. The preprocessed source code, an intermediate file, must be a valid C program because it
becomes the input to the compiler.

7.1 Preprocessor Directives

Preprocessor directives follow the special syntax.


 They begin with # in column one and usually do not terminate with a semicolon.
 The macro templates and their expansion are separated by space and not =.
 The directives can be placed anywhere in a program but are most often placed at the beginning of a
program, before main( ), or before the beginning of a particular function.

The preprocessor directives can be divided into following categories


1. Macro substitution.
2. File inclusion.
3. Conditional inclusion.
4. Miscellaneous directives.

In this particular module, we are going to concentrate only on Macro substitution.

7.1.1 Macros

003-00002 Page-55

Copyright CoreEL Technologies (I) Pvt. Ltd.


A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by
the contents of the macro. There are two kinds of macros.
1. Macro without parameters / Object-like macros
2. Macro with parameters / function-like macros

7.1.1.1 Macro without parameters

We create macros with the `#define' directive. Syntax is

#define identifier token-string

The #define directive, substitutes token-string for all subsequent occurrences of an identifier in the source
file. The identifier is replaced only when it forms a token.

Example

#define TRUE 1
#define SIZE 10
#define PI 3.141517
Note: macro templates (macros) are normally written in capitals. It is a convention to write all macros in
capitals to identify them as symbolic constant.

Example: Program to find the area and circumference of a circle


#include <stdio.h>
#define PI 3.14159
int main( )
{
int radius = 4;
float area, circumference ;
area = PI * radius * radius;
printf(“The area = %f “,area);
circumference = 2 * PI * radius;
printf(“The circumference = %f “, circumference);
return 0;
}

#define versus const


• A const object is subject to the scoping rules for variables, whereas a constant created using #define is
not.
• Unlike a const object, the value of a macro does not appear in the intermediate source code used by the
compiler because they are expanded inline.
The inline expansion makes the macro value unavailable to the debugger.
• A macro can be used in a constant expression, such as an array bound, whereas a const object cannot.

003-00002 Page-56

Copyright CoreEL Technologies (I) Pvt. Ltd.


7.1.1.2 Macro without parameters

You can define macros with parameters. When the preprocessor expands such a macro, it incorporates
arguments you specify for each use of the macro in the replacement text. Macros with parameters are often
called function-like macros. Syntax is

#define identifier(identifier, …, identifier) token-string

/* Program prints square of a number */


Source Code : Square.c Expanded Code : gcc –E Square.c
#define SQR(x) x * x
int main( ) int main( )
{ {
int x = 2; int x = 2;
printf(“ %d “ ,SQR(x)); printf(“ %d “ ,x * x);
} }
Output : 4

Note
There should not be a space between macro template and its arguments

GREAT(a,b) /* correct */
GREAT (a,b) /* error no space allowed */

The entire macro expansion should be enclosed within parentheses.

SQUARE(n,m) (((n)*(n))/(m)) /* correct */


SQUARE(n,m) n*n /m /* The expected result may not be obtained */

The problem with side effects is that macros don’t evaluate their arguments; they just paste them into the
macro text when performing the substitution.

#define SQR(x) x * x
int main( ) int main( )
{ {
int x = 2; int x = 2;
printf(“%d”,SQR(x + 3)); printf(“%d ” ,x+3*x+3);
} }
Output : 11 instead of 25

#define SQR(x) ((x) * (x))


int main( )
{
int x = 2;
printf(“ Result = %d “ , SQR(x + 2) );
}
There are some more side effects which cannot be eliminated by using paranthesis

003-00002 Page-57

Copyright CoreEL Technologies (I) Pvt. Ltd.


#define SQR(x) ((x) * (x))
int main( )
{
int x = 2;
printf(“ Result = %d “ , SQR(++x) );
}
After Expansion
int main( )
{
int x = 2;
printf(“ Result = %d “ , ++x * ++x);
}
Output : 16 and not 9.

7.1.1.3 Macros versus Functions

Whenever there is a function call the control is passed to the function and after executing the function the
control is returned back to the calling function, hence the program has to save the required information about
the currently executing function before switching to the called function in order to continue the execution of
the current function later. This is an overhead and therefore slows down the program. This can be avoided
using macros; in a macro call the preprocessor replaces the macro with its macro expansion. Macros
increase the program speed, but they use more memory. Functions use more CPU time but less memory.
Hence small functions can be replaced by macros.

Argument to function are evaluated and then passed where as in macros arguments are expanded and then
evaluated.

7.1.1.4 Scope of Macro Names (#undef)


A preprocessor undef directive causes the preprocessor to end the scope of a preprocessor definition. If the
identifier is not currently defined as a macro, #undef is ignored.

Example of #undef Directives

The following directives define BUFFER and SQR

#define BUFFER 512


#define SQR(x) ((x) * (x))

The following directives nullify these definitions:


#undef BUFFER
#undef SQR

Any occurrences of the identifiers BUFFER and SQR that follow these #undef directives are not replaced with
any replacement tokens. Once the definition of a macro has been removed by a #undef directive, the
identifier can be used in a new #define directive.

003-00002 Page-58

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 8

ARRAYS IN C

Introduction

The C language provides a convenient way of grouping a set of variables of same type under a single
variable name; the array. Array is one of the derived data types in C. By definition, an array is a group of
consecutive memory locations of same type represented by a single name. In this chapter we will see in detail
about the array data structure in C. Important string handling functions and character handling functions are
also introduced in this chapter.

8.1 Overview of arrays

Arrays are most useful when they have a large number of elements: that is, in cases where it would be
completely impractical to have a different name for every storage space in the memory. Suppose we had a
set of grades that we wished to read into the computer and suppose we wished to perform some operations
on these grades, we will quickly realize that we cannot perform such an operation until each and every grade
has been entered since it would be quite a tedious task to declare each and every student grade as a variable
especially since there may be a very large number.

In C we can define a variable called grade, which represents not a single value of grade but an entire set of
grades. Each element of the set can then be referenced by means of a number called as index number or
subscript.

8.2 Declaration of arrays

Like any other variable arrays must be declared before they are used. The general form of declaration is:

<type> <variable-name>[<no_of_elements>];

The type specifies the type of the elements that will be contained in the array, such as int float or char and the
size indicates the maximum number of elements that can be stored inside the array.

Example : int grade [30];

Declares the grade to be an array containing 50 integer elements. The array elements are accessed using
subscript. The array elements index or subscript begins with number zero. So grade [0] refers to the first
element of the array. . Any subscripts 0 to 29 are valid.

8.3 Memory layout and accessing the array elements


The declaration

int Values [ MAX ]; ------- would reserve enough space for an array called values that could hold up to 5
integers. Refer to the below given picture to conceptualize the reserved storage space.

Values [0]
Values [1]

003-00002 Page-59

Copyright CoreEL Technologies (I) Pvt. Ltd.


Values [2]
Values [3]
Values [4]

The array values stored in the memory.

Once the array is declared the computer reserves the amount of memory specified in the declaration. In the
above declaration 5 x 4 bytes of memory is reserved (32 bit compiler).

You can use these ”array subscript expressions” anywhere, like the name of a simple variable, for
example:
Value [0] = 10;
Value [1] = 20;
Value [2] = Value [0] + Value [1];

Notice that the subscripted array references can appear on either side of the assignment operator. The
subscript does not have to be a constant like 0 or 1; it can be any integral expression. For example, it’s
common to loop over all elements of an array:
#define MAX 10
int i;
for(i = 0; i < MAX ; i++)
Value [ i ] = 0;

This loop sets all ten elements of the array value to 0. Arrays are a real convenience for many problems, but
there is not a lot that C will do with them for you automatically. In particular, you can neither set all elements
of an array at once nor assign one array to another; both of the assignments are illegal

Value = 0; /* WRONG */
and
int b[MAX]; b = Value; /* WRONG */
To set all of the elements of an array to some value, you must do so one by one, as in the loop example
above. To copy the contents of one array to another, you must again do so one by one:
int b[MAX];
for(i = 0; i < MAX; i ++)
b [i] = Value [i];
Remember that for an array declared

int Value[10];

There is no element Value[10]; the topmost element is Value [9]. This is one reason that zero-based loops are
also common in C. Note that the for loop
for (i = 0 ; i < MAX ; i++)

In the little examples so far, we’ve always looped over all 10 elements of the sample array a. It’s common,
however, to use an array that’s bigger than necessarily needed.
We have to ensure that count value is always less than or equal to the number of elements actually declared
in Value.

003-00002 Page-60

Copyright CoreEL Technologies (I) Pvt. Ltd.


8.4 Initialization of arrays

We can initialize the elements in the array in the same way as the ordinary variables when they are We can
initialize the elements in the array in the same way as the ordinary variables when they are declared. The
general form of initialization of arrays is:

data_type array_name[size] = {list of values};


The values in the list are separated by commas, for example the statement
int number [3] = {0, 0}; ---------- will declare the array size as an array of size 3 and will assign zero to each
element if the number of values in the list is less than the number of elements, then only that many elements
are initialized. The remaining elements will be set to zero automatically.
In the declaration of an array the size may be omitted, in such cases the compiler generates the code to
allocate enough space for all initialized elements. For example the statement

int counter[ ] = {1,1,1,1};

Will declare the array to contain four elements with initial values 1.

8.5 Bounds Checking

In C there is no bound checking to check whether the subscript used for an array exceeds the size of the
array. Data entered with subscript exceeding the array size will simply be placed in memory outside the array;
probably overwrite the other’s data. There will be no error message displayed to warn. In some cases the
system may hang. Hence it is the programmer’s responsibility to keep track of the array size.

Program to Calculate the sum of all the elements of array


#include <stdio.h>
#define SIZE 5
int main( )
{
int a[SIZE],sum , i;

printf("\n ENTER THE ELEMENTS OF ARRAY (%d) ",SIZE);


for(i = 0 ; i < SIZE ; i++)
scanf(“%d”,&a[i]);

for(sum = i = 0 ; i < SIZE ; i++)


sum = sum + a[i];

printf("\n Sum of All Elements = %d ",sum);


}

8.6 Passing array as argument to function

003-00002 Page-61

Copyright CoreEL Technologies (I) Pvt. Ltd.


When you want to pass an array to function, just mention the name of the array while calling the function. At
the receiving end use an array notation. Arrays do not carry information about their own sizes. If array size
is needed, you must supply it as an additional argument
When you pass an array, it is passed by address and any changes done to an array will reflect the actual
array.

Passing an array to function


int main()
{
int arr[5] ;
read_array(arr , 5);
}
Receiving array in a function
void read_array(int arr[ ] , int n)
{ }

Function to read the element in an array


void read_array(int arr[ ],int n)
{
int i;
for(i = 0 ; i < n ; i++)
scanf(“%d”,&arr [i]);
}

8.7 Searching Algorithm

8.7.1 Linear Search

Linear search is the simplest search algorithm.


It compares each element of the array with the key element in sequence. It can be applied on sorted and
unsorted arrays.
Its worst case complexity is proportional to the number of elements in the list O(n). It is suitable for smaller
list.

Program to search an element using linear search


#include <stdio.h>
#define MAX_SIZE 10
int linear(int arr[ ],int n,int key);
void read_array(int arr[ ],int n);
int main( )
{
int n,i,arr [MAX_SIZE],key, pos;
printf(“\n Enter the no. of elements : “);
scanf(“%d”,&n);
if(n < 0 || n > MAX_SIZE)
{
printf(”INVALID SIZE”);
return 1;
}
printf(“\n Enter %d elements “,n);

003-00002 Page-62

Copyright CoreEL Technologies (I) Pvt. Ltd.


read_array(arr,n);
printf(“\n Enter the key element to search : “);
scanf(“%d”,&key);
pos = linear(arr,n,key);
if(pos)
printf(“\n Element found at pos %d”,pos);
else
printf(“\n Element not found “);
}

Function for linear search

int linear(int arr[ ],int n,int key)


{
int i;
/* Searching */
for(i = 0 ; i < n ; i++)
{
if(key == arr[i])
{ // If key element is found
return i + 1;
}
}
return 0; // If key element not found
}

8.7.2 Binary Search


It is a fast way to search for key element in a sorted array. The idea is to look at the element in the middle. If
the key is equal to that, the search is finished. If the key is less than the middle element, do a binary search
on the first half. If it’s greater, do a binary search of the second half.

The advantage of a binary search over a linear search is, it takes less number of searches. The worst case
complexity is O(log2n). To search for an element in a list of 1000 elements, binary search requires max of 10
comparisons.

This performance comes at a price – the array must be sorted first. Because sorting isn’t a fast operation, it
may not be worth the effort to sort when there are only a few searches.

003-00002 Page-63

Copyright CoreEL Technologies (I) Pvt. Ltd.


Function for binary search
int binary_search(int a[ ],int n,int key)
{
int low,mid,high;
low = 0;
high = n-1;
while(low <= high)
{
mid = (low + high) / 2;
if(key == a[mid])
{
return mid+1;
}
if(key > a[mid])
low = mid+1;
else
high = mid-1;
}
return 0;
}

8.8 Sorting

Introduction
What will you do if you were asked to search for a particular telephone number in a directory? You will ask for
the surname of the particular person and as the directory is sorted in an ascending order of alphabets, it will
not be difficult to find the telephone number. But if the case is reverse, you know the phone number and you
wish to find the name of the person using the telephone directory, will it be easy like the first case. One would
have to search the entire directory sequentially for this purpose. Data cannot be retrieved efficiently if it is not
placed in a particular format.
To convert an unordered list of data items into an ordered list is known as sorting. We can define sorting as
arrangement of elements in a list according to the increasing or decreasing (ascending/descending) value of
each element. There are many programs and processes in the computer, which require sorted data. Every
time there is a new entry sorting is done and it is put in its proper position. A computer on an average spends
25 to 40 % of its time in sorting. The only way to search any element in an unordered list is to perform
sequential search. If we have a list having thousands of records then this sequential search will take a very
large amount of time to search a given element. The worst part comes when you search the whole list for a
particular record, only to find that it does not exist. Sorting is one of the most important operations to be
performed on the list. The elements in the list may contain single values or records. Sorting process should be
done using minimum amount of time. There has been much work done to find optimal algorithms to perform
sorting under various environments.

Sorting techniques

1. Bubble Sort 4. Merge Sort

2. Selection Sort 5. Quick Sort

3. Insertion Sort

003-00002 Page-64

Copyright CoreEL Technologies (I) Pvt. Ltd.


8.8.1 Bubble sort

Bubble sort is a simple sorting algorithm. It works by repeatedly stepping through the list to be sorted,
comparing two items at a time and swapping them if they are in the wrong order. The pass through the list
is repeated until no swaps are needed, which indicates that the list is sorted. The algorithm gets its name
from the way smaller elements "bubble" to the top of the list. Because it only uses comparisons to operate
on elements, it is a comparison sort.

Bubble sort has worst-case complexity О(n²), where n is the number of items being sorted. There exist
many other sorting algorithms with substantially better worst-case complexity O(n log n), meaning that
bubble sort should not be used when n is large.

Step-by-step example
Let us take the array of numbers "5 1 4 2 8", and sort the array from lowest number to greatest number
using bubble sort algorithm. In each step, elements written in bold are being compared.
First Pass
(5 1 4 2 8) (1 5 4 2 8) Here, algorithm compares the first two elements, and swaps them.
(1 5 4 2 8) (1 4 5 2 8)
(1 4 5 2 8) (1 4 2 5 8)
(1 4 2 5 8) (1 4 2 5 8)

Now, since these elements are already in order, algorithm does not swap them.

Second Pass
(1 4 2 5 8) (1 4 2 5 8)
(1 4 2 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)

Now, the array is already sorted, but our algorithm does not know if it is completed. Algorithm needs one
whole pass without any swap to know it is sorted.

Third Pass
(1 2 4 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)
Finally, the array is sorted, and the algorithm can terminate...

003-00002 65
Page-65

Copyright CoreEL Technologies (I) Pvt. Ltd.


Function for bubble sort

void Bubble_Sort (int *a, int n)


{
int pass, comp,temp;
for (pass = 1; pass < n ; pass++)
{
for (comp = 0; comp < n - pass; comp++)
{
if(a [comp ] >= a [comp + 1 ])
{
temp = a [comp ];
a[comp ] = a[comp + 1 ];
a[comp + 1 ] = temp;
}
}
}
}

8.8.2 Selection Sort

The idea of Selection Sort is rather simple. It basically determines the minimum (or maximum) of the list
and swaps it with the element at the index where it is supposed to be.

The algorithm works as follows


• Find the minimum value in the list
• Swap it with the value in the first position
• Repeat the steps above for remainder of the list (starting at the second position)

Effectively, we divide the list into two parts: the sublist of items already sorted, which we build up from left
to right and is found at the beginning, and the sublist of items remaining to be sorted, occupying the
remainder of the array.

Here is an example of this sort algorithm sorting five elements:


31 25 12 22 11
11 25 12 22 31
11 12 25 22 31
11 12 22 25 31

Analysis

Selecting the lowest element requires scanning all n elements (this takes n - 1 comparisons) and then
swapping it into the first position. Finding the next lowest element requires scanning the remaining n - 1
2
elements and so on, for (n - 1) + (n - 2) + ... + 2 + 1 = n(n - 1) / 2 = O(n ) comparisons. Each of these
scans requires one swap for n - 1 elements (the final element is already in place). Thus, the comparisons
2
dominate the running time, which is O(n ).

003-00002 66
Page-66

Copyright CoreEL Technologies (I) Pvt. Ltd.


Function for selection sort

void selectionsort(int *a,int n)


{
int pass,leastindex;
for(pass = 0 ; pass < n-1 ; pass++)
{
leastindex = findmin(a,pass,n);
swap(a,pass,leastindex);
}
}

int findmin(int a[ ],int i,int n)


{
int pos = i,j;
for(j = i ; j < n ; j++)
if(a[j] < a[pos])
pos = j;
return pos;
}
void swap(int a[ ],int i,int pos)
{
int temp;
temp = a[i];
a[i] = a[pos];
a[pos] = temp;
}

003-00002 67
Page-67

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 9

STRINGS – CHARACTER ARRAYS

Introduction

A string is a sequence of characters terminated by ‘\0’ character. The null character, ’\0’, is used to mark
the end of a string (because it is distinct from all the “real” characters) that is stored in an array of
characters. The end marker allows your program to read the array one character at a time and know that
it should stop reading when it reads the ’\0’. When an array of characters is used in this way, the array is
often called a string variable.

Although the null character ’\0’ is written using two symbols, it is a single character that fits in one variable
of type char or one indexed variable of an array of characters. A string variable is just an array of
characters. Thus, the following array declaration provides us with a string variable capable of storing a
string value with nine or fewer characters:

char s[10];

As the strings should always end with a ’\0’ and it occupies one element of the array, the length of the
longest string that the array can hold is one less than the size of the array. This chapter concentrates on
declaring and initializing the character arrays and the library functions which can be used to manipulate
the strings.

9.1 Initializing Strings

You can initialize a string variable when you declare it as shown below

char myMessage[20] = "Hi there.";

Notice that the string assigned to the string variable need not fill the entire array. When you initialize a
string variable, you can omit the array size and C compiler will automatically make the size of the string
variable one more than the length of the quoted string. (The one extra indexed variable is for ’\0’.)

Example
char shortString[ ] = "abc";
is equivalent to
char shortString[4] = "abc";

Do not confuse the following initializations

char shortString[ ] = "abc";


and
char shortString[ ] = {’a’, ’b’, ’c’};

003-00002 68
Page-68

Copyright CoreEL Technologies (I) Pvt. Ltd.


They are not equivalent. The first of these two initializations places the null character ’\0’ in the array
after the characters ’a’, ’b’, and ’c’. The second one does not put a ’\0’ in the array.

A string variable is an array, so it has indexed variables that can be used just like those of any other
array. For example, suppose your program contains the following string variable declaration:

char ourString[5] = "Hi";

With ourString declared as above, your program has the following indexed variables:
ourString[0], ourString[1], ourString[2], ourString[3], and ourString[4]. For example, the following will
change the string value in ourString to uppercase:

int index = 0;
while (ourString[index] != ’\0’)
{
ourString[index] = toupper(ourString[index] );
index++;
}

Consider the above while loop that changes characters in the string variable ourString. That while loop
changes characters until it encounters a ’\0’. If the loop never encounters a ’\0’, then it could change a
large chunk of memory to some unwanted values, which could make your program do strange things. As
a safety feature, it would be wise to rewrite the above while loop as follows, so that if the null character
’\0’ is lost, the loop will not inadvertently change memory locations beyond the end of the array:

int index = 0;
while ((ourString[index] != ’\0’) && (index < SIZE))
{
ourString[index] = ’X’;
index++;
}

SIZE is a macro whose value is equal to the declared size of the array ourString.

9.2 String Library Functions

9.2.1 Strcpy and Strncpy

String values and string variables are not like values and variables of other data types, and many of the
usual operations do not work for strings. You cannot use a string variable in an assignment statement
using =. If you use == to test strings for equality, you will not get the result you expect. The reason for
these problems is that strings and string variables are arrays.

Assigning a value to a string variable is not as simple as it is for other kinds of variables. The following is
illegal:

char aString[10];

003-00002 69
Page-69

Copyright CoreEL Technologies (I) Pvt. Ltd.


aString = "Hello";
Although you can use the equal sign to assign a value to a string variable when the variable is declared,
you cannot do it anywhere else in your program. Technically, the use of the equal sign in a declaration, as
in

char happyString[7] = "DoBeDo";

is an initialization, not an assignment. If you want to assign a value to a string variable, you must use the
predefined function strcpy as shown below:

strcpy(aString, "Hello");

This will set the value of aString equal to "Hello". Unfortunately, this version of the function strcpy does
not check to make sure the copying does not exceed the size of the string variable that is the first
argument.

To avoid this problem there is strncpy function that takes a third argument which gives the maximum
number of characters to copy. If this third parameter is set to one less than the size of the array variable
in the first argument position, then you obtain a safe version of strcpy.

Example
char anotherString[10];
strncpy(anotherString, aStringVariable, 9);

With strncpy, at most nine characters (leaving room for ’\0’) will be copied from the string variable
aStringVariable no matter how long the string in aStringVariable may be.

9.2.3 Strcmp
You also cannot use the operator == in an expression to test whether two strings are the same.

Things are actually much worse than that. You can use == with strings, but it does not test for the strings
being equal. So if you use == to test two strings for equality, you are likely to get incorrect results, but no
error message!

To test whether two C-strings are the same, you can use the predefined function strcmp.

Example
if (strcmp(cString1, cString2))
printf("The strings are NOT the same.");
else
printf("The strings are the same.");

Note that the function strcmp works differently than you might guess. The comparison is true if the strings
do not match. The function strcmp compares the characters in the string arguments a character at a time.
If at any point the numeric encoding of the character from cString1 is less than the numeric encoding of

003-00002 70
Page-70

Copyright CoreEL Technologies (I) Pvt. Ltd.


the corresponding character from cString2, the testing stops at that point and a negative number is
returned. If the character from cString1 is greater than the character from cString2, a positive number is
returned. (Some implementations of strcmp return the difference of the character encoding, but you
should not depend on that.) If the strings are the same, a 0 is returned. The ordering relationship used for
comparing characters is called lexicographiC order.C does not provide any operator which manipulates
entire strings at once.

9.2.4 Strlen
To know the length of the string strlen ( ), function can be used. It returns the length of the string (i.e. the
number of characters in it), excluding the ‘\0’.

char str[ ] = "abc";


int len = strlen(str);
printf("length= %d\n", len);
The output will be length=3;
char str[ ] = “abc”;
int size = sizeof(str);
printf("size= %d\n", size);
It will print size=4.(including ‘\0’).
Note : sizeof( ) is not a function but it is an operator.

9.2.5 Strcat
Strcat concatenates two strings.
char dst[20] = "Hello";
char src[ ] = "world!";
printf("%s\n", dst);
strcat(dst, src);
printf("%s\n",dst);
Notice that we declared dst with extra space, to make room to append src
string.

Like the above examples, strings are manipulated via special routines available from the standard string
library string.h. Below table contains a few of the most commonly used functions from the string library
with the header file <string.h>.

003-00002 71
Page-71

Copyright CoreEL Technologies (I) Pvt. Ltd.


Other String Library Functions

FUNCTION DESCRIPTION CAUTIONS


strcpy(Target_String_Var , Copies the string value Src_String into Does not check to make sure
Src_String) the string variable Target_String_Var. Target_String_Var is large
enough to hold the value
Src_String.
strncpy(Target_tring_Var , The same as the two-argument strcpy If Limit is chosen carefully, this is
Src_String, Limit) except that at most Limit characters are safer than the two-argument
copied. version of strcpy.
strcat(Target_String_Var,S Concatenates the string value Does not check to see that
rc_String) Src_String onto the end of the C-string Target_String_Var is large
in the string variable Target_String_Var. enough to hold the result of the
concatenation.
strncat(Target_String_Var , The same as the two argument strcat If Limit is chosen carefully, this is
Src_String, Limit) except that at most Limit characters are safer than the two-argument
appended. version of strcat.
strlen(Src_String) Returns an integer equal to the length
of Src_String. (The null character, ’\0’,
is not counted in the length.)
strcmp(String_1,String_2) Returns 0 if String_1 and The order is lexicographic.
String_2 are the same. If String_1 equals String_2, this
Returns a function returns 0, which converts
value < 0 if String_1 is less than to false. Note that this is the
String_2. reverse of what you might expect
Returns a value > 0 if it to return when the strings are
String_1 is > than String_2 equal.
( that is returns a nonzero value if
String_1 and String_2 are different).
strncmp(String_1,String_2, The same as the two-argument strcat If Limit is chosen carefully, this is
Limit) except that at most Limit characters are safer than the two-argument
compared. version of strcmp.

strchr(string , character) Returns a pointer to the first occurrence


of the character in the string.
strrchr(string , character) Returns a pointer to the last occurrence
of the character in the string.

003-00002 72
Page-72

Copyright CoreEL Technologies (I) Pvt. Ltd.


9.3 String input and output

9.3.1 Character level I/O


C provides (through its libraries) a variety of I/O routines. At the character level, getchar ( ) reads one
character at a time from stdin, while putchar( ) writes one character at a time to stdout. For example,
consider

/*program prints number of characters and number of newlines*/


#include<stdio.h>
int main( )
{
int c, nc = 0, nl = 0;
while ((c = getchar( )) != EOF)
{
nc++;
if (c == '\n') nl++;
}
printf("Number of characters = %d, number of lines = \%d\n", nc, nl);
return 0;
}

To read/print a string (sequence of characters), C provides %s format specifier.


#include<stdio.h>
#define SIZE 20
int main( )
{
char name[SIZE];
printf(“\n ENTER THE NAME :”);
scanf(“ %s”,name);
printf(“\n THE ENTERED NAME IS %s”,name);
return 0;
}
Output:
ENTER THE NAME: RAM
THE ENTERED NAME IS RAM
ENTER THE NAME : BILL GATES
THE ENTERED NAME IS BILL

Observe that during the second execution, only first name (BILL) is accepted. This is because if scanf
sees a space it assumes to be the end of input. If you want to accept multi-word names use fgets.

003-00002 73
Page-73

Copyright CoreEL Technologies (I) Pvt. Ltd.


9.3.2 Fgets
Syntax is

char *fgets(char *line, int maxline, FILE *fp);

fgets( ) reads a line of text including the newline from fp into the character array line. At most maxline-1
characters will be read. A ‘\0’ is stored after the last character in the buffer.

#include<stdio.h>
#define SIZE 20
int main()
{
char name[SIZE];
printf(“\n ENTER THE NAME :”);
fgets(name,SIZE,stdin);
printf(“\n THE ENTERED NAME IS %s”,name);
return 0;
}
Output:
ENTER THE NAME : BILL GATES
THE ENTERED NAME IS BILL GATES
9.3.3. Sscanf
sscanf reads from a string instead of the standard input. Syntax is

int sscanf(char *string, char *format, arg1, arg2, ...)

#include<stdio.h>
#define SIZE 20
int main()
{
char date[SIZE];
int dd,mm,yy;
printf(“ENTER THE DATE :”);
fgets(date,SIZE,stdin);
if(sscanf(date,”%d %d %d”,&dd,&mm,&yy) != 3)
printf(“INVALID DATE\n”);
else
{
printf(“ VALID DATE \n“);
printf(“ Day = %d Month = %d Year = %d”,dd,mm,yy);
}
return 0;
}

003-00002 74
Page-74

Copyright CoreEL Technologies (I) Pvt. Ltd.


9.3.4 sprintf

The function sprintf does the same operations as printf does, but stores the output in a string: The syntax
is

int sprintf(char *string, char *format, arg1, arg2, ...);

sprintf formats the arguments in arg1, arg2, etc., according to format as before, but places the result in
string instead of the standard output; string must be big enough to receive the result.

#include<stdio.h>
#define SIZE 20
int main()
{
char regno[SIZE];
int rollno,yearofadmission;
char branch_code[3],college_code[3];
printf(“ENTER THE COLLEGE CODE :”);
scanf(“%2s”,college_code);
printf(“ENTER THE BRANCH CODE :”);
scanf(“%2s”,branch_code);
printf(“ENTER THE YEAR OF ADMISSION :”);
scanf(“%2d”,&yearofadmission);
printf(“ENTER THE ROLL NO :”);
scanf(“%3d”,&rollno);
sprintf(regno,”%s%02d%s%03d”,college_code,yearofadmission,\
branch_code, rollno);
printf(“THE REGNO = %s \n“,regno);
return 0;
}

003-00002 75
Page-75

Copyright CoreEL Technologies (I) Pvt. Ltd.


GOOD TO KNOW

CHARACTER CONVERSIONS AND TESTING

The C library ctype.h contains many useful functions to convert and test single characters. The common
functions are prototypes as follows:

Character testing:

int isalnum(int c) -- True if c is alphanumeric. int isalpha(int c) -- True if c is a letter.

int isascii(int c) -- True if c is ASCII .

int iscntrl(int c) -- True if c is a control character. int isdigit(int c) -- True if c is a decimal digit

int isgraph(int c) -- True if c is a graphical character. int islower(int c) -- True if c is a lowercase letter

int isprint(int c) -- True if c is a printable character


int ispunct (int c) -- True if c is a punctuation character. int isspace(int c) -- True if c is a space character.

int isupper(int c) -- True if c is an uppercase letter. int isxdigit(int c) -- True if c is a hexadecimal digit

Character Conversion:

int toascii(int c) -- Convert c to ASCII . tolower(int c) -- Convert c to lowercase. int toupper(int c) -- Convert
c to uppercase.

003-00002 76
Page-76

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 10

POINTERS IN C

Introduction

Pointers are derived data types 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 points to a memory location we can access and change the contents of
this memory location via the pointer. This chapter gives a clear picture about the important aspects of
pointers in C such as reference operator, dereference operator and pointer arithmetic.

10.1 Pointer declaration

A pointer is a variable that contains the memory location of another variable. The syntax is as shown
below.

type * variable name;

You start by specifying the type of data stored in the location identified by the pointer. The asterisk * tells
the compiler that you are creating a pointer variable. Finally you give the name of the variable.

Example:

int * ptr; float * string;

Irrespective of the type of the pointer, pointer always occupies 4 bytes of memory in a 32 bit environment.

10.2 Reference operator (&)

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

10.3 Dereference operator (*)

We have just seen that a variable which stores a reference to another variable is called a pointer.
Pointers are said to "point to" the variable whose address is stored in them.

Using a pointer we can directly access the value stored in the variable which it points to. To do this, we
simply have to precede the pointer's identifier with an asterisk (*), which acts as dereference operator and

003-00002 77
Page-77

Copyright CoreEL Technologies (I) Pvt. Ltd.


that can be literally translated to "value pointed by". Therefore, following with the values of the previous
example, if we write:

Declaring and assigning values to pointers.


#include <stdio.h>
int main( )
{
int x, *ptr_x;
x = 7;
printf("x: address=%p, content=%d\n", &x, x);
ptr_x = &x;
printf("ptr_x: address=%p, content=%p\n", &ptr_x, ptr_x);
printf("*ptr_x => %d\n", *ptr_x);
return 0;
}

10.4 Permissible pointer operations

 A pointer can have the address of an ordinary variable as its content (e.g., pv=&v)
 The content of a pointer can be copied to another pointer variable provided both pointers are of
same type. (e.g., pv = px)
 A pointer variable can be assigned a null(zero) value. (e.g., pv=NULL, where NULL is a symbolic
constant that represents the value 0).
 An integer quantity can be added to or subtracted from a pointer variable. (e.g., pv+3, ++pv, pv –
2, pv--, etc.).
 Pointers can be subtracted if the pointers are of same type. (e.g., pv-px),
 Pointers can be compared using relational operators (e.g., pv>px, pv==py, pv != py, etc.).

10.4.1 Pointer Arithmetic

As mentioned above, there are only two arithmetic operations that you can use for pointers: addition and
subtraction. Let p1 be an integer pointer with a current value of 2000. Also assumes that int is 4 bytes
long. After the expression

p1++;

p1 contains 2004 not 2001. The reason for this is that each time p1 is incremented; it will point to the next
integer. The same is true for decrements. For example, if p1 is 2000 then the statement

p1--; causes p1 to have the value 1996.

Generalizing from the above statements, the following rules govern pointer arithmetic. Each time a pointer
is incremented, it points to the memory location of the next element of its base type. Each time it is
decremented, it points to the location of the previous element.

003-00002 78
Page-78

Copyright CoreEL Technologies (I) Pvt. Ltd.


Besides addition and subtraction of a pointer and an integer, only one other arithmetic operation is
allowed. You can subtract one pointer from another in order to find the number of objects of their base
type that separate the two. All other arithmetic operations are prohibited.

10.5 Non Permissible pointer operations

 Two pointer variables cannot be added. (e.g., pv+px)


 Pointer variable cannot be multiplied by a constant. (e.g., pv*3).
 Two pointer variables cannot be divided or multiplied. (e.g., pv * px, px/py)

10.6 Pointer and arrays

The concept of array is very much bound to the one of pointer. In fact, the identifier of an array is
equivalent to the address of its first element, as a pointer is equivalent to the address of the first element
that it points to, so in fact they are the same concept. For example, supposing these two declarations:

int number[5];
int * p;

The following assignment operation would be valid:

p = number;

After that, p and number would be equivalent and would have the same properties. The only difference is
that we could change the value of pointer p by another one, whereas number will always point to the first
of the 5 elements of type int with which it was defined. Therefore, unlike p, which is an ordinary pointer,
number is an array, and an array can be considered a constant pointer. Therefore, the following allocation
would not be valid:

number = p;

Because numbers is an array, so it operates as a constant pointer, and we cannot assign values to
constants.

number [0] [1] [2] [3] [4]

p p+0 p+1 p+2 p+3 p+4

Figure 8.1 Pointers and Arrays

Due to the characteristics of variables, all expressions that include pointers in the following example are
perfectly valid:

003-00002 79
Page-79

Copyright CoreEL Technologies (I) Pvt. Ltd.


int main ()
{
int numbers[5]; int * p;
p = numbers; *p = 10; p++;
*p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
printf(“%d”, numbers[n] );
return 0;
}

a[5] = 0; // a [offset of 5] = 0
*(a+5) = 0; // pointed by (a+5) = 0

These two expressions are equivalent and valid both if a is a pointer or if a is an array.

10.7 Disadvantages of pointers

Pointers have tremendous power but the power can swing both sides good and evil. When a pointer is
used incorrectly or contains the wrong value, it can be a very difficult to find the bug.

When you use this incorrect pointer to read a memory location, you may be reading an incorrect garbage
value, which if unluckily accepted by your program can result in bugs. Consider a scenario in banking in
which any customers real account value is switched with this garbage value, he can become a millionaire
or beggar in a second, or think that in a rocket launching software you use this incorrect value as
launching angle and crashing the billion dollar masterpiece.

Now when you use this incorrect pointer to write a memory location you may be writing a unknown
memory location. If you have a large memory in the system, maybe you are using an unassigned memory
but if that memory by any luck is a memory used by O.S. or Hardware and you are modifying it, you
maybe corrupting your Operating System software or damaging your hardware and their drivers. Also it is
a possibility that you may be using a memory location already in use by your software storing some
essential data and you are unknowingly modifying it. You may be writing over your own code and data.

Such bugs and errors created by the pointers may not show up immediately but come up later and it is at
that time difficult to predict that it was the pointer to be blamed.

003-00002 80
Page-80

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 11

STRUCTURES

Introduction

In our previous chapters, we have seen how we can use normal variables to store one piece of
information and how arrays can be used to store a collection of information of the same type. But we may
encounter situations where in we have to stored different types of data under a single name. Here arrays
will not serve our purpose. Fortunately, C supports a constructed data type known as structure.
Structures provide for grouping variables of different data type under a single name.

11.1 Syntax of a structure

struct structure_name
{
type member1; Elements or
type member2; members of structure.
---------
};

The syntax starts with the keyword struct followed by structure_name. member1, member2… are the
members of the structure. The members can be ordinary variables, pointers, arrays or of type structure
again. Members cannot be initialized within a structure declaration because the above syntax only
declares a type but not define it.

From the declared type, a variable of its type can be created by using the structure name.

struct tag_name variable1, variable2,…;

Each of these variables contains all the members specified in the structure definition.

For example, suppose we want to store data about a student, which consists of student name (a string),
regno (an integer), fees (a float), section (a character) and so on. Then we create a structure variable as
below.

struct student
{
char name[10];
int rollno;
float fees;
char section;
};

struct student s1;

003-00002 81
Page-81

Copyright CoreEL Technologies (I) Pvt. Ltd.


This statement sets aside space in memory. It makes available space to hold all the elements in the
structure. Here s1 is a structure variable of type student. We can combine the declaration of a structure
and structure variable in one statement.

Example
struct student
{
char name[10];
int rollno;
float fees;
char section;
}s1,s2;

We can also write a structure declaration without the structure name as seen below. We can define as
many variables as we want immediately after the closing brace. But we will not be able to define variables
of this type later in our program. Since the tagname identifying this structure type is not available.

struct
{
char name[10];
int rollno;
float fees;
char section;
} s1, s2;

11.2 Initializing a structure variable

Let us see how to initialize the above structure.

struct student
{
char name[10];
int rollno;
float fees;
char section;
};
struct student s1 = {“Raghav”,0001,65000,’E’};
struct student s2 = {“Naina”,002,75000,’V’};

11.3 Accessing structure elements

Structure members or elements are accessed using the dot (.) operator. The syntax is

Structure variable.member;
For example to access the elements of the above structure the syntax is
s1.rollno;
s1.fees;

003-00002 82
Page-82

Copyright CoreEL Technologies (I) Pvt. Ltd.


11.4 Operations on Structures

There are a relatively small number of operations which C directly supports on structures. Some of the
operations supported are

11.4.1 Assigning one structure variable to another


As we've seen, we can declare structures, define variables of structure type, and select the members of
structures. We can also assign an entire structure variable to another structure variable.

In the above example, we can write

struct student s1 = {“Raghav”,0001,65000,’E’};


struct student s2;
s2 = s1;
If not this, we have to assign it member by member.

11.4.2 Comparison of structure variables


We cannot use relation operators to compare between structures. Individual members have to be
compared using relational and logical operators.

/*Comparison of structure variables*/


#include <stdio.h>
#include <string.h>
struct student
{
char name[12];
int rollno;
float fees;
};
int main( )
{
struct student raghav = {"raghav",001,45000};
struct student naina;
raghav = naina;
/* if(st1 == st2) gives error */
if((strcmp(raghav.name,naina.name)==0)&&(raghav.fees==naina.fees)&&
(raghav.rollno==naina.rollno))
printf("They are equal");
else
printf("\nThey are not equal");

return 0;
}

003-00002 83
Page-83

Copyright CoreEL Technologies (I) Pvt. Ltd.


CHAPTER 12

ADVANCED STRUCTURES, UNIONS AND ENUMERATED DATA TYPES

Introduction

This chapter aims at exploring the concepts of structures in depth. It also introduces a new user defined
data type in C named as union and compares structures with unions.

12.1 Arrays of Structure

We know that a structure helps us to store the different types of information about an entity lets say
student. Now if we want to store the details of 10 students, we can create an array of structure student.
For eg:

struct student
{
char name[20];
int rollno;
float rees;
};
struct student s[10];

The elements of the structures are stored in adjacent memory locations. Since each element in this array
is a structure variable and since all structure elements are always stored in adjacent locations we can
very well visualize the arrangement of array of structures in memory as below.

003-00002 84
Page-84

Copyright CoreEL Technologies (I) Pvt. Ltd.


12.2 Nested structures

Nested structures refers to writing one structure inside another structure. For eg:
struct date {
int dd;
int mm;
int yy;
};
struct student {
char name[10];
int rollno;
float fees;
struct date doj;
};
struct student raghav;

To access the elements of the structure date,

raghav.doj.dd;

raghav.doj.mm;

12.3 Structure pointers

Pointers in C can be made to hold the address of the user defined type structures also. Such pointers are
known as structure pointers. Basic rules of pointers remains the same here. To declare a structure pointer
the syntax is
struct structure_name *pointer_name;

To access the members of the structure using pointer, we use -> operator. Syntax is
Pointer_name -> member_name;

For eg
struct student
{
char name[20];
int rollno;
float fees;
};
int main()
{
struct student raghav = {“Raghav”, 001, 65000};
struct student *ptr = &raghav;
printf(“Name = %s\n”, ptr -> name);
printf(“Roll no = %d\n”, ptr -> rollno);
printf(“Fees = %f\n”, ptr -> fees);
}

003-00002 85
Page-85

Copyright CoreEL Technologies (I) Pvt. Ltd.


Another way of accessing the members is

(*ptr_name).member_name;

For eg:

The above printf can be modified into

struct student
{
char name[20];
int rollno;
float fees;
};
int main()
{
struct student raghav = {“Raghav”, 001, 65000};
struct student *ptr = &raghav;
printf(“Name = %s\n”, (*ptr). name);
printf(“Roll no = %d\n”, (*ptr) . rollno);
printf(“Fees = %f\n”, (*ptr). fees);
}

The parentheses are required because the dot operator (.) has higher precedence then the indirection
operator (*). Without the parenthesis the compiler would generate error because ptr(a pointer) is not
directly compatible with the dot operator.

12.4 Self-referential structures

It is a structure which contains one member which is a pointer of its own type.

Example

struct student
{
char name [12];
int rollno;
float fees;
struct student *next;
};

The above structure contains an element/member which is a pointer to a structure of the same type (i.e.,
a pointer to structure of type student), called next. Therefore this is a self-referential structure. Self
referential structures are very useful in applications that involve linked data structures, such as lists and
trees.

003-00002 86
Page-86

Copyright CoreEL Technologies (I) Pvt. Ltd.


12.5 Passing structures to Functions

There are two ways of doing this.

12.5.1 Passing individual structure elements to function


struct student
{
char name[12];
int rollno;
float fees;
};
void display(char n[], int r, float f)
{
printf("Name : %s\t",n);
printf("Rollno: %d\t",r);
printf("Fees : %f\n",f);
}
int main( )
{
struct student st = { “raghav",001,65000};
display (st.name, st.rollno, st.fees);
return 0;
}

When the number of elements in the structure increases, passing element by element becomes difficult.

12.5.2 Passing entire structure to function


struct student
{
char name[12];
int rollno;
float fees;
};
void display(struct student raghav)
{
printf("Name : %s\t",raghav.name);
printf("Rollno: %d\t",raghav.rollno);
printf("Fees : %f\n",raghav.fees);
}
int main( )
{
struct student st = { “raghav",001,65000};
display (st);
return 0;
}

003-00002 87
Page-87

Copyright CoreEL Technologies (I) Pvt. Ltd.


Both the methods can be implemented using pass by address also. So if we modify the above program, it
will look like below.

struct student
{
char name[12];
int rollno;
float fees;
};
void display(struct student *raghav)
{
printf("Name : %s\t",raghav -> name);
printf("Rollno: %d\t",raghav -> rollno);
printf("Fees : %f\n",raghav -> fees);
}
int main( )
{
struct student st = { “raghav",001,65000};
display (&st);
return 0;
12.6
} Memory saving structures using C Bit fields

In a scalar data object, the smallest object that can be addressed directly is usually a byte. Bit fields
provide an alternate method of accessing bits. A bit field is a collection of adjacent bits. It is defined inside
a structure but is different from other members because its size is specified in terms of bits. Bit field can
be applied only to integers (signed or unsigned).

We cannot get the address of bit field members

For eg

struct Date
{
unsigned int month : 4; // 1 is January; 12 is December.
unsigned int day : 5; // The day of the month (1 to 31).
unsigned int year : 12;
};

n
If the size of a bit field is n, then the range of values that the bit field can take is from 0 to 2 – 1. We cant
apply sizeof and address operators to bit fields. So we cannot use scanf() to input values to bit field.

Bit fields are considered non portable as most of the issues related with them are implementation
dependent. A plain int field may be treated as signed by some compilers while unsigned by others. So for
portability, it is better to clearly specify signed or unsigned in the declaration of bit fields. If a bit field is
defined as signed, then it should be at least 2 bits long because one bit is used for sign.

003-00002 88
Page-88

Copyright CoreEL Technologies (I) Pvt. Ltd.


The other implementation dependent issues about bit fields is that whether they can cross integer
boundaries or not. For eg

struct sample
{
unsigned a : 10;
unsigned b : 7;
unsigned c : 17;
};

The first two fields occupy only 17 bits in a 32 bit integer. So 15 bits can still be used for another bit field.
But the bits needed for next bit field is more than 15. Some implementations may start the next field (c)
from a new integer while others may just place the next field in 17 adjacent bits. 15 unused from the
previous integer and 2 bits from the next integer.

We can define unnamed bitfields for controlling the alignment of bit fields within an integer. The size of
unnamed bit field privides padding within the integer.

struct sample
{
unsigned a : 10;
unsigned b : 7;
unsigned : 15;
unsigned c : 17;
};

Here the next field starts with the second integer. We can also take the size of unnamed bitfield zero. It
will give the same result as above.

struct sample
{
unsigned a : 10;
unsigned b : 7;
unsigned : 0;
unsigned c : 17;
};

12.7 Structure padding

Although the compiler (or interpreter) normally allocates individual data items on aligned boundaries,
structures often have members with different alignment requirements. To maintain proper alignment, the
translator normally inserts additional unnamed data members so that each member is properly aligned.
Structure padding occurs because the members of the structure must appear at the correct byte
boundary, to achieve this the compiler puts in padding bytes (or bits if bit fields are in use) so that the
structure members appear in the correct location.

003-00002 89
Page-89

Copyright CoreEL Technologies (I) Pvt. Ltd.


Padding is only inserted when a structure member is followed by a member with a larger alignment
requirement or at the end of the structure. By changing the ordering of members in a structure, it is
possible to change the amount of padding required to maintain alignment. For example, if members are
sorted by ascending or descending alignment requirements, a minimal amount of padding is required.
The minimal amount of padding required is always less than the largest alignment in the structure.

In general members are stored sequentially in a memory so that in the structure below the member Data1
will always precede Data2 and Data2 will always precede Data3:

struct MyData

{
short Data1; short Data2; short Data3;

};

If the type "short" is stored in two bytes of memory then each member of the data structure depicted
above would be 2-byte aligned. Data1 would be at offset 0, Data2 at offset 2 and Data3 at offset 4. The
size of this structure would be 6 bytes.

The type of each member of the structure usually has a default alignment, meaning that it will, unless
otherwise requested by the programmer, be aligned on a pre-determined boundary. The following typical
alignments are valid for compilers from Microsoft, Borland, and GNU when compiling for 32-bit x86:

A char (one byte) will be 1-byte aligned.

A short (two bytes) will be 2-byte aligned.

An int (four bytes) will be 4-byte aligned.

A float (four bytes) will be 4-byte aligned.

A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on Linux (8-byte with -
malign-double compile time option).

A long double (twelve bytes) will be 4-byte aligned on Linux.

Any pointer (four bytes) will be 4-byte aligned on Linux. (e.g.: char*, int*)

The only notable difference in alignment for a 64-bit Linux system when compared to a 32 bit is:

A double (eight bytes) will be 8-byte aligned.

A long double (Sixteen bytes) will be 16-byte aligned.


Any pointer (eight bytes) will be 8-byte aligned.
Here is a structure with members of various types, totaling 8 bytes before compilation:

003-00002 90
Page-90

Copyright CoreEL Technologies (I) Pvt. Ltd.


struct MixedData
{
char Data1;
short Data2;
int Data3;
char Data4;
};

After compilation the data structure will be supplemented with padding bytes to ensure a proper alignment
for each of its members

struct MixedData /* After compilation in 32-bit x86 machine */


{
char Data1; /* 1 byte */
char Padding1[1]; /* 1 byte for the following 'short' to be aligned on
a 2 byte boundary Assuming that the address where structure begins is an
even number */
short Data2; /* 2 bytes */
int Data3; /* 4 bytes - largest structure member */
char Data4; /* 1 byte */
char Padding2[3]; /* 3 bytes to make total size of the structure 12
bytes */
};

The compiled size of the structure is now 12 bytes. It is important to note that the last member is padded
with the number of bytes required to maket the total size of the structure to be a least common multiple of
the size of a largest structure member. In this case 3 bytes are added to the last member to pad the
structure to the size of a 12 bytes (4 bytes of int × 3).

It is possible to change the alignment of structures to reduce the memory they require (or to conform to
an existing format) by reordering structure members or changing the compiler’s alignment (or “packing”)
of structure members.

struct MixedData /* after reordering */


{
char Data1;
char Data4; /* reordered */
short Data2;
int Data3;
};

The compiled size of the structure now matches the pre-compiled size of 8 bytes. Note that

Padding1[1] has been replaced (and thus eliminated) by Data4 and Padding2[3] is no longer necessary
as the structure is already aligned to the size of a long word.

003-00002 91
Page-91

Copyright CoreEL Technologies (I) Pvt. Ltd.


The alternative method of enforcing the MixedData structure to be aligned to a one byte boundary is
pragma pack which will cause the pre-processor to discard the pre-determined alignment of the structure
members and thus no padding bytes would be inserted.

For eg:

#pragma pack(push) /* push current alignment to stack */


#pragma pack(1) /* set alignment to 1 byte boundary */

struct MyPackedData
{
char Data1; long Data2; char Data3;
};
#pragma pack(pop) /* restore original alignment from stack
*/

12.8 Unions

Unions like structure contain members whose individual data types may differ from one another. However
the members that compose a union all share the same storage area within the computer’s memory where
as each member within a structure is assigned its own unique storage area. Thus unions are used to
conserve memory.

They are useful for application involving multiple members, where values need not be assigned to all the
members at any one time.

12.8.1 Syntax of union


union union_name
{
members;

};
union union_name variable_name;

The compiler will allocate enough storage to accommodate the largest element in the union. Only one
member of the union will be initialized at a time. In effect a union creates a storage location that can be
used by one of its members at a time. When a different number is assigned a new value, the new value
replaces the previous member’s value. Unions may be used in all places where a structure is allowed.
The notation for accessing a union member remains the same as for the structure.

12.9 Enumerated data types

Enumerated data types will help us to create one more type of user defined data type where the
identifiers in the enum data type will represent integer values.

003-00002 92
Page-92

Copyright CoreEL Technologies (I) Pvt. Ltd.


12.9.1 Syntax of enum

enum enum_name{ member1, member2,…member n };

Here, enum is the keyword. enum_name is the name of the enumerated data-type Once the enumerated
data-type is defined the variables of that type can be created as follows

enum enum_name variable1,variable2,..variable n;

The definition and the variable declaration can be combined as follows


enum enum_name { member1, member2,…memberN } variable1,variable2;

Here the enum_name is optional and variable1 and variable2 are the variables of type enum.

Internally the compiler treats the enumeration constants as integers and assign's values beginning from 0
for first member, with each successive member increasing by 1 and so on.

Example

enum weekday {MON, TUE, WED, THU, FRI}; /* defining enumerated data-type*/
enum weekday d2; /* creating a variable of that type*/

The enumeration constants will represent the following values.


MON  0
TUE  1
WED  2
YHU  3
FRI  4

12.9.2 Uses of enumerated data types

Enumerated variables are usually used to clarify the operation of a program. For example,

Example

003-00002 93
Page-93

Copyright CoreEL Technologies (I) Pvt. Ltd.


int main( )
{
enum DAYS_OF_WEEK {SUN,MON, TUE,WED,THU,FRI,SAT} d1, d2;
d1 = TUE;
d2 = WED;
printf(“No of days between d1 & d2 :", d2 - d1);
if(d1 > SUN && d1 < SAT) /*They can be compared */
printf(“Valid Week Day\n");
else
printf("Invlalid Week Day\n");
switch(d1)
{
case MON: printf(“\nMonday");
break;
case TUE: printf("\nTuesday" );
break;
case WED: printf("\nWednesday");
break;
case THU: printf("\nThursday");
break;
case FRI: printf("\nFriday");
break;
default: printf("\nInvalid day");
}
return 0;
}

These automatic assignments can be overridden within the definition of the enumeration by assigning
some of the constants with explicit integer values which differ from the default values. Thus the constants
which are not assigned explicit values will automatically be assigned values which increase by 1 from the
last explicit assignment. This may cause two or more enumeration constants to have the same integer
values.

enum weekday {MON=1, TUE, WED, THU, FRI};

The member MON is assigned a value 1, TUE will be represent the value 2, WED represents 3 and so
on. i.e., the other members are automatically assigned values that increase successively by 1.

It is not possible to collect the value to an enum variable using the input statements.

003-00002 94
Page-94

Copyright CoreEL Technologies (I) Pvt. Ltd.


Good to know

Typedef

The Keyword typedef is used to give an alternate name for an existing datatype. Or in other words,
typedef is used to create shorter or simpler type names.

Let's see how typedef works. Suppose you want to use the term BYTE for one-byte numbers. You simply
define BYTE as if it were a char variable and precede the definition by the keyword typedef, like

typedef unsigned char BYTE;


From then on, you can use BYTE to define variables.
BYTE x, y[10], * z;

typedef unsigned int size_t;

Defines a new type name size_t as a synonym for type unsigned int

size_t no_elements;
size_t class_strength;
void bubblesort(int arr[] , size_t n);

Similarly, the declaration

typedef char *String_t;


Defines a new type name String _t as a synonym for type char *

String_t s1 = “Sandeepani”;
size_t Strlen(String_t str);

typedef can also be applied to structures and union

Eg:
struct Student
{
int id;
char name[20];
int sem;
};
typedef struct Student STUDENT;

Now STUDENT can be used as the datatype.

STUDENT s1 , s2[5];

003-00002 95
Page-95

Copyright CoreEL Technologies (I) Pvt. Ltd.


Typedef can be combined with structure declaration

typedef struct Student typedef struct


{ {
int id; int id;
char name[20]; char name[20];
int sem; int sem;
}STUDENT; }STUDENT;

Notes :

 Using typedef does not define any objects or storage.


 typedef does not create a new data type; it only adds a new name for existing type.
 Typedef names allow you to encapsulate implementation details that may change
 Use typedef to help make a program more portable.

003-00002 96
Page-96

Copyright CoreEL Technologies (I) Pvt. Ltd.


REFERENCES

C Primer plus – Stephen Prata


C programming – Dennis Ritchie

003-00002 97
Page-97

Copyright CoreEL Technologies (I) Pvt. Ltd.

Você também pode gostar