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

C Course Material

The document provides an overview of the C programming language and its use in embedded systems. It discusses C's history, characteristics, and role. C combines aspects of low-level languages like assembly with high-level languages. It is portable, modular, and efficient. C is widely used to develop operating systems, embedded systems, and other applications because it allows direct hardware interaction. Common embedded systems programmed in C include Bluetooth devices, microcontrollers, USB devices, and more.

Uploaded by

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

C Course Material

The document provides an overview of the C programming language and its use in embedded systems. It discusses C's history, characteristics, and role. C combines aspects of low-level languages like assembly with high-level languages. It is portable, modular, and efficient. C is widely used to develop operating systems, embedded systems, and other applications because it allows direct hardware interaction. Common embedded systems programmed in C include Bluetooth devices, microcontrollers, USB devices, and more.

Uploaded by

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

Embedded

C-Course

Material

Contents
1. Introduction
About C Language.
About Microcontrollers
RISC Processors
CISC Processors
2. Variables & Operators
3. Control Structures
a. IF statement
i. Ladder IF statement
b. FOR statement
c. WHILE statement
d. DO-WHILE statement
e. SWITCH statement
Examples
4. Functions, User define Functions & Macros
5. Derivative Data types
a. Arrays
b. Structure
c. Union
d. Enumerators
e. Tree
f. Linked List
g. Pointers
Examples

6. Pragama & Scope of Variables


7. Assignments

1. Introduction:
Powerful features, simple syntax, and portability make C a preferred language among
programmers for business and industrial applications. Portability means that C programs written
for a computer with a particular kind of processor say Intel can be executed on computers with
different processors such as Motorola, Sun Sparc, or IBM with little or no modification.

C language is widely used in the development of operating systems. An Operating System


(OS) is software (collection of programs) that controls the various functions of a computer. Also it
makes other programs on your computer work. For example, you cannot work with a word
processor program, such as Microsoft Word, if there is no operating system installed on your
computer. Windows, UNIX, Linux, Solaris, and MacOS are some of the popular operating
systems.

1.1.

HISTORY OF C:

In the early days of computers, the only programming languages available to programmers
were two low level languages, machine and assembly language. Programming in machine and
assembly languages was tedious and time consuming because all memory, stack, interrupts and
hardware is to be managed by programmer. Increase in use of computers, many high-level
languages such as FORTRAN, Basic and Pascal are developed.
By using high-level languages hardware will be simple, syntax made easier. In 1972, the
Unix Operating system was being developed. During this time, the concept of a System
programming language having attributes of both low level and high level languages also
developed. Brian W. Kernighan and Dennis M. Ritchie developed C at Bell Laboratories as a
system programming language. Their goal was to develop a language that was simple and flexible
enough to be used in a variety of different platforms. In 1983, the American National Standards
Institute formed a committee to produce a C programming language standard. This "ANSI C" was
completed in 1988. C with objects) is the most popular programming language in the world and is
the dominant in Microsoft Windows application development. Small C can be used in
microcontrollers.

1.2.

CHARACTERISTICS OF C:

Modularity

Portability

Extendibility

Speed

Flexibility

Modularity:
Ability to breakdown a large module into manageable sub modules called as modularity,
which is an important feature of structured programming languages.
Advantages:
1. Projects can be completed in time.
2. Debugging will be easier and faster.
Portability:
The ability to port i.e. to install the software in different platform is called portability.
Highest degree of portability: C language offers highest degree of portability i.e., percentage of
changes to be made to the sources code is at minimum when the software is to be loaded in
another platform. Percentage of changes to the source code is minimum. The software that is
100% portable is also called as platform independent software or architecture neutral software.
Eg: Java.
Extendibility:
Ability to extend the existing software by adding new features is called as extendibility.
Speed:
C is also called as middle level language because programs written in c language run at
the speeds matching to that of the same programs written in assembly language so c language
has both the merits of high level and middle level language and because if this feature it is mainly
used in developing system software.
Flexibility:

Key words or reverse words.

ANSIC has 32 reverse words.

C language has right number of reverse words which allows the programmers to have
complete control on the language.

C is also called as programmers language since it allows programmers to induce


creativeness into the programmers.

1.3.

WHAT KIND OF LANGUAGE IS C?

C is called a middle-level language because it combines the best elements of low-level or


machine language with high-level languages.

C takes a middle path between low-level assembly language


Direct access to memory layout through pointer manipulation
Concise syntax, small set of keywords
and a high-level programming language like Java:
Block structure
Some encapsulation of code, via functions
Type checking (pretty weak)

C is a Structure Programming Language because it contains programs in well defined control


structures. C language can break large task into sub-tasks which made programmer easy called
Modularity.

1.4.

C VS ASSEMBLY:

C
Writing Programs much faster
Learning and mastering takes less time
Portable
Well defined structured
Powerful keywords
Supports modularity
High-level language

1.5.

ASSEMBLY
Writing programs are slower
It takes more time
Non portable
Not a well defined structured
More number of keywords
Does not support modularity
Low-level language

WHY YOU SHOULD LEARN C?

o
o
o
o

C is simple.
There are only 32 keywords so C is very easy to master.
C programs run faster than programs written in most other languages.
C enables easy communication with computer hardware making it easy to

write system

programs such as compilers and interpreters.


o C language supports Integrated Development Environment (IDE).

1.6.

ROLE OF C IN EMBEDDED SYSTEMS:

C is one of the most commonly used software languages used on embedded device
controllers. One reason is because it is one of the few software languages that operates on both 8
bit controllers and 64 bit PCs, meaning that many computer programmers can write C software
for both personal computers and embedded devices. The C language can also use very simple
commands to control the device, freeing up the limited memory of the device to hold many
commands or parameters. C can be written for both microcontrollers and digital signal processors.
Code is written in C on a programmer's PC. Code is run through a compiler on the
programmer's PC to create a software program. The embedded system software may be run
through a simulator on the programmer's computer. The software program is copied onto the
controller using a "programmer." The controller is then tested on a "test bed" to ensure that it
works properly.

1.7.

COMMON EMBEDDED SYSTEMS THAT USE C:

Bluetooth devices are programmed in C. PIC microcontrollers such as those used in web
cameras are frequently programmed in C. PIC microcontrollers programmed in C have also been
used in LED (light emitting diodes) devices and LCD (liquid crystal display) monitors. USB
devices are embedded devices frequently coded in C.

1.8.

STANDARDS FOR EMBEDDED SYSTEM PROGRAMMING IN C:

The American National Standards Institute (ANSI) has written standards for the C
programming language. The International Standards Organization wrote standard ISO/IEC 9899
for the C programming language. The Motor Industry Software Reliability Association has
created a proprietary set of standards for programming in C for embedded devices in automobile.

1.9.

WHERE IS C USEFUL?

Cs ability to communicate directly with hardware makes it a powerful choice for system
programmers. In fact, popular operating systems such as Unix and Linux are written entirely in C.
Additionally, even compilers and interpreters for other languages such as FORTRAN, PASCAL,
and BASIC are written in C. However, Cs scope is not just limited to developing system
programs. It is also used to develop any kind of application, including complex business ones.
The following is a partial list of areas where C language is used:

Embedded Systems
Systems Programming
Artificial Intelligence
Industrial Automation
Computer Graphics
Space Research
Image Processing
Game Programming

1.10. C-COMPILERS:
When you write any program in C language then to run that program you need to compile
that program using a C Compiler which converts your program into a language understandable by
a computer. This is called machine language (i.e. binary format). So before proceeding, make sure
you have C Compiler available at your computer.

1.11. LIFE CYCLE OF A C PROGRAM


1) Write the program
int main ()
{
printf ("Hello World");
}

2) Compile the program


When the program gets compiled, the compiler realizes that the current compile unit (ie.,
the simple C program in this case) has no implementation for printf(), and therefore produces an
entry in the object file's symbol table saying that printf() has an `unresolved reference'. And the
compiler generates an object file (.o file) if there were no syntax errors in the program
3) Link the object file(s)

The next phase is to link the object files to produce an executable. During linking, the
static linker (ld) sees the unresolved reference to printf() and searches the available libraries for an
implementation for printf(). In general this will be found in the C library (libC on Solaris). Now,
the linker has two options:
It (linker) can take the printf() implementation from the library and copy it into the final
executable. The linker then searches the printf() implemenation for other unresolved references,
and again consult the libraries for resolution. This process will be performed iteratively until all
references to the symbols were resolved. This is known as static linking
If the C library is realized as a `shared library', the linker can simply put a reference to the
C library into the final executable. Still the linker performs symbol resolution checking as above,
to determine if the reference to the printf() function necessiates further references to other (shared
or nonshared) libraries. This is known as dynamic linking
4) Run the executable
What happens when you run the executable, depends on whether it was linked statically
or dynamically:
A statically linked executable is self contained. It is loaded into memory. The entry
point, whose designation is system dependent (for eg, the `__main' symbol) is found and called.
This entry function, usually provided by the compiler or a library, performs some setup and
initialization and then calls the user-defined main() function and the instructions inside main()
function gets executed
In a dynamically linked executable, after loading the executable binary into memory, the
dynamic linker (ld.so.1) takes control first. It reads the library references to dynamic libraries
produced by the static linker, and loads them into memory. It then performs symbol resolution
again and updates all references to symbols in the shared library to point to their actual location,
which can only be determined at runtime, because the shared libraries might be loaded to different
memory locations each time the executable binary gets executed

HLL (High Level Language):


A programming language such as C, FORTRAN, or Pascal that enables a programmer to
write programs that are more or less independent of a particular type of computer. Such languages
are considered high-level because they are closer to human languages and further from machine
languages.
ALL (Assembly Level Language):
Assembly language is essentially the native language of your computer. Technically the
processor on machine understands machine code (consisting of ones and zeroes). But in order to
write such a machine code program, assembly language is used and then an assembler is used to
convert it to machine code.
Assembly language simply consists of mnemonic codes which are easy to remember (they are
similar to words in the english language), which stand for each of the different machine code instructions
that the machine is capable of executing (8bit or 16bit machine/controller).

MLL (Machine Level Language):


Machine level language is the lowest-level programming language. Machine language is the only
language understood by computers. While easily understood by computers, machine languages are almost
impossible for humans to use because they consists of sequence of bits (1s and 0s).

Comparison between HLL, ALL and MLL:


HLL:

ALL

User friendly
Machine independent
Has comparably less statement than assembly language
Portable
Full optimization cannot be achieved
Less time to code
Easy to debug

Faster approach
Operates directly on the register
More statement
Not portable
Machine dependent

Very difficult to code or even understand


Consist of 1s and 0s

More time to code


Difficult to debug

MLL

Not portable
Machine dependent

About Microcontrollers:
Endian is the ordering of bytes in scalar data on the machine.

Big Endean:
It stores scalars in their natural order, with most significant byte in the lowest numeric byte
address. Examples of big endian processors are the IBM System 360 and 370, Motorola 680x0 and most
RISC processors.

Little Endean:
It stores scalars with the least significant byte in the lowest numeric byte address. Examples of
little endian processors are the Digital VAX and Intel x86 (including Pentium).

Processors can broadly be divided into CISC and RISC.


Complex Instruction Set Computers (CISC) have a large instruction set, with hardware
support for a wide variety of operations. In scientific, engineering, and mathematical operations
with hand coded assembly language (and some business applications with hand coded assembly
language), CISC processors usually perform the most work in the shortest time.
Eg. Intel 386, 486, Pentium, Pentium Pro, Pentium II, Pentium III, Motorolas 68000, 68020,
68040, etc

Reduced Instruction Set Computers (RISC) have a small, compact instruction set. In most
business applications and in programs created by compilers from high level language source,
RISC processors usually perform the most work in the shortest time.
Eg: IBM RS6000, MC88100, DECs Alpha 21064, 21164 and 21264 processors

Life cycle of a micro-controller project


It is important to have a general idea of the steps that are followed to realize a project,
from the very beginning of an idea to the very end of a finalized project.

Introduction to 8051 Microcontroller


The 8051 is an 8 bit microcontroller originally developed by Intel in 1980. It is the world's
most popular microcontroller core, made by many independent manufacturers (truly multisourced). There were 126 million 8051s (and variants) shipped in 1993.
Features:
* CPU with boolean processor

* 5 or 6 interrupts
* 2 or 3 16-bit timer/counters
* Programmable full-duplex serial port
* 32 I/O lines (four 8-bit ports)
* RAM
* ROM/EPROM in some models
Interrupts
One strong point of the 8051 is the way it handles interrupts. Vectoring to fixed 8-byte
areas is convenient and efficient. Most interrupt routines are very short (or at least they should
be), and generally can fit into the 8-byte area. Of course if your interrupt routine is longer, you
can still jump to the appropriate routine from within the 8 byte interrupt region.
The 8051 instruction set is optimized for the one-bit operations so often desired in realworld, real-time control applications. The boolean processor provides direct support for bit
manipulation. This leads to more efficient programs that need to deal with binary input and output
conditions inherent in digital-control problems. Bit addressing can be used for test pin monitoring
or program control flags.
The 8051 micro-controller architecture

This figures shows the main features and components that the designer can interact with.
You can notice that the 89S52 has four different ports, each one having eight Input/output lines
providing a total of 32 I/O lines. Those ports can be used to output DATA and orders do other
devices, or to read the state of a sensor, or a switch. Most of the ports of the 89S52 have dual
function meaning that they can be used for two different functions: the fist one is to perform
input/output operations and the second one is used to implement special features of the
microcontroller like counting external pulses, interrupting the execution of the program according
to external events, performing serial data transfer or connecting the chip to a computer to update
the software.
Special Function Registers (SFRs)
The 8051 is a flexible microcontroller with a relatively large number of modes of
operations. The program inspects and changes the operating mode of the 8051 by manipulating
the values of the 8051's Special Function Registers (SFRs).

SFRs are accessed as if they were normal Internal RAM. The only difference is that
Internal RAM is from address 00h through 7Fh whereas SFR registers exist in the address range
of 80h through FFh.Each SFR has an address (80h through FFh) and a name. The following chart
provides a graphical presentation of the 8051's SFRs, their names, and their address.

8051 Memory Organisation


Internal ROM
The 8051 has 4K (4096 locations) of on-chip ROM. This is used for storing the system
program. 212 = 4096, therefore the internal ROM address bus is 12 bits wide and internal ROM
locations go from 000H to FFFH.
Internal RAM
There are 256 bytes of internal RAM on the 8051. 28 = 256, therefore the internal RAM
address bus is 8 bits wide and internal RAM locations go from 00H to FFH. The first 128

locations (00H to 7FH) of internal RAM are used by the programmer for storing data while the
second 128 locations (80H to FFH) are the Special Function Registers (SFRs)

Introduction to PIC16Fxx :
Microchip manufacture a series of microcontrollers called PIC (Peripheral Interface
Conroller). There are many different flavours available, some basic low memory types, going
right up through to ones that have Analogue - To- Digital converters and even PWM built in.
There are several ways of programming the PIC - using BASIC, C, or Assembly
Language.
The PIC architecture is characterized by its multiple attributes:

Separate code and data spaces (Harvard architecture) for devices other than PIC32, which

has a Von Neumann architecture.


A small number of fixed length instructions
Most instructions are single cycle execution (2 clock cycles, or 4 clock cycles in 8-bit

models), with one delay cycle on branches and skips


One accumulator (W0), the use of which (as source operand) is implied (i.e. is not encoded

in the opcode)
All RAM locations function as registers as both source and/or destination of math and other

functions.[3]
A hardware stack for storing return addresses
A fairly small amount of addressable data space (typically 256 bytes), extended through

banking
Data space mapped CPU, port, and peripheral registers
The program counter is also mapped into the data space and writable

Main features of the 16 family

Operating speed DC-10 Mhz clock input


RISC CPU 35 single-word instructions
Timer
Different Interrupt sources
Size memories (RAM, ROM) and an additional features vary by the type of
microcontroller

Memory Arrangement
There are two memory blocks in the PIC16F8X:

The program memory (14bits Bus)


The data memory. (8bits Bus)

Each block has its own bus, so that access to each block can occur during the same clock cycle.
The data memory can further be broken down into:

The General Purpose Registers (GPR)


The Special Function Registers (SFRs)

Special function registers


An area of data memory is dedicated to registers that are required for configuration and
dataflow control. This dedicated memory area is divided into a number of special function
registers which can not be used as general purpose registers by the programmer. The special
function registers are TMR0, OPTION, PCL, STATUS, FSR, PORTA, PORTB, TRISA,
TRISB, EEDATA, EECON1, EEADR, EECON2, PCLATH and INTCON and are situated in
the data memory locations.

Peripherals

General purpose I/O pins.


Internal clock oscillators.
8/16 Bit Timers.
Internal EEPROM Memory.
Synchronous/Asynchronous Serial Interface USART.
MSSP Peripheral for IC and SPI Communications.
Capture/Compare and PWM modules.
Analog-to-digital converters (up to ~1.0 MHz).
USB, Ethernet, CAN interfacing support.
External memory interface.
Integrated analog RF front ends (PIC16F639, and rfPIC).

CHAPTER 2

STRUCTURE OF C PROGRAM ,

DATA

TYPES AND STORAGE CLASSES IN C

2.1.

STRUCTURE OF C PROGRAM:
The structure of a C program is a protocol (rules) to the programmer, while writing a C

program. The general basic structure of C program is shown in the figure below. The whole
program is controlled within main ( ) along with left brace denoted by { and right braces
denoted by }. If you need to declare local variables and executable program structures are
enclosed within { and } is called the body of the main function. The main ( ) function can be
preceded by documentation, preprocessor statements and global declarations.

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

2.1.2 PREPROCESSOR STATEMENTS:

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

2.1.3 GLOBAL DECLARATIONS:


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

2.1.4 THE MAIN ( ) FUNCTION:


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

2.1.5 BRACES:

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

2.1.6 LOCAL DECLARATIONS:


The variable declaration is a part of C program and all the variables are used in main ( )
function should be declared in the local declaration section is called local variables. Not only
variables, we can also declare arrays, functions, pointers etc. These variables can also be
initialized with basic data types.
For example,
main ( )
{
int sum = 0;
int x;
float y;
}
Here, the variable sum is declared as integer variable and it is initialized to zero. Other variables
declared as int and float and these variables inside any function are called local variables.

2.1.7 PROGRAM STATEMENTS:


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

2.1.8 USER DEFINED FUNCTIONS:


These are subprograms, generally, a subprogram is a function and these functions are
written by the user are called user; defined functions. These functions are performed by user
specific tasks and this also contains set of program statements. They may be written before or
after a main () function and called within main () function. This is an optional to the programmer.
Now, let us write a small program to display some message shown below.
# include <stdio.h>
main()
{
printf ("welcome to the world of C/n");
}

2.2. DATATYPES IN C:
C language is rich in its data types. ANSI C supports four classes of data types:

Primary data types (fundamental).


User-defined data types.
Derived data types.
Empty data set (void).

2.2.1. PRIMARY DATA TYPES:


All C compilers support four fundamental data types.

Integer (int)
Character (char)
Floating point (float)
Double-precision floating point (double).

Various data types and terminology used to describe is given below diagram.
Integer type:
Signed type
Int
Short int
Long int

Unsigned type
Unsigned int
Unsigned short int
Unsigned long int

Character type:

Signed char
Unsigned char

Floating Type
Float

Double

Long double

Size and Range of Basic Data Types:


Data type
Char
Int
Float
Double

Range
-128 to 127
-32,768 to 32,767
3.4e-38 to 3.4e+38
1.7e-308 to 1.7e+308

Integer types:
Integers are whole numbers with a range of values supported by a particular machine. Size
of an integer that can be stored depends on the computer. If we use a 16-bit word length, the size
of the integer value is limited to the range of (-2 n-1 to +2n-1-1). A signed bit uses one bit for sign
and 15 bits for the magnitude of the number. C has different forms of integer storage like short
int, long int, in both signed and unsigned forms.
Floating point types:
Floating point numbers are stored in all machines, with 6 digits of precision. This data
type is defined by using keyword float. When the accuracy provided by float number is not
sufficient, the type double can be used. The data type double can have precision of 14 digits.
Further extension in precision we can use long double.
Character types:

A single character can be defined as a character (char) type data. Characters are usually
stored in 8 bits (one byte) of internal storage. While unsigned char have values between 0 to 255,
signed char have values from -128 to 127.

SI.No Keyword

Range

Storage in

1.
2.
3.
4.
5.
6.
7.

Char (signed)
Unsigned char
Int
Unsigned int
Short
Unsigned short
Long

-127 to 127
0 to 255
-32,768 to 32,767
0 to 65,535
-32,768 to 32,767
0 to 65,535
-2,147,483,648 to

Bytes
1
1
2
2
2
2
4

8.
9.

Unsigned long
Float

2,147,483,647
0 to 4,294,967,295
1.2E-38 to 3.4E38, approx.

4
4

10.

Double

range precision = 7 digits


2.2E-308 to 1.8E308, approx.

range precision = 19 digits.

Secondary or Derived data type

Derived data type is constructed from basic data type. Example: Arrays, Structures, Enumerated
data types, Union etc..(discussed in the later part of the material)

2.2.2. EMPTY DATA SET (VOID):


A function with void result type ends either by reaching the end of the function or by
executing a return statement with no returned value. The void type may also appear as the sole
argument of a function prototype to indicate that the function takes no arguments. Note that
despite the name, in all of these situations, the void type serves as a unit type, not as a zero or
bottom type, even though unlike a real unit type which is a singleton, the void type is said to
comprise an empty set of values, and the language does not provide any way to declare an object
or represent a value with type void.

2.2.3. User-defined data types. type def


In C language a user can define an identifier that represents an existing data type. The user
defined datatype identifier can later be used to declare variables. The general syntax is typedef
type identifier; here type represents existing data type and identifier refers to the row name
given to the data type.
Example:
typedef int salary;
typedef float average;
Here salary symbolizes int and average symbolizes float. They can be later used to declare
variables as follows:
Salary dept1, dept2;
Average section1, section2;
Therefore dept1 and dept2 are indirectly declared as integer datatype and section1 and section2
are indirectly float data type.

2.3. Storage class in C


A storage class defines the scope (visibility) and life time of variables and/or functions
within a C Program.

There are four storage classes which can be used in a C Program. They are auto, register,
static and extern.

2.3.1. auto Storage Class Specifier

The auto storage-class specifier declares an automatic variable, a variable with a local lifetime. An

auto variable is visible only in the block in which it is declared.


The variables with auto storage class are not initialized automatically, you should either explicitly
initialize them when you declare it, or assign them with some initial values in statements within
the block.

An internal static variable (a static variable with local or block scope) can be initialized
with the address of any external or static item, but not with the address of another auto
item, because the address of an auto item is not a constant.

Automatic variables may be specified upon declaration to be of storage class auto.


However, it is not required to use the keyword auto because by default, storage class
within a block is auto.

Keyword : auto
Storage Location : Main memory
Initial Value : Garbage Value
Life : Control remains in a block where it is defined.
Scope : Local to the block in which variable is declared.
Syntax:
auto [data_type] [variable_name];
ex: auto int var; or int var;

2.3.2. register- Storage Class Specifier

Registers are memory located within the CPU itself where data can be stored and accessed
quickly. Normally, the compiler determines what data is to be stored in the registers of the
CPU and at what instant.

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 and it is not an obligation for the CPU to do this.

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

It is not applicable for arrays, structures or pointers and it cannot not be used with static or
external storage class.

Keyword : register
Storage Location : CPU Register
Initial Value : Garbage
Life : Local to the block in which variable is declared.
Scope : Local to the block.
Syntax:
register [data_type] [variable_name];
ex: register int var;

2.3.3. static-Storage Class Specifiers

static storage class 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.

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.

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.

static 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 such as:
static extern var;

static variables are stored in data segment area of the memory.

Static storage class can be used only if we want the value of a variable to persist between
different function calls.
o
o
o
o
o

Keyword : static
Storage Location : Main memory
Initial Value : Zero and can be initialize once only.
Life : depends on function calls and the whole application or program.
Scope : Local to the block.
Syntax:
static [data_type] [variable_name];
ex: static int var;

2.3.4. extern - Storage Class Specifier

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, and the C language provides storage
classes which can meet these requirements; namely, the external (extern) and static
(static) classes.

External 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 (extern keyword
may be omitted).

Typically if declared and defined at the beginning of a source file, the extern keyword can
be omitted. If the program is in several source files, and a variable is defined in let say
file1.c and used in file2.c and file3.c then the extern keyword must be used in file2.c and
file3.c.

But, usual practice is to collect extern declarations of variables and functions in a separate
header file (.h file) then included by using #include directive.

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.

The scope of external variables is global, i.e. the entire source code in the file following
the declarations. All functions following the declaration may access the external variable
by using its name. However, if a local variable having the same name is declared within a
function, references to the name will access the local variable cell.
o

Keyword : extern

Storage Location : Main memory

Initial Value : Zero

Life : Until the program ends.

Scope : Global to the program.


Syntax:
extern [data_type] [variable_name];
ex: extern int var;

2.4. MODIFIERS IN C AND TYPE CASTING


2.4.1. NEED OF MODIFIERS:
Let us consider an example of a program, which will accept an age from the user to do
some processing. Because the age is represented in numbers, so we will have to use the integer
data type int. We all know that even under exceptional case an age of a person cannot exceed
more than 150. Now, that we are using an integer data type it occupies 2 Bytes of memory, which

would not be required to represent the value 150. Instead the value 150 could easily be saved in
an integer of 1 Byte in size, but the default size of an integer is 2 Bytes. So we have a problem
here. Well, note that we cant solve.
To override the default nature of a data type, C has provided us with data type modifiers as
follows:
Signed:
By default all data types are declared as signed. Signed means that the data type is capable of
storing negative values.
Unsigned:
To modify a data types behavior so that it can only store positive values, we require to use the
data type unsigned. For example, if we were to declare a variable age, we know that an age cannot
be represented by negative values and hence, we can modify the default behavior of the int data
type as follows:
unsigned int age;
This declaration allows the age variable to store only positive values. An immediate effect is that
the range changes from (-32768 to 32767) to (0 to 65536)
Long:
Many times in our programs we would want to store values beyond the storage capacity of the
basic data types. In such cases we use the data type modifier long. This doubles the storage
capacity of the data type being used.
E.g. long int annual salary will make the storage capacity of variable annual salary to 4 bytes. The
exception to this is long double, which modifies the size of the double data type to 10 bytes.
Please note that in some compilers this has no effect.

Short:
If long data type modifier doubles the size, short on the other hand reduces the size of the data
type to half. Please refer to the example of age variable to explain the concept of data type
modifiers. The same will be achieved by providing the declaration of age as follows:
short int age;
This declaration above, will provide the variable age with only 1 byte and its data range will be
from -128 to 127.

2.4.2. TYPE CASTING:


In computer science, type conversion or typecasting refers to different ways of,
implicitly or explicitly, changing an entity of one data type into another. This is done to take
advantage of certain features of type hierarchies or type representations. One example would be
small integers, which can be stored in a compact format and converted to a larger representation
when used in arithmetic computations. C allows programmers to perform typecasting by placing
the type name in parentheses and placing this in front of the value.

For instance
main()
{
float a;
a = (float) 5 / 3;
}
The above program gives result as 1.666666. This is because the integer 5 is converted to floating
point value before division and the operation between float and integer results in float.

From the above it is clear that the usage of typecasting is to make a variable of one type,
act like another type for one single operation. So by using this ability of typecasting it is possible
for create ASCII characters by typecasting integer to its character equivalent.
Typecasting is also used in arithmetic operation to get correct result. This is very much
needed in case of division when integer gets divided and the remainder is omitted. In order to get
correct precision value, one can make use of typecast as shown in example above. Another use of
the typecasting is shown in example below.
For instance:
main()
{
int a = 5000, b = 7000 ;
long int c = a * b ;
}
Here two integers are multiplied and the result is truncated and stored in variable c of type long
int. But this would not fetch correct result for all. To get a more desired output the code is written
as
long int c = (long int) a * b;
Though typecast has so many uses one must take care about its usage since using typecast in
wrong places may cause loss of data like for instance truncating a float when typecasting to an int.
#include <stdio.h>
main()
{
double d1 = 1234.56;
int i1=456;

printf("The value of d1 as int without cast operator %d\n",d1);


printf("The value of d1 as int with cast operator %d\n",(int)d1);
printf("The value of i1 as double without cast operator %f\n",i1);
printf("The value of i1 as double with cast operator %f\n",(double)i1);
i1 = 10;
printf("Effect of multiple unary operator %f\n",(double)++i1);
i1 = 10;
printf("Effect of multiple unary operator %f\n",(double)- ++i1);
i1 = 10;
printf("Effect of multiple unary operator %f\n",(double)- -i1);
i1 = 10;
printf("Effect of multiple unary operator %f\n",(double)-i1++);
}

Output:
The value of d1 as int without cast operator 1889785610
The value of d1 as int with cast operator 1234
The value of i1 as double without cast operator 1234.559570
The value of i1 as double with cast operator 456.000000
Effect of multiple unary operator 11.000000
Effect of multiple unary operator -11.000000
Effect of multiple unary operator 10.000000
Effect of multiple unary operator -10.000000

2.4.3. IMPLICIT CONVERSION:


Implicit conversions do not require any operator. They are automatically performed when a value
is copied to a compatible type.
For example:
short a=2000;
int b;
b=a;
Here, the value of a has been promoted from short to int and we have not had to specify any
type-casting operator. This is known as a standard conversion. Standard conversions affect
fundamental data types, and allow conversions such as the conversions between numerical types
(short to int, int to float, double to int...), to or from bool, and some pointer conversions. Some of
these conversions may imply a loss of precision, which the compiler can signal with a warning.
This

can

be

avoided

with

an

explicit

conversion.

2.4.4. EXPLICIT CONVERSION:


C is a strong-typed language. Many conversions, especially those that imply a different
interpretation of the value, require an explicit conversion. We have already seen two notations for
explicit type conversion: functional and c-like casting:

short a=2000;
int b;

b = (int) a;

// c-like cast notation

b = int (a);

// functional notation

2.4.4. TYPE CONVERSIONS IN EXPRESSIONS:


C permits mixing of constants and variables of different types in an expression, but during
evaluation it adhere to very strict rules of type conversion. If the operands are of different types,
the lower type is automatically converted to the higher type before the operation proceeds. The
result is of the higher type. Given below is the sequence of rules that are applied while evaluating
expressions.

All short and char are automatically converted to int.


If one of the operands is long double, the other will be converted to long double and the

result will be long double.


Else, if one of the operands is double, the other will be converted to double and the result

will be double.
Else, if one of the operands is float, the other will be converted to float and the result will

be float.
Else if one of the operand is unsigned long int, the other will be converted to unsigned
long int and the result will be unsigned long int.

C automatically converts all floating point operands to double precision. The final result of an
expression is converted to the type of the variable on the left of the assignment sign before
assigning the value to it. However, the following changes are introduced during the final
assignment:

Float to int causes truncation of the fractional part.


Double to float causes rounding of digits.
Long int to int causes dropping of the excess higher order bits.

CHAPTER 3
OPERATORS IN C

3.1. OPERATOR
An operator is a symbol that tells the computer to perform certain mathematical or logical
manipulations. C supports a rich set of operators. Operators are used in programs to manipulate data and
variables. They usually form a part of the mathematical of logical expressions.

C operators can be classified into a number of categories. They include:

Arithmetic

Relational

Logical

Increment or Decrement

Conditional

Bitwise

Assignment

Special

3.1.1.

ARITHMETIC OPERATORS:

C provides all the basic operators. The operators +, -, *, and / all work the same way as they do in
other languages. These can operate on any built-in data type allowed in C. The unary minus operator, in
effect, multiplies its single operand by -1.

Operator

Meaning

Addition Or Unary Plus

Subtraction Or Unary Minus

Multiplication

Division

Modulo Division

Integer division truncates any fractional part. The modulo division produces the remainder of an
integer division. Examples of arithmetic operators are:

ab

a+b

a*b

a/b

Here a and b are called operands. The modulo division operator % cannot be used on floating point data. C
does not have an operator for exponentiation.

Integer Arithmetic: When both the operands in a single arithmetic expression such as a + b are integers,
the expression is called as integer expression, and the operation is called integer arithmetic. Integer
arithmetic always yields an integer value. The largest integer depends on the machine. During integer
division, if both the operands are of same sign, the result is truncated towards zero, if one of them is
negative; the direction of truncation is implementation dependent. That is,
6/7 = 0 and -6/-7 = 0
But -6/7 may be zero or -1(machine dependent)
Similarly during modulo division, the sign of the result is always the sign of the first operand (the
dividend) this is
-14 % 3 = 2
-14 % -3 = -2
14 % -3 = 2

Real Arithmetic: An arithmetic operation involving only real operands is called real arithmetic. Any
operand may have either in decimal or exponential notation. Since floating point values are rounded to the
number of significant digits permissible, the final value is an approximation of the correct result.
If x, y and z are floats, then we will have:
X = 6.0/7.0 = 0.857143
Y = 1.0/3.0 = 0.333333
The operator % cannot be used with real operands.

Mixed_Mode Arithmetic: When one of the operand is real and the other is integer, the expression is
called mixed-mode arithmetic expression. If either operand is of the real type, then only the real expression
is performed and the result is always a real number. Thus
15/10 = 1.5
Where as
15/10 = 1

If the numerator term is less then the denominator term (b<a), then the following rules are applied.
1. b % a

gives b

2. (-b) % a

gives (-b)

3. (-b) % (-a) gives (-b)


4. b%(-a)

gives (-a)

If the division has both the numerator and denominator are real values then the result is also real. If it is
mixed that means one is 'int' and second is in 'float' then also the result is 'real'.
The +,-,*,and % are divided into two types.
They are,
1. low priority group and
2. high priority group
The low priority group is + and -.
The high priority group is * and /.

3.1.2.

RELATIONAL OPEARTOR:

We often compare two quantities, and depending on their relation, take certain decisions. For
example, we may compare the age of two persons, or the price of two items, and so on. These comparisons

can be done with the help of relational operators. Any expression which contains relational operators is
called relational expressions. The value of relational expression is either one or zero. If the specified
relation is true then result is one. If the specified relation is false then result is zero. C supports six
relational operators in all.
operator

Meaning

<

is less than

<=

is less than or equal to

>

is greater than

>=

is greater than or equal to

==

is equal to

!=

is not equal to

A simple relational expression contains only one relational operator takes the following form:
Arithmetic exp-1

relational operator

Arithmetic exp-2

Some examples of simple relational expressions and their values:

5.8 >=

TRUE

<=

TRUE

-90 >=

FALSE

TRUE

!=

When arithmetic expressions are used on either side of a relational operator, the arithmetic expressions will
be evaluated first and then the results compared. That is, arithmetic operators have a higher priority over
relational operators. Relational operators are used in decision statements such as, if and while to decide the
course of action of a running program.

3.1.3.

LOGICAL OPERATORS:

An expression which combines two or more relational expressions is termed as a logical


expression or a compound relational expression. A logical expression yields a value of one or zero.
Operator

Meaning

&&

Logical AND

||

Logical OR

Logical NOT

Truth table
op-1

op-2

op-1 && op-2

op-1 || op-2

non-zero

non-zero

non-zero

non-zero

3.1.4.

ASSIGNMENT OPERATORS:

Assignment operators are used to assign the result of an expression of a variable. In C has a set of
shorthand assignment operators of the form

v op = exp;

Where v is the variable, exp is an expression and op is a C binary arithmetic operator. The operator = is
known as the shorthand assignment operator.
the assignment statement

v op = exp;

v = v op(exp);
Is equivalent to
Consider an example
This is same as the statement

x += y+1;
x = x+(y+1). The shorthand operator += means add y+1 to x or

increment x by y+1.
Table: Shorthand assignment operators

statement with simple assignment operator

statement with shorthand operator

a=a+1

a += 1

a = a -1

a -= 1

a = a * (n +1)

a *= n+1

a = a/ (n+1)

a /= n+1

a = a %b

a %=b

The Use of Shorthand Assignment Operators has three advantages:

What appears on the left-hand side need not be replaced and therefore if becomes easier to write

The statement is more concise and easier to read.

The statement is more efficient.

3.1.5.

INCREMENT OR DECREMENT OPERATOR:


C has two very useful operators not generally found in other languages. These are the increment

and decrement operators:


++ and --

The operator ++ adds 1 to the operand while -- subtracts 1. Both are unary operators takes the following
form:
++m; or m++;
--m; or m--;
++m; is equivalent to m = m+1;(or m+=1;)
--m; is equivalent to m = m-1; (or m-=1;)
We use increment and decrement statements in for and while loops extensively.
While ++m and m++ mean the same thing when they form statements independently, they behave
differently when they are used in expressions on the right-hand side of an assignment statement. Consider
the following:
m = 5;
y = ++m;

In this case, the value of t and m would be 6. Suppose, if we write the above statements as
m = 5;
y = m++;
Then the value of y would be 5 and m would be 6. A prefix operator first adds 1 to the operand and then
the result is assigned to the variable on left. On the other hand, a postfix operator first assigns the value to
the variable on left then increments the operand.

3.1.6.

CONDITIONAL OPERATOR:

A ternary operator ? : is available in C to construct conditional expressions of the form


exp1 ? exp 2 : exp 3
Where exp1, exp2, and exp3 are expressions. The operator? : works as follows: exp1 is evaluated
first. If it is non-zero (true), then the expression exp2 is evaluated and becomes the value of the expression.

If exp1 is false, exp3 is evaluated and its value becomes the value of the expression. Note that only one of
the expressions (either exp2 or exp3) is evaluated.
Example program:
main()
{
int a, b, c;
printf(enter two values);
scanf(%d %d, &s, &b);
c = (a>b)? a:b;
printf(bigger value is %d, c);
}
OUTPUT:

enter two values 10 20


bigger value is 20.

3.1.7.

BIT WISE OPERATOR:

C has a distinction of supporting special operators known as bitwise operators for manipulation of
data at bit level. These operators are used for testing the bits, or shifting them right or left. Bitwise
operators may not be applied to float or double.

Operator

Meaning

&

Bitwise AND

Bitwise OR

Bitwise exclusive OR

<<

Shift left

>>

Shift right

Ones compliment

Table: Bitwise operators


BITWISE AND: Bitwise AND is denoted by the symbol & (ampersand). The & operator performs a
bitwise AND on two integers. Each bit in the result is 1 only if both corresponding bits in the two input
operands are 1. The following is a chart that defines &, defining AND on individual bits.
x

x&y

BITWISE OR: Bitwise OR is denoted by the symbol | (vertical bar). The | (vertical bar) operator
performs a bitwise OR on two integers. Each bit in the result is 1 if either of the corresponding bits in the
two input operands is 1. The following chart that defines |, defining OR on individual bits.

x|y

BITWISE XOR: Bitwise XOR is denoted by the symbol ^ (caret). The ^ (caret) operator performs a
bitwise exclusive-OR on two integers. Each bit in the result is 1 if one, but not both, of the corresponding
bits in the two input operands is 1. The following chart that defines Bitwise XOR

x^y

SHIFT LEFT: The << operator shifts its first operand left by a number of bits given by its second operand,
filling in new 0 bits at the right.

SHIFT RIGHT: The >> operator shifts its first operand right. If the first operand is unsigned, >> fills in 0
bits from the left, but if the first operand is signed, >> might fill in 1 bits if the high-order bit was already
1

ONEs COMPLIMENT: The ~ (tilde) operator performs a bitwise complement on its single integer
operand. Complementing a number means to change all the 0 bits to 1 and all the 1s to 0s.

3.1.8.

SPECIAL OPERATORS:

C supports some special operators of interest such as comma operator, size of operator, pointer
operators (& and *) and member selection operators (. And ->).

THE COMMA OPERATOR: The comma operator can be used to link the related expressions together. A
comma-linked list of expressions is evaluated left to right and the value of right-most expression ids the
value of the combined expression. For example the statement
value = (x=10, y=5, x+y);

First assigns the value 10 to x, then assigns 5 to y, and finally assigns 15(10+ 5) to value. Since comma
operator has lower precedence of all operators, the parentheses are necessary. Some applications of comma
operator:
In for loops:
for(n = 1, m = 10; n <= m; n++, m++)
in while loops:
while(c = getchar(), c!=10)
exchanging values:
t = x, x = y, y = t;

THE SIZEOF OPERATOR: The size of is a complier time operator and, when used with an operand, it
returns the number of bytes the operand occupies. The operand may be a variable, a constant or a data type
qualifier.

Examples:

m = sizeof(sum);
n = sizeof(long int)

The size of operator is normally used to determine the lengths of arrays and structures when their sizes are
not known to the programmer. It is also used to allocate memory space dynamically to variables during
execution of a program.

3.2. OPERATOR PRECEDENCE AND ASSOCIATIVITY:

Each operator in C has a precedence associated with it. This precedence is used to determine how
an expression involving more than one operator is evaluated. There are distinct levels of precedence and an

operator may belong to one of the levels. The operators at the higher level of precedence are evaluated
first. The operators are of same precedence are evaluated either from left to right or from right to left,
depending on the level. This is known as the associativity property of an operator. The groups are listed in
the order of decreasing precedence (rank 1 indicates the highest precedence level and 15 the lowest)

3.2.1.

OPERATOR PRESEDENCE TABLE:

Operator

Description

Associativly

Prority

()

Function call

Left to Right

[]

Subscript

Left to Right

Logical Negation

Right to Left

Bit wise Not

Uniary plus

Uniary minus

++

Increment

--

Decrement

Directional

&

Address

(Type)

type casting

size of

size of an object

Multiplication

Left to Right

Division

Modulo Division

Addition

Left to Right

Subtraction

<<

Left shift

Left to Right

>>

Right shift

< or <=

Less than

Left to Right

> or >=

Greater than

Equity

Left to Right

!=

Not equal

&

Bit wise And

Left to Right

Bit wise Or

Left to Right

Bit wise exclusive Or Left to Right

10

&&

Logical And

Left to Right

11

Logical Or

Left to Right

12

Conditional

Left to Right

13

Assignment

Right To Left

14

Operational

14

Left to right

15

?:
Op

Assignment

(+=,-

=,*=,/=,%=)
,

Coma

Consider the following statement:


If (x ==10 + 15 && y<10)

The precedence rule say that the addition operator has the higher priority and the logical operator (&&)
and the relational operator (++ and <). Therefore, the addition of 10 and 15 is executed first. This is
equivalent to:
If (x == 25 && y < 10)

The next step is to determine whether x is equal to 25 and y is less than 10. If we assume a value of 20 for
x and 5 for y, then
x == 25 is false (0)
y < 10 is true (1)
Note that since the operator < enjoys a higher priority compared to +++, y, 10 is tested first and then x ==
25 is tested. Finally we get:

if( FALSE && TRUE)


Because one of the conditions is FALSE, the complex condition is FALSE.

3.2.2.

PRECEDENCE OF ARITHMETIC OPERATORS:

An arithmetic expression without parentheses will be evaluated from left to right using the rules of
precedence of operators. There are two distinct priority levels of arithmetic operators.
High priority

* ? %

Low priority

+ -

The basic evaluation procedure includes two left to right passes through the expression. During the first
pass, the high priority operator (if any) is applied as they are encountered. During the second pass, the low
priority operators (if any) are applied as they are encountered.

CHAPTER 4
CONTROL STATEMENTS

C language provides 2 types of control statements

Branching Statements

Looping Statements

4.1.

BRANCHING STATEMENTS:

4.1.1. If Statement:
This is the most simple form of the branching statements. It takes an expression in parenthesis
and a statement or block of statements. If the expression is true then the statement or block of
statements gets executed otherwise these statements are skipped.
Syntax:
if (expression)
statement;
or
if (expression)
{
Block of statements;
}

4.1.2. If else
The set of statements inside if block is executed only if the condition inside the
parenthesis of if comes true. Otherwise the set of statements in Else block will be executed.

Syntax:
if (expression)
{
Block of statements;
}
else
{
Block of statements;
}

4.1.3. Ladder If else


The set of statements inside if block is executed only if the condition inside the
parenthesis of if comes true. Otherwise the set of statements in Else block will be executed
only when expression in else if becomes true.
Syntax:
if (expression)
{
Block of statements;
}
else if (expression)
{
Block of statements;
}

4.1.4. Nested If else


A If-Else block inside an another if or else block is called nested if-else
if (expression1)
{
Block of statements;
if (expression2)
{

Block of statements;
}
else
{
Block of statements;
}
}
else
{
Block of statements;
if (expression3)
{
Block of statements;
}
else
{
Block of statements;
}
}

4.1.5. Switch Statement


The switch statement is much like a nested if else statement. switch statement can be slightly
more efficient and easier to read.
Syntax
switch( expression )
{
case constant-expression1:

statements1;

[case constant-expression2:

statements2;]

[case constant-expression3:

statements3;]

[default : statements4;]
}

4.2.

Looping Statements:

In looping, a sequence of statements is executed until some conditions for termination of


the loop are satisfied. A program loop therefore consists of two segments, one known as the body
of the loop and the other known as the control statement. The control statement tests certain
conditions and then directs the repeated execution of the statements contained in the body of the
loop. Depending on the position of the control statement in the loop, a control structure may be
classified either as the entry-controlled loop or as the exit controlled loop.
In the entry-controlled loop, the control conditions are tested before the start of the loop
execution. If the conditions are not satisfied, then the body of the loop will not be executed. In the
case of an exit-controlled loop, the test is performed at the end of the body of the loop and
therefore the body is executed unconditionally for the first time.

The test conditions should be carefully stated in order to perform the desired number of
loop executions. It is assumed that the test conditions will eventually transfer the control out of
the loop, due to some reason it does not do so, the control sets up an infinite loop and the body is
executed over and over again.
A looping process, in general, would include the following four steps:

Setting and initialization of a counter.


Execution of the statements in the loop.
Test for a specified conditions for execution of the loop.
Incrementing/decrementing the counter.

The test may be either to determine whether the loop has been repeated the specified number of
times or to determine whether a particular condition has been met.
The C language provides for three loop constructs for performing loop operations. They are:

The while statement.


The do statement.
The for statement.

4.2.1. for Loop:


Structure of for loop
for( expression1; expression2; expression3)
{
Single statement
or
Block of statements;
}

In the above syntax:

expression1 - Initialise variables.

expression2 - Condtional expression, as long as this condition is true, loop will keep
executing.

expression3 - expression3 is the modifier which may be simple increment of a variable.

Expression1 will be executed only once when the loop begins for the 1st iteration. Executes the
block of statements only if expression 2 is evaluated as true (1).
Benefits of for loop

Reduces code length


Finite and infinite loops

Structure of FOR loop with examples.

for(i= 9; i>=0; i = i-1)


{
printf (%d,i);
}
printf(\n);
This loop is executed 10 times, but the output would be from 9 to 0 instead of 0 to 9. Since
the conditional test is always performed at the beginning of the loop, the body of the loop may not
be executed at all, if the condition fails at the start.

Benefits of FOR loop.


1.

The unique aspect of for loop is that one or more sections can be omitted, if necessary.

Consider the following statements:


.

m = 5;
for( ; m != 100; )
{
printf(%d\n, m);
m = m + 5;
}
Both initialization and increment sections are omitted in the for statement. The
initialization has been done before the for statement and the control variable is incremented inside
the loop. In the above case the increment and initialization are left blank. However, the
semicolons separating the sections must remain. If the test condition is not present, the for
statement sets up and infinite loop. Such loops can be broken using break or goto statements in
the loop.
2.

The time delay can be set up using the for loop as follws,
for(j =1000; j > 0; j = j-1)
This loop is executed 1000 times without producing any output, it simply causes a time
delay.

4.2.2. while statement:


The while is an entry-controlled loop statement. The text condition is evaluated and if the
condition is true, then the body of the loop is executed. After execution of the body, the testcondition is once again evaluated and if it is true, the body is executed once again. This process
continues until the test condition becomes false and the control is transferred out of the loop. On
exit, the program continues with the statements immediately after the body of the loop.
The syntax of the while loop is as given below:
while ( expression )
{
Single statement
or
Block of statements;
}

Structure of WHILE loop with examples.


sum = o;
n = 1;
while (n<=10)
{
sum = sum + n*n;
n = n+1;
}
printf(sum = %d\n, sum);

The body of the loop is executed 10 times for n = 1,2,3.10 each time adding the square
of the value of n, which is incremented inside the loop. The test condition may also be written as
n<11

Benefits of WHILE loop.

It helps to iterate set of statements for infinite number of times until power is down
It helps to run the code forever, as few embedded systems will not contain operating
system in it.

And also how to use in Embedded Development.


Comparison between WHILE and FOR loops.

4.2.3. do-while Statement:


do ... while is just like a while loop except that the test condition is checked at the end of the loop rather
than at the beginning. This has the effect that the content of the loop are always executed at least once.
do
{
Single statement
or
Block of statements;
}while(expression);

Structure of DO-WHILE loop with examples.


main()
{
int n,i;
printf(enter a value);
scanf(%d, &n);
i=1;
do
{
printf(%d,i);
i++;
}while(i<=n);
}

OUTPUT:

Enter a value 5
12345

C provides two commands to control how we loop:

4.3.

Break Statement:
We use break statement in both control structures and looping structures. When the
break statement is encountered inside a loop, the loop is immediately exited and the
program continues with the statement immediately following the loop. When the loops are
nested, the break statement would only exit from the loop containing it. That is, break is
exit only a single loop.

4.4.

Continue Statement:
Like the break which causes the loop to be terminated, the continue, as the name implies,

causes the loop to be continued with the next iteration after skipping any statements in between.
The continue statement tells the complier, SKIP THE FOLLOWING STATEMENT AND
CONTINUE WITH NEXT OTERATION. In while and do loops, continue causes the control to
go directly to the test condition and then to continue the iteration process. In the case of for loop,
the increment section of the loop is executed before the test-condition is evaluated.

CHAPTER 5
FUNCTION
A function is a block of code that has a name and it has a property that it is reusable i.e. it
can be executed from as many different points in a C Program as required. Function groups a
number of program statements into a unit and gives it a name. This unit can be invoked from
other parts of a program. A computer program cannot handle all the tasks by itself. Instead its
requests other program like entities called functions in C to get its tasks done. A function is a
self contained block of statements that perform a coherent task of same kind
The name of the function is unique in a C Program and is Global. It names that a function
can be accessed from any location within a C Program. We pass information to the function called
arguments specified when the function is called. And the function either returns some value to
the point it was called from or returns nothing. We can divide a long C program into small blocks
which can perform a certain task. A function is a self contained block of statements that perform a
coherent task of same kind.

5.1.

STRUCTURE OF A FUNCTION:

All functions have thefunction


form:
name(argument list)
argument declaration;
{
local variable declarations;
executable statement1;
executable statements2;
.......
return(expression);
}

All parts are not essential. Some may be absent. For example, the argument list and its
associated argument declaration parts are optional. The return statement is the mechanism for
returning a value to the calling function. This is also an optional statement. Its absence indicates
that function does not return any value.
5.1.1. Function Header:
In the first line of the above code
int sum(int x, int y)
It has three main parts
1. The name of the function i.e. sum
2. The parameters of the function enclosed in parenthesis
3. Return value type i.e. int

5.1.1. Argument List:


The argument list contains valid variable names separated by commas. The list must be
surrounded by parentheses. Note that no semicolon follows the closing parenthesis. The
argument variables receive values from the calling function, thus providing a means for data
communications from the calling function to the called function. Some examples of
functions with arguments are:
quadratic(a,b,c)
mul(a,b)
All arguments variables must be declared for their types after the function header and before the
opening brace of the function body.

5.1.2. Function Body:


Whatever is written with in { } in the above example is the body of the function.

5.1.3. Function Prototypes:

The prototype of a function provides the basic information about a function which tells the
compiler that the function is used correctly or not. It contains the same information as the
function header contains. The prototype of the function in the above example would be like
int sum (int x, int y);
The only difference between the header and the prototype is the semicolon; there must the
semicolon at the end of the prototype. Functions groups a number of program statements into a
unit and gives it a name. This unit can be invoked from other parts of a program. A computer
program cannot handle all the tasks by itself. Instead its requests other program like entities
called functions in C to get its tasks done. A function is a self contained block of statements that
perform a coherent task of same kind.

5.2. Why we use functions?


The most important reason to use functions is to aid in the conceptual organization of a
program. Another reason to use functions is to reduce program size. Any sequence of instructions
that appears in program more than once is a candidate for being made into a function. The
functions code is stored in only one place in memory, even though the function is executed many
times in the course of the program.
Two reasons
1. Writing functions avoids rewriting the same code over and over.
2. Using functions it becomes easier to write programs and keep track of what they are
doing.
Advantages:
It is easy to use.

Debugging is more suitable for programs.

It reduces the size of a program.

It is easy to understand the actual logic of a program.

Highly suited in case of large programs.

By using functions in a program, it is possible to construct modular and structured


programs.

5.3. Function Declaration:


Just as you cant use a variable without first telling the compiler what it is, you also cant
use functions without telling the compiler about it, There are two ways to do this. The approach
we show here its o declare the function before it is called. The other approach is to define it before
its called. ; well examine that next.) in the Table program, the functions star line() is declared in
the line.
Void star line ( );
The declaration tells the compiler that at some later point we plan to present a function called star
line. The keyword void specifies that the function has no return value, and the empty parentheses
indicate that it takes no arguments.
Notice that the functions declarations is terminated with a semicolon It is a complete
statement in itself. Function declarations are also called prototypes, since they provide a model or
blueprint for the function. They tell the compiler, a function that looks like this is coming up
later in the program, so its all right if you see references to it before you see the function itself.

5.4. Calling the Function:


The function is called (or invoked) three times from main (). Each of the three calls look
like this:
Star line():
This is all we need to call a function name, followed by parentheses. The syntax of the call is very
similar to that of declaration, except that the return type is not used. A semicolon terminates the
call. Executing the call statement causes the function to execute; that is, control is transferred to
the function, the statement in the function definition are executed, and then control returns to the
statement following the function call.
Ex:

PTO

Note: main is also a function which is used to indication to complier to where from the
completion should start.

The function is basically divided into two types. They are


1. User defined and
2. Pre-defined functions
The main distinction between user-defined and library function is that the former are not
required to be written by user while the latter have to be developed by the user at the time of
writing a program

5.5.

User Defined Functions:

A User-Defined Function, or UDF, is a function provided by the user of a program or


environment, in a context where the usual assumption is that functions are built into the program
or environment. The data communication from calling function to called function can be achieved
by parameters or arguments. The arguments and parameters are equal but the variables present at
the calling function are called Actual parameters and variables present at the function definition
then they are called formal parameters. The actual parameters may be constants, variables (or)
expressions. The formal parameters must be variables. We can pass only one value to the
definition of the function to called function by using return values.
Based on the arguments and parameters they are divided into three types. They are
1. Function with no arguments and no return values,
2. Function with arguments and no return values and
3. Function with arguments and return values.

5.6.

Function with no arguments and no return values:


In this we not pass any arguments to definition of the function and we do return any value

to the calling function.

Ex:
main()
{
sum();
}

void sum()
{
int a,b;
printf(Enter any 2 no's:);
scanf(%d,&a,&b);
printf(sum of numbers:%d, a+b);
}
The above function not sending any arguments to function definition and not receiving anything
from function definition.

5.7.

Function with arguments and no return values:


In this we are passing arguments to defination of the function and we are not going to

return any value to the calling function.

Function2()

Eg:

Function1()

Sending
Arguments

..............;

..............;

..............;

..............;

main()
..............;
{

Function2();
}

..............;
No return Value

..............;
}

int a,b;
printf(Enter any 2 no's:);
scanf(%d,&a,&b);
sum(a,b);

// sending arguments to function definition

}
void sum(int a, int b) // a and b local variables to function definition
{
printf(sum of numbers:%d,a+b);
}

The above function we are sending arguments as a & b to function definition and are received
by formal parameters a and b and not returning to any information to the called function.

5.8.

Function with arguments and return values:


In this we are passing arguments to definition of the function and we are going to return

the result of function definition to the calling function.


Function1()
{

Sending
Arguments

Function2()
{
..............;

..............;

..............;

..............;

returning Value to

..............;

called function

Function2();

Ex:

..............;
return(c);
}

main()
{
int a,b,c;
printf(Enter any 2 no's:);
scanf(%d,&a,&b);
c=sum(a,b);

// sending arguments to function definition

printf(Sum of two numbers:%d,c);


}
void sum(int a, int b)// a and b local variables to
function definition
{
return(a+b);

// sending result to the called function

}
The above function we are sending arguments as a & b to function definition and are received by
formal parameters a and b and returning the result to called function and received by the variable
C at to the called function.

5.9.

Handling of non-integer functions:


C function returns a value of the type as the default case when no other type is specified

explicitly. For example,


return (sum);
Returns only the integer part of sum. This is due to the absence of the type-specifier in the
function header. In this case, we can accept the integer value of sum because the truncated
decimal part is insignificant compared to the integer part. We must do two things to enable a
calling function to receive a non-integer value from a called function:

The explicit type specifier, corresponding to the data type required must be mentioned in
the function header. The general form of the function definition is:
Type-specifier function-name (argument list)
argument declaration;
{

The type specifier tells the compiler, the type of data the function is to return.
The called function must be declared at the start of the body in the calling function, like
any other variable. This is to tell the calling function the type of data that the function is
actually returning.

main()
{
float a, b, mul();
double div();
a = 12.345;
b = 9.82;
printf(%f\n, mul(a,b));
printf(%f\n, div(a,b));

Example program:

}
float mul(x,y)
float x,y;
{
return(x * y);
}
double div(p,q)
double p,q;
{
return(p/q);
}

The declaration part of main function declares not only variables but the functions mul
and div as well. This only tells the complier that mul will return a float type value and div a
double type value Parentheses that follow mul and div specify that they are functions instead of
variables. If we mismatch between the type of data that the called function returns and the type of
data that the calling function expects, we will have unpredictable results.

5.10. Function returning nothing:


Consider the program:
main()
{
printline();
value();
printline();
}
printline();
{
..........

The functions print line() and value() do not return any values and therefore they were not
declared in the main. Although the program works nicely, we can declare them in them main with
the qualifier void. This states explicitly that the functions do not return values. This prevents any
main()

accidental use of these functions in expressions.


{
void printline();
void value();
void printline();
}
void printline();
{
..........

5.11. Nesting of functions:


C permits nesting of functions, main can call function1, which calls function2, which calls
function3 and so on. Consider the following example:

main()
{
int a,b,c;
float ratio();
scanf(%d%d%d,&a,&b,&c);
printf(%fn,ratio(a,b,c));
}
float ratio(x,y,z)
int x,y,z;
{
if(difference(y,z))
return(x/y-z));
else
return(0,0);
}
difference(p,q)
{
int p,q;
{
if(p!=q)
return(1);
else
return(0);
}

The above program calculates the ratio a/(b-c), and prints the result. we have the following three
functions:
main ()
ratio ()
difference ()
Main reads the values of a, b and c and calls the function ratio to calculate the value a/(b-c). This
ratio cannot be evaluated if (b-c) = o. Therefore, ratio calls another function difference to test
whether the difference (b-c) is zero or not. Difference returns 1, if b is not equal to c; otherwise
returns zero to the function ratio. In turn, ratio calculates the value a/(b-c) if it receives 1 returns
the result in float. In case, ratio receives zero form difference, it sends back 0.0 to main including
that (b-c) = 0.

5.12. Recursive Function:


When a called function in turn calls another function a process of chaining occurs. When
a function calls itself then it is called as 'recursive function.
main()
{
printf(this an example of recursion \n);
main();
}

When executed, this program will produce an output as:


This is an example of recursion
This is an example of recursion
This is an example of recursion
Execution is terminated abruptly; otherwise the execution will continue indefinitely.
Another example of recursion is the evaluation of factorials of a given number. The factorial of a
number n is expressed as a series of repetitive multiplications.
Features:

There should be at least one if statement used to terminate recursion.

It does not contain any looping statements.

Advantages:

It is easy to use.

It represents compact programming structures.

Disadvantages:

It is slower than that of looping statements because each time function is called.

5.13. Macro
Definition of Macro
A macro is a fragment of code which has been given a name and performs the specified
operation by replacing the macro name with the text it has been used to represent
Different types of Macros
Macros with Parameters or object like macros

Ex. #define BUFFER_SIZE 1024

Macros without parameters or function like macros


Ex. #define MAX(X, Y) ((X>Y)?X:Y))

How to use Macros in Embedded Development


Start the declaration of macro with the #define pre-processor directive
The name of the macro should be in capitals, which is widely used and

distinguishes from ordinary variables


There should not be any spaces in between the macro name
Only letters, digits and underscore character can be used and first letter cannot be a

digit
The following representation will gives the idea with regards to macro declaration

Use parenthesis around an argument or a definition as a whole

Benefits of Macros
Define once use many criteria
The time taken to execute the code will be reduced
Increase the readability of the code

CHAPTER 6
POINTERS
6.1.

Introduction:
Pointers are another important feature of C language. Although they may appear a little

confusing for a beginner, they are a powerful tool and handy to use once they are mastered. There
are number of reasons for using pointers.

A pointer enables us to access a variable that is defined outside the function.


Pointers are more efficient in handling data tables.
Pointers reduce length and complexity of a program.
They increase the execution speed.
The use of a pointer array to character strings results in saving of data storage space in
memory.

6.2. Understanding pointers:


A pointer is a variable which holds the address of the storage location for another given
variable. C provides two operators & and * which allow pointers to be used in many versatile
ways.
& and *
The & and * operators have already been used once to hand back values to variable parameters.
They can be read in a program to have the following meanings:
& the address of...
* The contents of the address held in...

This reinforces the idea that pointers reach out an imaginary hand and point to some location in
the memory and it is more usual to speak of pointers in this way. The two operators * and & are
always written in front of a variable, clinging on, so that they refer, without doubt, to that one
variable. For instance, &x the address at which the variable x is stored. *ptr the contents of
the variable which is pointed to by ptr.
Consider the following c statement:
int x=2;
The above statement requests compiler to execute following steps:

Reserve the required space (depending upon the data type and computer configuration) for

the variable (randomly selected out of free memory pool)


Assign as name for that reserved space
Store the integer value 2 in the reserved space

And we can find out the starting location number of that reserve space by the following statement,
& operator is used find the address of the variable.
printf (Address is %u, &x);
Suppose we get the output of the above statement as 8621 which is the starting address of the
reserved space and hence we can represent the memory map for the variable i as:

If we run the same statement int x=2; again then the same steps would be following but the
memory location selected can be different from 8621. Reason being that the compiler randomly
selects the location from the large pool of free memory spaces and every time we select it, there
are rare chances of same memory location being selected.
The pointer, as the name suggests, is something which is pointing to or directing to
something. The pointer is used to store the address of another variable and the data type of the
pointer is same as data type of variable it is pointing to. As the variable which points to other
variable is called pointer and the variable which is pointed to by the pointer is called Pointee. We
represent the relation between the two as:

We can also have pointer to pointer and we declare it as:


int **z;
z=&y;
And the memory map can be represented as:

Note: Types of operations on pointers like addition of pointers, multiplying pointer by number,
dividing pointer by number are illegal.

6.3. Pointers and its initilisation:


Something to be varying of with pointer variables is the way that they are initialized. It is
incorrect, logically, to initialize pointers in a declaration. A compiler will probably not prevent
this however because there is nothing incorrect about it as far as syntax is concerned.
Think about what happens when the following statement is written. This statement is really
talking about two different storage places in the memory:
int *a = 2;
First of all, what is declared is a pointer, so space for a `pointer to int' is allocated by the program
and to start off with that space will contain garbage (random numbers), because no statement like
a = &some int; has yet been encountered which would give it a value. It will then attempt to fill
the contents of some variable, pointed to by a, with the value 2. This is doomed to failure. a only
contains garbage so the 2 could be stored anywhere. There may not even be a variable at the place

in the memory which a points to. Nothing has been said about that yet. This kind of initialization
cannot possibly work and will most likely crash the program or corrupt some other data.

6.4. Typecasting in pointers:


It is tempting but incorrect to think that a pointer to an integer is the same kind of object as
a pointer to a floating point object or any other type for that matter. This is not necessarily the
case. Compilers distinguish between pointers to different kinds of objects. There are occasions
however when it is actually necessary to convert one kind of pointer into another. This might
happen with a type of variable called "unions" or even functions which allocate storage for special
uses. These objects are met later on in this book. When this situation comes about, the cast
operator has to be used to make sure that pointers have compatible types when they are assigned
to one another. The Cast Operator, is written in front of a variable to force it to be a particular
type: (type) variable
For pointers it is: (type *) pointer
Look at the following statement:
char *ch;
int *i;
i = (int *) ch;
This copies the value of the pointer ch to the pointer i. The cast operator makes sure that the
pointers are in step and not talking at cross purposes. The reason that pointers have to be cast
into shape is a bit subtle and depends upon particular computers. In practice it may not actually do
anything, but it is a necessary part of the syntax of C.

6.5. Pointer expressions:


Like any other variable, pointer variable can be used in arithmetic expressions. For
example if p1 and p2 are properly declared and initialized pointers, then the following statements
are valid.

y=*p1**p2;
sum=sum+*p1;
z=5*-*p2/p1;
*p2 = *p2 + 10;
C language allows us to add integers to, subtract integers from pointers as well as to subtract one
pointer from the other. We can also use short hand operators with the pointers p1+=; sum+=*p2;
etc., we can also compare pointers by using relational operators the expressions such as p1 > p2,
p1==p2 and p1! =p2 are

allowed.

/*Program to illustrate the pointer expression and pointer arithmetic*/


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

ptr1,ptr2;

int

a,b,x,y,z;

a=30;b=6;
ptr1=&a;
ptr2=&b;
x=*ptr1+*ptr26;
y=6*-*ptr1/*ptr2+30;
printf(nAddress

of

+%u,ptr1);

printf(nAddress

of

%u,ptr2);

printf(na=%d,

b=%d,a,b);

printf(nx=%d,y=%d,x,y);
ptr1=ptr1

70;

ptr2= ptr2;
printf(na=%d,
}

b=%d,a,b);

6.6. Pointer increment and scale factors:


Pointers can be incremented like, p1 = p1 + 2; p1 = p1 + 1; an expression can be like p1+
+; Will cause the pointer p1 to point to the next value of its type. For example, if p1 is an integer
pointer with an initial value, say 2800, then after the operation p1 = p1 +1, the value of p1 will be
2802, and not 2801. Its value is increased by the length of the data type that its points to. This
length is called the scale factor.

6.7. Pointers and Arrays:


Pointers do not have to point to single variables. They can also point at the cells of an
array. For example, we can write
int *ip;
int a[10];
ip = &a[3];
We would end up with ip pointing at the fourth cell of the array a (remember, arrays are 0-based,
so a [0] is the first cell). We could illustrate the situation like this:

We would use this ip just like the one in the previous section: *ip gives us what ip points to,
which in this case will be the value in a [3]. Once we have a pointer pointing into an array, we can
start doing pointer arithmetic. Given that ip is a pointer to a [3], we can add 1 to ip: ip + 1; In C, it
gives a pointer to the cell one farther on, which in this case is a[4]. To make this clear, let's assign
this new pointer to another pointer variable: ip2 = ip + 1;
Now the picture looks like this:

6.8. Arrays of pointers:


We can have arrays of pointers since pointers are variables. Arrays of Pointers are a data
representation that will cope efficiently and conveniently with variable length text lines. This
eliminates:

Complicated storage management


High overheads of moving lines

Syntax of declaring a pointer:


data_type_name

* variable

name

First of all, specify the data type of data stored in the location, which is to identified by the
pointer. The asterisk tells the compiler that you are creating a pointer variable. Then specify the
name of variable. You can see in the given example, we have created an array of pointers of
maximum size 3. Then we have assigned the objects of array pointer.
array[0] = &x;
array[1] = &y;
array[2] = &z;

#include <stdio.h>
#include <conio.h>
main()
{
clrscr();
int *array[3];
int x = 10, y = 20, z = 30;
int i;
array[0] = &x;
array[1] = &y;

array[2] = &z;
for (i=0; i< 3; i++)
{
printf("The value of %d= %d ,address is %u\t \n", i, *(array[i]),array[i]);
}
getch();
return 0;
}
Output:

The information about how arrays are stored was not included just for interest. There is
another way of looking at arrays which follows the BCPL idea of an array as simply a block of
memory. An array can be accessed with pointers as well as with [] square brackets. The name of
an array variable, standing alone, is actually a pointer to the first element in the array.
For example: if an array is declared float numbers [34]; numbers is a pointer to the first floating
point number in the array; numbers is a pointer in its own right. (In this case it is type pointer to
float.) So the first element of the array could be accessed by writing:
numbers [0] = 22.3;
*numbers = 22.3;

6.9. Memory Map:


In C language we have different types of variables like global variable, local variable,
parameter to the function and dynamically allocated variable. But do we know how memory is
allocated to these variables and where are these variables stored? This concept is very important
to understand. So lets discuss this and understand the language better which would help us in
dealing with many errors in the program.

We consider 3 kinds of memory in a computer system

Fixed Memory
Stack Memory
Heap Memory

6.10. Fixed memory:


This memory is used to store the program written or the application being run (i.e. the
executable code) and the constant variables or other constant structures. The global and the static
variables are also stored in the fixed memory. This memory is categorized into code memory,
data memory etc. The code memory stores the executable code while the data memory stores the
global and the static variables.

6.11. Stack memory:


The stack memory is a data structure which follows the policy of Last in First out
(LIFO).The stack memory is used to store the static data which includes the variables which are
declared at the start of the program like the fixed arrays, local variables and the parameters which
are passed to a function during the function call. Other than this the return address pointer, frame
pointer (the pointer which is used to point to the starting of the frame just below) and other
registers. The life of the static variables ends as soon as the function returns or the program
execution stops. The stack memory is used separately for separate programs in an operation
system. The memory in stack is allocated at the compile time.
Disadvantage: The memory declared first remains the same i.e. if we declare large memory then
there is wastage of memory while if we declare lesser memory then we are in a problem.
Advantage: The memory allocated is de allocated automatically after the function returns and
hence the same memory is available for re-use again

6.12. Heap memory:


The heap memory is used to allocate space to the dynamic data. The data whose size can
shrink and expand as the requirements vary. We can allocate the extra memory whenever required
using command such as malloc (), calloc (), realloc () and de-allocate the space already allocated
using command such as free (), delete ().
The memory in heap is allocated at the run time. We can take HEAP memory as a group of
nodes (circles) and every node is reachable only if It has a direct or indirect reference from some
root node (pointer) which is stored in STACK memory. When we use memory allocation
functions like malloc, calloc or realloc the memory node are selected and linked to the specified
root node. Now if we dont free the nodes of HEAP memory before the root node is de-allocated,
the reference to those memory nodes is lost and they become unreachable, hence known as
garbage memory or memory leak. Hence to avoid this problem the programmer must free the
memory after its use.

Figure: Memory management in C


Advantage: This memory can be anytime shrunk or expanded whenever the requirements of the
program changes.

Disadvantage: We have to manually de allocate the memory allocated using function like free or
delete, otherwise the memory which is not de allocated at the proper time goes to the garbage and
is not available for re-use.
Illustration with Simple Program:
int x=4;
main()
{
int z;
char* y;
y= malloc(6);
y=hello;
printf(%c, *y);
z = square(x);
printf(%d, z);
free(y);
}
int square(int k)
{
return k*k;
}
Now we see which variables in the program are stored where. In this program we have
different types of variables like x as global variable, z & k as local variable and as parameter to
the function and y is dynamically allocated variable. So x is stored in fixed memory, z & k are
stored in Stack Memory and the pointer y is also stored in stack memory while the 6 bytes
(allocated by malloc) which are pointees of pointer y are stored in heap memory.

Pragma & Scope of Variables

The #pragma directive is the method specified by the C standard for providing additional
information to the compiler, beyond what is conveyed in the language itself. #pragma' is for
compiler directives that are machine-specific or operating-system-specific, i.e. it tells the compiler
to do something, set some option, take some action, override some default, etc. that may or may
not apply to all machines and operating systems

#pragma config setting = state|value


#pragma config register = value

where setting is a configuration setting descriptor, e.g., WDT, and state is a textual
description of the desired state, e.g., OFF. The value field is a numerical value that can
be used in preference to a descriptor.
Consider the following PIC18-only examples.
#pragma config WDT = ON // turn on watchdog timer
#pragma config WDT = 1 // an alternate form of the above
#pragma config WDTPS = 0x1A // specify the timer postscale value

Derivative Data types:


1) Arrays: Definitions, declaration, types of Arrays with examples. How to use in embedded
development
a. Definition of a array
Array is a collection of same type elements under the same variable identifier referenced by
index number. Arrays are widely used within programming for different purposes such as
sorting, searching and etc. Arrays are used to store a group of data of a single type. Arrays
are efficient and useful for performing operations. You can use them to store a set of high
scores in a video game, a 2 dimensional map layout, or store the coordinates of a multidimensional matrix for linear algebra calculations.
Arrays are of two types single dimension array and multi-dimension array. Each of these array
type can be of either static array or dynamic array. Static arrays have their sizes declared
from the start and the size cannot be changed after declaration. Dynamic arrays that allow

you to dynamically change their size at runtime, but they require more advanced techniques
such as pointers and memory allocation.
b. Declaration of a array
Arrays can be declared using any of the data types available in C. Array size must be declared
using constant value before initialization. A single dimensional array will be useful for
simple grouping of data
Syntax: <data type> array_name[size_of_array];
Sample code : char game_map[4];
c. Initialization of array
Initializing Single Dimension Arrays
Array can be initialized in two ways, initializing on declaration or initialized by assignment.
Initializing on Declaration
If you know the values you want in the array at declaration time, you can initialize an array as
follows:
Syntax:
<data type> array_name[size_of_array] = {element 1, element 2, ...};
Sample code:
char game_map[3] = {'S', 'R', 'D'};
d.

Performing operations on array

Accessing Single Dimension Array Elements


Arrays are 0-indexed, so the first array element is at index = 0, and the highest is size_of_array
1. To access an array element at a given index you would use the following syntax:
Syntax:
array_name[index_of_element];
Sample code
array_name[index_of_element] = value;
e. Use of array in embedded system
i.
Memory read and write
ii.
Displaying a string on a LCD
2)
a.

Structure: definitions, declaration, with examples. How to use in embedded development


Definition of a structure

A structure is a collection of variables under a single name. The variables can be of different
types, and each has a name which is used to select it from the structure. A structure is a
convenient way of grouping several pieces of related information together.A structure can be
defined as a new named type, thus extending the number of available types. It can use other
structures, arrays or pointers as some of its members
b. Structure definition
Here is the common syntax of structure definition:
struct struct_name{ structure_member1;
structure_member2;
.
structure_member n
};
Structure declaration
struct struct_name{ structure_member1;
structure_member2;
.
structure_member n
}var1,var2 var n;

OR
struct struct_name var1,var2 var n

c. Accessing a structure
<Var_name>.<structure_member>
d. Initialization of structure
Structure members can be initialized when you declare a variable of your structure:
Sample code:
struct object player1 = {player1, 0, 0};
The above declaration will create a struct object called player1 with an id equal to player1,
xpos equal to 0, and ypos equal to 0.
To access the members of a structure, you use the . (scope resolution) operator. Shown below
is an example of how you can accomplish initialization by assigning values using the scope
resolution operator:
Sample Code:

struct object player1;


player1.id = player1;
player1.xpos = 0;
player1.ypos = 0;
e. Use of structures in embedded system
i.
Customer ID information

3) Union: Definitions, declaration, with examples. How to use in embedded development

Union are like structures, containing the members whose individual data types may differ
from one another. However, the members that compose a union shall share the same storage area
within the computers memory, whereas each member within a structure is assigned its own
unique storage area. Thus, unions are used to conserve memory.
The general syntax of the union is as given below,
union tag{
member1;
member 2;
--member m
}variable 1, varibale2, . . . ., variable n;
union is a required keyword, tag is the name that appeared in the union definition, member1
member n are the union members and variable 1, variable 2, variable n are union variables of type
tag.
An individual union member can be accessed in the same manner as an individual structure
members, using the operators ->and.
Point to remember:
1. Like a structure, a union is also a derived data type.
2. The members of a union share a single storage space.

3. Only one member of each union can be referenced at a time.


4. Amount of space allocated for storage is the amount needed for the largest
member of the union.
Advantages of union
1. Conservation of memory can be done as space allocated for storage is the amount of space
needed for the largest member of the union.
2. Code optimization is possible with this type
Advantages of union in embedded systems
1. To retrieve the higher 8 bits and the lower 8 bits separately instead of 16 bit long data the
union can be used
union data
{
int data;
struct {
unsigned char higher;
unsigned char lower;
} parts;
};
a. Use of union in embedded system
i. Addressing a register in a controller
4) Enumerators: Definitions, declaration, with examples. How to use in embedded
a.

development
Definition of a Enumerators
An enumeration consists of a set of named integer constants. An enumeration type
declaration gives the name of the (optional) enumeration tag and defines the set of named
integer identifiers (called the "enumeration set," "enumerator constants," "enumerators," or
"members"). A variable with enumeration type stores one of the values of the enumeration
set defined by that type.
Variables of enum type can be used in indexing expressions and as operands of all arithmetic
and relational operators. Enumerations provide an alternative to the #define preprocessor

directive with the advantages that the values can be generated for you and obey normal
scoping rules.
In ANSI C, the expressions that define the value of an enumerator constant always have int
type; thus, the storage associated with an enumeration variable is the storage required for a
single int value. An enumeration constant or a value of enumerated type can be used
anywhere the C language permits an integer expression.
Declaration of a Enumerators
Syntax
enum-specifier:
enum identifier opt { enumerator-list }
enum identifier
Example:
enum DAY
/* Defines an enumeration type */
{
saturday,
/* Names day and declares a
*/
sunday = 0, /* variable named workday with */
monday,
/* that type
*/
tuesday,
wednesday, /* wednesday is associated with 3 */
thursday,
friday
} workday;

b.

Use of Enumerators in embedded system


1.
To maintain consecutive address

You might also like