You are on page 1of 90

PROGRAMING IN C - A STUDY MATERIAL

Compiled By:

Mr. Kabiraj Nahak


Supported By:
Miss Jharana Das
Miss Manaswini Mahapatra
Mr. Sanjeev Kumar Nayak
Mr. Chinmaya Mohini

PROGRAMING IN C - A STUDY MATERIAL

TABLE OF CONTENTS
MODULE I:
Chapter 01: Data Types, Variables & Constants .. 02

Chapter 02: Operators 10


Chapter 03: Standard Input/output Operations. 14
Chapter 04: Control Structures 25

MODULE II:
Chapter 05: Functions. 35
Chapter 06: Storage Classes 41
Chapter 07: Arrays 44
Chapter 08: Pointers 55
Chapter 09: Dynamic Memory Allocation. 62
Chapter 10: Command Line Argument 64

MODULE III:
Chapter 11: Structures, Unions & Enumerations 65
Chapter 12: File Handling. 71
Chapter 13: Preprocessors.. 84

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

MODULE I

CHAPTER 1 (DATA TYPES, VARIABLES AND CONSTANTS)


DATA TYPES:
Every variable has to have a type, which determines computers memory taken up by it and how the
program interprets the bit patterns found in the objects storage allocation.

Basic Data Types:

Data Types Size

Char
int

Float
Double
1. char:

1 byte
2 bytes (16 bit compiler)
4 bytes (32 bit compiler)
4 bytes
8 bytes

Range

-128 to 127
-32678 to 32767
-2147483648 to 2147483647
3.4e - 38 to 3.4e + 38
1.7e - 308 to 1.7e + 308

char is a Integral type stored in computer as coded set of binary digits having positive decimal equivalent
and able to hold 8 bits of data. For signed char 1 sign bit and 7 data bits for unsigned char all 8 data bits.
Modifiers
: signed, unsigned
Size : 1 bytes
Range: signed char : -128 to 127
unsigned char : 0 to 255
Format specifier: %c
If data value exceeds max limit or min limit, it loops back to the min limit and max limit respectivily.
For negative numbers sign bit will be 1 and data bits will be stored in 2s complement. For positive
numbers sign bit will be 0 and data bits will be stored directly.

2. int:

Variables of int data type hold an integer value. For signed int, 1 sign bit and rest data bits. For unsigned
int, all are data bits.
Modifiers:
signed, unsigned, short, long
Size:
short : 2 bytes
int
: 2 bytes (16 bit machine) and 4 bytes (32 bit machine)
Long : 4 bytes
Range: signed short int
: -32768 to 32767
unsigned short int
: 0 to 65355
signed int
: -2n-1 to 2n-1-1 (n is the number of bits)
unsigned int
: 0 to 2X2n-1-1 (n is the number of bits)
signed long int : -2147483648 to 2147483647
unsigned long int
: 0 to 4294967295
Types: decimal integer, octal integer, hexadecimal integer.
Format specifier:
int: %d, %i
unsigned int: %u (unsigned)
long int: %ld, %li
short int: %h, %hi, %hd
octal: %o
hexadecimal: %x
If data value exceeds max limit it loops back from the min limit and similarly for min limit.
For negative numbers sign bit will be 1 and data bits will be stored in 2s complement. For positive
numbers sign bit will be 0 and data bits will be stored directly.
Endianness is the system attribute that indicates whether the integers represented from right or
left.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

Big-endian is an order in which the big end (Most significant value in the sequence) is stored first
(at lowest storage address) and in little-endian little end (least significant value in the sequence)
is stored first (at lowest storage address).

3. float :

Variables of float data type hold a real number value.


Modifiers
: short (float), long (double), Long double
Size: float
: 4 bytes
double
: 8 bytes
long double : 10 bytes
Range:
float
: 3.4e - 38 to 3.4e + 38
double
: 1.7e - 308 to 1.7e + 308
long double : 3.4e - 4932 to 1.1e + 4932
Types: fractional, exponential.
Format specifier: %f (float), %lf(double), %Lf (long double), %g, %e(exponential form)
float stores floating point numbers with 6 digits of precision. double stores floating point numbers
with 14 digits of precision.
float, double and long double data types are stored in memory in the following format:
float
1 sign bit 8 bit exponent 23 bit mantissa
double
1 sign bit 11 bit exponent 52 bit mantissa
long double 1 sign bit 15 bit exponent 64 bit mantissa
In IEEE standard, floating point no. is stored in a binary form known as normalized form.
In the normalized form, the most significant bit of mantissa is always 1 (so this bit is not stored).
The exponent is for representing the power of 2 instead of 10 as computers base is 2.
Exponent is stored in unsigned binary form after adding a positive integer bias whose value is 127
for single precision floating-point number (float) and 1023 for double precision floating point
number.

4. void:

Its and empty data type associated with function and pointer. Its used:
To explicitly declare a function returning no value. E.g. void show ( );
To declare a function having no argument. E.g. void show (void );
To create a generic pointer. e.g.
void main ( ){
void *p;
printf (enter a number);
scanf(%d, (int) &p);
printf(%d, (int) p); }

5. enum:

An enumerated variable defines a sequence set of constant of type integral.


e.g.
enum subject { C, OOPS, JAVA, OS };

Tips and Tricks:


1.
2.
3.
4.
5.

The process of byte ordering is known as endianness.


Data will be stored in memory in ABCD or DCBA format that depends on Endianness of the system.
In little-endian systems data is stored in DBCA order.
In big-endian data is stored in ABCD order.
C language supports 256 characters. Out of them 127 are ASCII (26 + 26 alphabets, 10 digits, 32
special characters, 33 control characters, and 129 are Extended ASCII characters.)
6. Size of integer type depends on compiler or word length of the processor.
7. Unsigned modifier always makes double the range of a type.
8. When a signed negative integer is compared with an unsigned integer, the signed integer is
immediately converted to an unsigned integer temporarily. E.g.
void main ( )

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

int a = -11;
unsigned int b=2579;
if (a>b)
printf (Hello);
else
printf (Hi); }
Output: Hello
Explanation: When the -11(signed) is compared with 2579(unsigned), then the signed -11
converted to the unsigned, i.e. 65536-11=65525(since the max range of unsigned int is 65536)
which is greater than 2579.
9. When the conversion is from integer to float using the format specifiers such as %d and %f, the
same variable and the next variable(s) will suffer i.e. loss of data. e.g.
void main ( )
{
int a=5, b=7;
float c=9.9;
printf ( %d %d %d , c, a, b);
}
Output: garbage or wrong value.
Explanation: memory representation of integer is different from that of float.
10. Cycle is present in integer and character data type but is not present in float or double types. If a
value of a variable exceeds its range of its types, it immediately wraps round to positive or negative.
Finding the output:
If the given value of an integer is more then 65535 then ans = given value % 65536
If the given value of an integer is in between 32767 and 65536 then ans = given value - 65536
e.g.
void main ( )
{
int s = 90000, c = 50000;
printf (%d\t%d,s,c);
}
Output: 24464
-15536
11. The recurring 32 bits real number is less than 64 bits recurring real number. E.g.
void main()
{
float x=4.2;
if (x == 4.2)
printf (hello);
else
printf (hi);
}
Output: hi
Explanation: 4.2 consumes 8 bytes i.e. 64 bits. When its stored in x which is a float variable, it
consumes 4 bytes i.e. 32 bits. Binary number 4.2 (8 bytes ) > binary number x (4 bytes).
12. % (modulus) operator is not applicable to any floating number. Itll show a error (illegal use of
floating point).
13. Character variables always consume 1 byte but character constants always consume 2 bytes.
(Character constants are always stored in memory in their ASCII value which is a integer.)
e.g.:
void main ( )
{
char p = A;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

printf (%d\t%d, sizeof (p), sizeof (A));


}
Output: 1 2
14. When float variables exceed their boundary, error is (+/-) INF (in turbo c 3.0 its overflow error).
15. Float data is always stored in memory in mantissa and exponent format.
16. Float follows 23 bits mantissa, 8 bits exponent, and 1 bit sign, but double follows 52 bits mantissa,
11 bits exponent and 1 bit sign.
17. Enum data type creates a sequence set of integral constants. There is no cycle present in enum data
type.
18. BCPL is a type-less language.
19. When a language is able to produce a new data type it is called extensibility.
20. Typedef creates a new name but does not create a new type.
21. If the character constant may be one or two characters long, but only the 1st character is considered
(turbo c). More than two will show an error.
e.g.
void main ( )
{
char p=AB;
printf (%c,p);
}
Output: A (in turbo c but in ANSI C output is B)
22. No two enumerated constants can be assigned the same value.
e.g.
void main ( )
{
enum day { sun, mon };
enum star { sun, moon };
}
Output: error: multiple declaration for sun.
23. No variable except a pointer can be expressed with the type void. (Error: sizeof variable is
unknown or zero.)
24. void type is used in three different places, such as:
i) No argument to a function ii) No Return type
iii) Generic Pointer
25. Result of an operation is not bounded by any overflow.
void main ( )
{
short int a=20000, b=20000;
if(a+b>0)
printf("hello");
else
printf("Hi");
}
Output: hello
(Result of an operation is not
bounded by any overflow.)

void main ( )
{
short int a=20000, b=20000;
short int c=a+b;
if(c>0)
printf("hello");
else
printf("Hi");
}
Output: Hi
(Value of an integer variable wraps
to the negative value due to overflow.)

VARIABLES AND CONSTANTS:

Variables:

Its a named object that resides in the memory (RAM) and is capable of being examined and modified.
Variable name is a name given to a location in memory of a computer where different constants are
stored.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

Variable Declaration:

A variable must be declared before using it to make the compiler know the name and type of variable so
that itll decide what type of values it can take and what will be the size itll take in memory.

Syntax: <storage class> <data type> <variable name>;

E.g.

(Storage class is optional)

static int a;
char a;

Variable Initialization:

Giving an initial value to a variable is called initialization of a variable. A variable should be initialized to a
value to be used in different operations.

Syntax: <storage class> <data type> <variable name> = <value>;

E.g.

static int a=20;


float b=2.23;

Properties of Variables:

The properties of variables are decided or affected by the following aspects and factors.
Scope of the variables (local and global)
Life span of the variable
Default initial value of a variable
Storage of the variable (in memory or in register)
L value and R value of the variable
Qualifier of the variable

Use of Variables:

Fixed value: value of a variable is fixed after initialization if its value does not change in the run time.
Stepper/Counter: Used in loops.
Most-recent holder: Repeatedly asks the user to input until the given value is valid in as per the pre
defined criteria and the variable holds the last valid input.
Gatherer: The value of a gatherer accumulates all the values gone through so far in a cumulative
effect.
Transformation: In this case the variable always gets its new value from the value(s) of other
variable(s) through the same calculation.
One-way flag: Its a Boolean variable which once changed cant get its original value anymore.
Follower: it always gets the old value of another known variable as its new value.
Temporary: If the value of a variable is needed only for a short period.
Organizer: Its an array which is used for recognizing its elements after organization.

Naming Conventions:

ANSI has formulated a set of rules for naming the variables in an efficient manner.
The variable name must be within 32 characters.
The first character must be an alphabet or an underscore (_) and the rest can be alphabets, digits or
underscores.
No space or special characters are allowed.
No keyword can be a variable name.

Declaration vs. Definition:

Declaration is used to specify the name and type of an object to the compiler. It asserts that the object
exists but does not actually allocate memory space for it. (Reuse of the variable from somewhere out of
scope).
While definition is used to provide a value to a variable so that itll reserve memory space for itself.
E.g.
void main ( )
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

extern int x; // variable declaration


printf (%d, x);

}
int x = 5; // variable definition

L-value and R-value:

C compiler classifies the expressions into 2 categories: L Value:


Its an expression that refers to an object that has a location and can be changed or examined and be
visible only at the left hand side of an assignment operator. E.g. int k=5; but not int 5=k;
R Value
Its an expression that permits examination but not alteration and is visible only in the right hand side
of an assignment operator.
E.g.
int it ( );
it=2; //wrong as it is a function not a variable.
it=x; //wrong as it is a function not a variable.

Qualifiers:

Qualifiers improve the quality, efficiency and accessibility of the data objects or function objects.
Volatile qualifier:
E.g. int volatile x; or volatile int x;
Volatile is used to explicitly tell the compiler that a variables value may be changed at any time by
some external source (from outside the program, may be a kernel code or device drivers).
When the variable is declared as volatile, the compiler will examine the value of the variable each
time its encountered to see whether any external alteration has changed the value or not.
The volatile qualifier tells the compiler that a variable may be referenced in such a way that the
values hidden from the compiler but known to the programmer.
Value of the volatile qualifier gets refreshed every time its accessed and hence should be used to
qualify variables which are very frequently accessed, like loop counters.
In case of hardware mapping the variable must be declared to be volatile.
Const qualifier:
const qualifier tells the compiler, the variable value cannot be changed in the current file, but can be
modified in another file.
E.g. int const x=5; or const int x=5;
A const variable can be initialized only at the time of declaration.
In case of a constant pointer (const *p) the address, the pointer refers to can never be changed as
well the pointer cant be initialized in future. But the value at the address the pointer contains can be
changed.
Const in function parameter provides security to data while passing data as a parameter in a function.

Global Identifiers:

Turbo c uses many global variables for different purposes. All global variables are pre fixed with an
underscore (_) character. E.g. _ _TIME_ _ (no space) will show the current time.

Constants:

A constant is an entity that does not change or alter. In C constants can be created using const, enum, or by
using Macro expansion (#define c=11). There are different types of constants as follows.

Integer Constant:

Its of three types:


Decimal integer constants: int x=15;
Octal integer constant: int x=015;
Hexadecimal constant: int x=0x15;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

If the number is preceded with a 0 or 0x, its an octal or hexa-decimal integer constant respectively. If the
number is succeeded with a L or u, its an long or unsigned integer constants respectively. (5L, 9u)

Valid Character Constant:

Its normally a character out of 256 characters enclosed with in a single quote ( ). Octal character
constants usually preceded by a backslash (\a). Hexa-decimal character constants are preceded by a \x.
e.g. char p=34;

Escape Character Constant:

All escape character constants start with \ and implicitly represented in the form of octal numbers.
If the escape character range is more than 255, itll cause an error Numeric constant too large.
\377 is a valid character constant as its by default an octal number with decimal value 255. But
\378 is a not valid octal number hence not a character constant.
\457 is a valid octal number but range is beyond 255 and hence invalid character constant.
If the 1st character followed by a \, is a valid octal digit (0 to 7), itll be considered as an octal number
or else as any character constant.
Some valid Escape Characters:
Escape Character
ASCII value
Purpose
\a
7
Bell character
\b
8
Back space
\t
9
Horizontal tab
\n
10
New line
\v
11
Vertical tab
\f
12
Form feed
\r
13
Carriage return

Real Constant:

Its the floating point constants. It could be written in two forms: Fractional form and exponential form.
e.g.
float x = 4.5;
//4.5 is double constant.
float x = 4.5f;
//4.5f is float constant.
float x = 4.5e+2;
//4.5e+2 is exponential constant.
float x = 4.5L;
//4.5L is long double constant.

Tips and Tricks:

1. 2 types of variables: value type (int a;) and reference type (int a[5];).
value type variables are created in the stack area while reference type variables are created in the
heap area.
2. Microprocessor generates the address for the variables and the storage class decides where it will
be created and how many bytes itll occupy.
3. When the sizeof ( ) operator is used with an object, parenthesis is not compulsory, but when used
with any data type, its compulsory. E.g. sizeof x; sizeof 5; sizeof (int);
4. Variables cant be initialized in the sizeof ( ) operator.
5. An ordinary pointer may be used to point a pointer to volatile object, but for that an explicit type
cast must be used to assign a pointer to a volatile object to an ordinary pointer.
e.g.
volatile int volatile_int;
int *ordinary_ptr;
volatile int *ptr_to_volatile;
int *volatile volatile_ptr;
ptr_to_volatile = ordinary_ptr;
//valid
ordinary_ptr = ptr_to_volatile;
//invalid
ordinary_ptr = (int *) ptr_to_volatile;
//valid
6. 5 is a character constant while 5 is a string constant. 5L is a long integer constant while 5.0L is a
long double constant.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

7. const and volatile can be used together. E.g. const volatile int x=5; or volatile const int x=5;
8. Function name can be used as a variable name inside that function only.
main is a special type of function, not a keyword.
9. The minimum octal character constant is \000 and maximum octal character constant is \377.
10. All constants in C are R value category of objects.
11. The number of constants and variables in C are equal.
12. Constant variables, array name and function name; enum constants are R value category of objects
and they should always be placed in the right side of an equal-to operators.
13. All escape sequence characters are octal character constants.
14. The size of the null string constant is 1 byte.
15. \0 is null character constant whose ASCII value is 0.
16. Every variable and function allocates memory in load time and run time, but how much memory will
be allocated and where will be allocated that is decided during compile and linking time.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 2 (OPERATORS)

Operators specify the basic operations that are to be performed with the basic data objects (variables and
constants). C consists of 45 operators. Expressions formulated with the help of them and are evaluated to
get desired result.
Operators are classified depending upon the number of operands, where an operand is the data item upon
which the operators act. E.g. X+Y (X and Y: operands, +: an operator)
Classifications:
1. Unary (1 operand)
2. Binary (2 operands)
3. Ternary (3 operands)

Precedence Table:

Precedence Operator
1
( ) [ ] -> .
- ++ _
2
~ ! &
* (Type) sizeof ( )
3
* / %
4
+ 5
<< >>
6
< <= > >=
7
== !=
8
&
9
^
10
|
11
&&
12
||
13
?:
= *= /= %=
14
+= -= &= ^= |=
<<= >>=
15
,

Different Type of Operators:

Associative
Left to Right
Right to Left
Left to Right
Left to Right
Left to Right
Left to Right
Left to Right
Left to Right
Left to Right
Left to Right
Left to Right
Left to Right
Right to Left
Right to Left
Left to Right

1. Arithmetic Operators: (+, -, *, / and % )


+ - unary dummy operator and binary addition operator.
- - unary negation operator and binary subtraction operator.
* - binary product operator.
/ - binary division operator.
%- modulo-division operator (binary).
Types of arithmetic expressions:
a) INTEGER MODE EXPRESSION: if all the operands used are integers (char, unsigned char, int,
short, long, unsigned int), the expression is called an integer mode expression and the
resultant value is always an integer.
E.g. 9/5 = 1
b) REAL MODE EXPRESSION: if all the operands used are real values (float, double, long double),
the expression is called a real mode expression and the resultant value is always a float type.
E.g. 5.0 + 4.0 = 9.0
c) MIXED MODE EXPRESSION: if some operands are integer type and some are of real type in
an expression, its called a mixed mode expression and the resultant value will always be of
float type. E.g. 5.0 + 4 = 9.0
2. Relational Operators: (<, >, ==, >=, <=, !=)

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

10

PROGRAMING IN C - A STUDY MATERIAL

<
- is less than operator
>
- is greater than operator
==
- is equals to operator
>=
- greater than equals to operator
>=
- less than equals to operator
!=
- not equals to operator
Relational expressions:
Relational expressions always result either 0 (false) or 1(true non-zero).

3. Logical Operators: (&&, ||, !)

&&
- logical and operator (if the values of both the objects are non-zero (true), it results 1 else
0.)
||
- logical or operator (if the values of both the objects are zero (false), it results 0 else 1.)
!
- logical not operator (if the value of an object is 0, it results 1 else 0.)
Logical expressions:
Logical expressions also return either 0 or 1.

4. Assignment Operators: (=, +=, -=, *=, /=, %=)

=
- assignment operator (its used to assign the value of an expression to a variable.)
Short-hand arithmetic assignment operator: (op=)
C has a set of short-hand assignment operators of the form
v op= exp;
Where v is a variable, exp is an expression and op is c binary arithmetic operator. op= is known as
shorthand assignment operator.
The assignment statement v op= exp;
is same as
v = v op (exp);
with v evaluated only once.
e.g.
x += y+1; is same as x = x + (y+1);
The short-hand operator += means add y+1 to x or increment x by y+1.
Advantages of using short-hand assignment operator are:
1. The left hand side is not repeated in the right hand side and hence easier to write.
2. The statement is more concise and easier to read.
3. The statement is more efficient.

5. Increment/ Decrement Operators: (++, --)


- increment operator: adds 1 to the object.
++
-- decrement operator: subtracts 1 from the object.

Pre- increment/decrement: (++x, --x)


Here first increment or decrement will be done and then the expression will be evaluated.
E.g.
a=5, b=9;
++a + b = 15, a == 6 and b == 9.
Post- increment/decrement: (x++, x--)
Here first the expression will be evaluated and then increment or decrement will be done.
E.g.
a=5, b=9;
a++ + b = 14, a == 6, b == 9.

6. Conditional Operators: ( ? : )

Its a ternary operator pair used for conditional operation.


Syntax: exp1 ? exp2 : exp3
Here exp1, exp2, exp3 are expressions. exp1 is evaluated first. If its non-zero (true) then exp2 is
evaluated and becomes the value of the whole expression. If exp1 is zero (false), then exp3 is
evaluated and becomes the value of the whole expression.

7. Bitwise Operators: (~, >>, <<, &, |, ^)


VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

11

PROGRAMING IN C - A STUDY MATERIAL

~
>>

- bitwise ones complement operator. E.g. int x= ~5; here x= -6. (~a = -(a+1))
- bitwise Right shift operator. E.g. int x= 5>>1; here x= 2. (binary of 5 is shifted to right by

1bit )
<<
- bitwise Left shift operator. E.g. int x= 5<<1; here x= 10. (binary of 5 is shifted to left by 1bit
)
&
- bitwise AND operator. E.g. int x= 5&9; here x= 1.
|
- bitwise OR operator. E.g. int x= 5|9; here x= 13.
^
- bitwise XOR operator. E.g. int x=5^9; here x=12.
C supports bitwise operators (except ~) combined with assignment operator to create short hand
bitwise assignment operators. E.g. >>=

8. Special Operators:
a. Data Access Operator:
()
[]
.
->
&
*

- grouping statement operator and function call operator.


- subscript operator
- member access operator. (structure member operator)
- pointer to member access operator. (structure pointer operator)
- address of operator.
- value at address operator. (pointer operator)
b. sizeof ( )
- gives a result equal to the size of the object, or expression or data type in bytes.
c. (type) - forces the compiler to convert the value from one cast to another cast with out changing
the originality.
d. , (comma operator) its used to link the related expressions together. It enjoys the low priority
and associativity is from left to right. So the value of the last variable will be the result of the
expression. Its used in for and while loops also.

Tips and Tricks:

1. Precedence decides the priority of the operators while associativity determines the order of
evaluation.
2. Precedence and associativity of an operator is only implemented if expression is represented in INFIX
notation.
3. The operator which requires three operands is called ternary operator. ?: is a conditional ternary
operator.
4. sizeof ( ) is a operator which is also a keyword but looks like a function. It does not evaluate any
expression passed as an argument. Its applicable only to the variables, constants, data types but not
to the functions.
5. Modulus (%) works only with the integral operands and cant be applied to float or double (Error:
Illegal use of floating point).
6. C does not allow ** like ++ as ** is not an operator.
7. Increment/ decrement operators can only be applied to the variables. Cant be applied to the
constants (5++; Error: Lvalue required.)
8. Return keyword cant be used with conditional operator.
e.g. p > 65540 ? return 1: return 0;
//Error: expression syntax.
9. Bitwise operators work with only integer and characters.
e.g. float x=2.0&5; //Error: Illegal use of floating point.
10. Continuous triple plus (+++) are allowed but not more. e.g. a+++5; //a++ + 5
If more than three plus are used, then they must be separated by spaces.
E.g.
a++ + ++b;
//valid
a+++++b;
//Error: L value required.
11. If the left hand operand yields false value, the right operand is not evaluated in a logical expression
using &&. E.g.
int x, y = 2, a = 5;
x = y-2 && a++;

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

12

PROGRAMING IN C - A STUDY MATERIAL

printf (%d, a);


Output: 5
12. If the left hand operand yields true value, the right operand is not evaluated in a logical expression
using ||. E.g.
int x, a = 5;
x = 5+3 || a++;
printf (%d, a);
Output: 5
13. If two operands in an assignment expression are of different data types then the value of the right
hand operand will automatically be converted to the type of the operand on left. The entire
expression will then be of same data type.
14. Floating-point values are truncated when assigned to integer variables.
15. Double precision values are rounded when assigned to floating point single precision identifiers.
16. Associativity of a comma ( , ) operator is left to right.
17. # is a string forming operator that converts a non-string data to string and is used only in preprocessor
directives.
18. There is no operator in C to calculate the power of a number.
19. Return value of relational and logical operators is 0 or 1.
20. x++ and ++x both are always same if they are used independently. They behave differently when they
form part of an expression.
21. If ++ or - - operators occurs more than once, then first two makes a pair and are evaluated, then the
result is added in next, then next

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

13

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 3 (STANDARD INPUT/OUTPUT OPERATIONS)


Accepting the required inputs from input devices and displaying the produced result on output devices are
referred to as input/output operations.
There are three types of I/O depending on the source devices for input and target devices for output. They
are:
a. Console I/O
b. Disk I/O
c. Port I/O
The standard library of I/O functions for a platform will be provided by the designer of the compiler for
that platform.
Since the prototypes of the functions are available in the header files (ex: stdio.h, conio.h, etc.), we need to
include them as part of our source program file with the help of the preprocessor directive #include as:
#include <stdio.h>
The instruction # include<stdio.h> tells the compiler to search for a file named stdio.h and place its
contents at this point in the program. The content of the header file become part of the source code when
it is compiled.
In this chapter we deal with console I/O only. Console I/O uses keyboard as the standard input device and
screen as the standard output device.
There are two types of console I/O operations such as:
1. Unformatted Input/output Operation.
2. Formatted Input/output Operation.

Unformatted Input/Output Operations


Unformatted Input Operation:
getc()

Header file
: stdio.h
Prototype
: int getc(FILE *stream);
Description
: Gets character from stream. getc returns the next character on the given input stream and
increments the stream's file pointer to point to the next character.
Note: For Win32s or Win32 GUI applications, stdin must be redirected.
Return Value : On success, getc returns the character read, after converting it to an int without sign extension. On
end-of-file or error, it returns EOF.
Example:
#include <stdio.h>
int main(void)
{
char ch;
printf("Input a character:");
ch = getc(stdin); //reads a character from the standard input stream
printf("The character input was: '%c'\n", ch);
return 0;
}

getch()
Header file
: conio.h
Prototype
: int getch(void);
Description
: Gets character from keyboard, does not echo to screen. getch reads a single character directly from
the keyboard, without echoing to the screen.
Note: Do not use this function for Win32s or Win32 GUI applications.
Return Value : getch returns the character read from the keyboard.
Example:
#include <conio.h>
#include <stdio.h>
int main(void)
{
int c;
int extended = 0;
c = getch();

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

14

PROGRAMING IN C - A STUDY MATERIAL


if (!c)
extended = getch();
if (extended)
printf("The character is extended\n");
else
printf("The character isn't extended\n");
return 0;
}

getchar()
Header file
: stdio.h
Prototype
: int getchar(void);
Description
: Gets character from stdin. getchar is a macro that returns the next character on the named input
stream stdin. It is defined to be getc(stdin).
Note: Do not use this function for Win32s or Win32 GUI applications.
Return Value : On success, getchar returns the character read, after converting it to an int without sign extension.
On end-of-file or error, it returns EOF.
Example:
#include <stdio.h>
int main(void)
{
int c;
/* Note that getchar reads from stdin and is line buffered; this means it will not
return until you press ENTER.*/
while ((c = getchar()) != '\n')
printf("%c", c);
return 0; }

getche()
Header file
: conio.h
Prototype
: int getche(void);
Description
: Gets character from the keyboard, echoes to screen. getche reads a single character from the
keyboard and echoes it to the current text window using direct video or BIOS.
Note: Do not use this function for Win32s or Win32 GUI applications.
Return Value : getche returns the character read from the keyboard.
Example:
#include <stdio.h>
#include <conio.h>
int main(void)
{
char ch;
printf("Input a character:");
ch = getche();
printf("\nYou input a '%c'\n", ch);
return 0;
}

gets()
Header file
: stdio.h
Prototype
: char *gets(char *s);
Description
: Gets a string from stdin. gets collects a string of characters terminated by a new line from the
standard input stream stdin and puts it into s. The new line is replaced by a null character (\0) in s. gets allows input
strings to contain certain whitespace characters (spaces, tabs). gets returns when it encounters a new line; everything
up to the new line is copied into s.
Note: For Win32s or Win32 GUI applications, stdin must be redirected.
Return Value : On success, gets returns the string argument s. On end-of-file or error, it returns NULL
Example:
#include <stdio.h>
int main(void)

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

15

PROGRAMING IN C - A STUDY MATERIAL


{
char string[80];
printf("Input a string:");
gets(string);
printf("The string input was: %s\n", string);
return 0;
}

Unformatted output Operation:


putc()
Header file
Prototype
Description
stream.
Return Value

: stdio.h
: int putc(int c, FILE *stream);
: Outputs a character to a stream. putc is a macro that outputs the character c to the stream given by
: On success, putc returns the character printed, c. On error, putc returns EOF.

putch()
Hederfile
: conio.h
Prototype
: int putch(int c);
Description
: Outputs character to screen. putch outputs the character c to the current text window. It is a text
mode function performing direct video output to the console. putch does not translate linefeed characters (\n) into
carriage-return/linefeed pairs. The string is written either directly to screen memory or by way of a BIOS call,
depending on the value of the global variable _directvideo.
Note: This function should not be used in Win32s or Win32 GUI applications.
Return Value : On success, putch returns the character printed, c. On error, it returns EOF.
Example:
#include <stdio.h>
#include <conio.h>
int main(void)
{
char ch = 0;
printf("Input a string:");
while ((ch != '\r'))
{
ch = getch();
putch(ch);
}
return 0;
}

putchar()
Header file
: stdio.h
Prototype
: int putchar(int c);
Description
: putchar(c) is a macro defined to be putc(c, stdout).
Note: For Win32s or Win32 GUI applications, stdout must be redirected.
Return Value : On success, putchar returns the character c. On error, putchar returns EOF.
Example:
#include <stdio.h>
/* define some box-drawing characters */
#define LEFT_TOP 0xDA
#define RIGHT_TOP 0xBF
#define HORIZ
0xC4
#define VERT
0xB3
#define LEFT_BOT 0xC0
#define RIGHT_BOT 0xD9
int main(void)
{
char i, j;
/* draw the top of the box */

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

16

PROGRAMING IN C - A STUDY MATERIAL


putchar(LEFT_TOP);
for (i=0; i<10; i++)
putchar(HORIZ);
putchar(RIGHT_TOP);
putchar('\n');
/* draw the middle */
for (i=0; i<4; i++)
{
putchar(VERT);
for (j=0; j<10; j++)
putchar(' ');
putchar(VERT);
putchar('\n');
}
/* draw the bottom */
putchar(LEFT_BOT);
for (i=0; i<10; i++)
putchar(HORIZ);
putchar(RIGHT_BOT);
putchar('\n');
return 0;
}

puts()
Header file
: stdio.h
Prototype
: int puts(const char *s);
Description
: Outputs a string to stdout. puts copies the null-terminated string s to the standard output stream
stdout and appends a newline character.
Note: For Win32s or Win32 GUI applications, stdout must be redirected.
Return Value : On successful completion, puts returns a nonnegative value. Otherwise, it returns a value of EOF.
Example:
#include <stdio.h>
int main(void)
{
char string[] = "This is an example output string\n";
puts(string);
return 0;
}

Formatted Input/output Operation:

Formatted Input Operation:


Formatted input refers to an input data that has been arranged in a particular format. This is possible in C
using the scanf function. The scanf( ) is used to accept mixed or same types of data through the keyboard.
Syntax :
scanf ( control string , arg1, arg2,.,argn ) ;
Where control string specifies the field format in which the data is to be entered and the argument
arg1, arg2 ,.,argn specify the address of locations where the data is stored. Ampersand ( & ) symbol
procedes each variable ( except string variable ) to obtain the address of the variable.
Example:
scanf (%d , &n ) ;
scanf ( %c , &c ) ;
scanf ( %d %c %f , &a , &b , &c );
NOTE: The order of the format specifiers matched with that of the variables (arguments). This is must
when we are reading into more than one variable. The values entered must be delimited by spaces, tabs or
new line character.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

17

PROGRAMING IN C - A STUDY MATERIAL

FORMAT SPECIFIERS FOR DIFFERENT DATA TYPES AVAILABLE IN C ARE:


Format Specifier
Meaning
%c
a character
%d
a decimal integer
%f
a floating point value
%e
a floating value
%h
a short integer
%ld
a long integer
%s
a string
%u
an unsigned integer
%o
an octal number
%x
an hexadecimal number
%[..]
a string of words

scanf()
Header file
: stdio.h
Prototype
: int scanf(const char *format[, address, ...]);
Description
: Scans and formats input from the stdin stream.
Note
: For Win32s or Win32 GUI applications, stdin must be redirected.
The scanf function:
scans a series of input fields one character at a time
formats each field according to a corresponding format specifier passed in the format string *format.
vsscanf scans and formats input from a string, using an argument list.
There must be one format specifier and address for each input field. scanf might stop scanning a particular field before
it reaches the normal end-of-field (whitespace) character, or it might terminate entirely.
Warning
: scanf often leads to unexpected results if you diverge from an expected pattern. You must provide
information that tells scanf how to synchronize at the end of a line. The combination of gets or fgets followed by sscanf
is safe and easy, and therefore recommended over scanf.
Return Value : On success, scanf returns the number of input fields successfully scanned, converted, and stored.
The return value does not include scanned fields that were not stored. On error: if no fields were stored, scanf returns
0. if scanf attempts to read at end-of-file or at end-of-string, it returns EOF.

cscanf()
Header file
: conio.h
Prototype
: int cscanf(char *format[, address, ...]);
Description
: Scans and formats input from the console. cscanf scans a series of input fields one character at a
time, reading directly from the console. Then each field is formatted according to a format specifier passed to cscanf in
the format string pointed to by format. Finally, cscanf stores the formatted input at an address passed to it as an
argument following format, and echoes the input directly to the screen. There must be the same number of format
specifiers and addresses as there are input fields.
Note
: cscanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace)
character, or it might terminate entirely for a number of reasons. See scanf for a discussion of possible causes.
Note
: Do not use this function for Win32s or Win32 GUI applications.
Return Value : cscanf returns the number of input fields successfully scanned, converted, and stored; the return
value does not include scanned fields that were not stored. If no fields were stored, the return value is 0. If cscanf
attempts to read at end-of-file, the return value is EOF.
Example:
#include <conio.h>
int main(void)
{
char string[80];
/* clear the screen */
clrscr();
/* Prompt the user for input */
cprintf("Enter a string with no spaces:");
/* read the input */
cscanf("%s", string);
/* display what was read */

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

18

PROGRAMING IN C - A STUDY MATERIAL


cprintf("\r\nThe string entered is: %s", string);
return 0;
}

sscanf()
Header file
: stdio.h
Prototype
: int sscanf(const char *buffer, const char *format[, address, ...]);
Description
: Scans and formats input from a string.
Note
: sscanf scans a series of input fields, one character at a time, reading from a string. Then each field
is formatted according to a format specifier passed to sscanf in the format string pointed to by format. Finally, sscanf
stores the formatted input at an address passed to it as an argument following format. There must be the same
number of format specifiers and addresses as there are input fields. sscanf might stop scanning a particular field
before it reaches the normal end-of-field (whitespace) character, or it might terminate entirely, for a number of
reasons.
Return Value : On success, sscanf returns the number of input fields successfully scanned, converted, and stored;
the return value does not include scanned fields that were not stored. If sscanf attempts to read at end-of-string, it
returns EOF. On error (If no fields were stored), it returns 0.
Example:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
char *names[4] = {"Peter", "Mike", "Shea", "Jerry"};
#define NUMITEMS 4
int main(void)
{
int
loop;
char temp[4][80];
char name[20];
int
age;
long salary;
clrscr();
// clear the screen
/* create name, age and salary data */
for (loop=0; loop < NUMITEMS; ++loop)
sprintf(temp[loop], "%s %d %ld", names[loop], random(10) + 20, random(5000) +
27500L);
/* print title bar */
printf("%4s | %-20s | %5s | %15s\n", "#", "Name", "Age", "Salary");
printf("
--------------------------------------------------\n");
/* input a name, age and salary data */
for (loop=0; loop < NUMITEMS; ++loop)
{
sscanf(temp[loop],"%s %d %ld", &name, &age, &salary);
printf("%4d | %-20s | %5d | %15ld\n", loop + 1, name, age, salary);
}
return 0;
}

Formatted output Operation:


The printf ( ) is used to display data on the screen. The syntax of its usage is
Syntax:
printf ( control string , arg1 , arg2,..,argn ) ;
Here arg1,arg2,,argn are the variables, the values of which are to be displayed on the screen.
Control string consists of the following three items:
a. Format specifiers similar to those discussed in the case of scanf( ).
b. Some sequence of characters, which will be displayed on the screen as they are.
c. Character like \n,\t and \b etc. These characters are called escape sequence characters.
Example: To display the value of the variable n of int type.
printf ( %d , n ) ;
// %d is the format specifier for the int variable n.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

19

PROGRAMING IN C - A STUDY MATERIAL

printf ( %c , ch ) ;
// ch is a variable of character .
printf ( %f , f ) ; // f is a variable of float
printf ( %d %f %c , i , f , c ) ;
NOTE:
1. The order of the format specifiers matches with that of the variables (arguments ).This is a
must when we are displaying values of more then one variable.
2. Many times, the printf ( ) is used to display just some messages.
Format specifiers for other data types available in C are:
Format Specifiers
Meaning
%c
Character
%d
Decimal integer
%ld
Long integer
%f
Floating point value in decimal point notation
%e
Floating point value in exponential form
%h
Short integer
%lf
Long float
%s
String
%u
Unsigned integer
%p
Pointer
%o
Octal number without the prefix 0
%x
Hexadecimal number without the prefix 0x
Escape Sequence Characters
Escape
Meaning
sequence
\n
New line
\t
Horizontal tab
\v
Vertical tab
\f
\b

Form feed
Back space

\a
\\
\?
\
\

Escape
sequence

Meaning
Alert character
Backslash
Question mark
Single quote
Double quote

printf()
Header file
: stdio.h
Prototype
: int printf(const char *format[, argument, ...]);
Description
: Writes formatted output to stdout.
printf function:
Accepts a series of arguments.
Appllies to each argument a format specifier contained in the format string *format.
Outputs the formatted data (to the screen, a stream, stdout, or a string).
There must be enough arguments for the format. If there are not, the results will be unpredictable and likely
disastrous. Excess arguments (more than required by the format) are merely ignored.
Note
: For Win32s or Win32 GUI applications, stdout must be redirected.
Return Value : On success, printf returns the number of bytes output. On error, printf returns EOF.

cprintf()
Header file
: conio.h
Prototype
: int cprintf(const char *format[, argument, ...]);
Description
: Writes formatted output to the screen. cprintf accepts a series of arguments, applies to each a
format specifier contained in the format string pointed to by format, and outputs the formatted data directly to the
current text window on the screen. There must be the same number of format specifiers as arguments. The string is
written either directly to screen memory or by way of a BIOS call, depending on the value of the global variable

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

20

PROGRAMING IN C - A STUDY MATERIAL


_directvideo. Unlike fprintf and printf, cprintf does not translate linefeed characters (\n) into carriage-return/linefeed
character pairs (\r\n). Tab characters (specified by \t) are not expanded into spaces.
Note
: Do not use this function for Win32s or Win32 GUI applications.
Return Value : cprintf returns the number of characters output.
Example:
#include <conio.h>
int main(void)
{
/* clear the screen */
clrscr();
/* create a text window */
window(10, 10, 80, 25);
/* output some text in the window */
cprintf("Hello world\r\n");
/* wait for a key */
getch();
return 0;
}

sprintf()
Header file
: stdio.h
Prototype
: int sprintf(char *buffer, const char *format[, argument, ...]);
Description
: Writes formatted output to a string.
Note
: sprintf accepts a series of arguments, applies to each a format specifier contained in the format
string pointed to by format, and outputs the formatted data to a string. sprintf applies the first format specifier to the
first argument, the second to the second, and so on. There must be the same number of format specifiers as
arguments.
Return Value : On success, sprintf returns the number of bytes output. The return value does not include the
terminating null byte in the count. On error, sprintf returns EOF.
Example:
#include <stdio.h>
#include <math.h>
int main(void)
{
char buffer[80];
sprintf(buffer, "An approximation of Pi is %f\n", M_PI);
puts(buffer);
return 0;
}

Formatting of Outputs

Formatting of outputs refers to displaying the outputs in more readable and comprehensible manner. The
main objective of formatting is to increase the degree of readability of outputs.
Formatting of Integers
Formatting of float point values

Formatting of Integers

Suppose i is a variable of type int and its value is 3456. The value of i can be formatted by modifying the
above control string. The modified control string would be %wd, where w is an interger specifying the
width which the value of i has to be displayed.
Different cases of representation of formatted output:
1. printf ( %6d , i ) ;
3
4
5
6
Since, the width specified is six, six columns are allocated and the value of i is right justified in the specified
width.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

21

PROGRAMING IN C - A STUDY MATERIAL

2. printf ( %3d , i ) ;
3
4

since , the width specified is less than the actual number of digit of the value in i ,the width is ignored and
full value is displayed.

Formatting of float point values:

Suppose f is a variable of type float and its value is 3456.56. To display the value of f, we use the following
printf( ) statements:
printf(%f, f );
As a result, the value of f will be displayed on the screen starting from the first column of the screen as
follows:
3456.560000
The value of f can be formatted by modifying the above control string. The modified control string would
be %w.pf, where w is an integer specifying the width within which the value of f has to be displayed and p
denotes the number of digits to be displayed after the decimal point.
1. printf( %7.2f, f );
3

Since the width specified is seven, seven columns are allocated and the value of f is displayed as shown
earlier. Note that the decimal point also occupies one location and only two digits are displayed after
the decimal point.
2. printf( %3.2f, f );
3

Since the width specified is less than the actual number of digits of the value in f width is ignored
and the full value is displayed.
3. printf( %9.2f, f );
3
4
5
6
.
5
6
Since the width specified is nine which is greater than the number of digits in the given number, nine
columns are allocated and the value of f is right justified in the specified width.
4. printf( % - 9.2f, f );
3
4
5
6
.
5
6
Since the width specified is nine which is greater than the number of digits in the given number, nine
columns are allocated and the value of f is left justified in the specified width because of the presence
of symbol before the width specifier.
5. printf( % 09.2f, f );
0
0
3
4
5
6
.
5
6
Since the symbol 0 is used before the width specifier, the leading blanks are filled with zeros. The
number is said to have been padded with zeros.
6. printf( % 7.1f, f );
3
4
5
6
.
6
Since the number of digits to be displayed, which is one, is less than the actual number of digits (two)
after the point in the given number, the value is rounded off to the first digit.
7. printf( % e, f );
3
.
4
5
6
5
6
0
e
+
0
3
Display the floating point number in exponentiation form with six digits after the point in the mantissa.
8. printf( %10.2 e, f );
3
.
4
6
e
+
0
3
Display the floating point number in exponentiation form with three after the point in the mantissa
within the specified width. The display is right justified.
9. printf( % - 10.2 e, f );
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

22

PROGRAMING IN C - A STUDY MATERIAL

3
.
4
6
e
+
0
3
Display the floating point number in exponentiation form with three after the point in the mantissa
within the specified width. The display is left justified because of the presence of minus symbol before
the width.

Formatting Of Characters:

Suppose c is a variable of type char. To display the character stored in the variable C, we use the following printf ( )
statement:
printf ( %c , c ) ;
As a result of the execution of the statement, the character stored in will be displayed on the screen in the current
position of the cursor. Similar to formatting of integer s, characters also can be formatted. The modified control
string to display a character is
%wc, where w is the width specifier.
The character will be displayed right-justified in the field of w columns. We can make the display left-justified by
placing a minus sign before the integer w. The default value for w is 1.
Example:
1. printf ( %4c , c ) ;
Since, the width specified is four, four columns are allocated and the character stored in c is displayed right justified
in the width as follows:
a
2. printf ( % -4c , c ) ;
Since the width is four, four columns are allocated and the character stored in c is displayed left justified in the
specified width because of the presence of symbol before the width specifier as follows:
a

Formatting of Strings:

The format specification for outputting strings is similar to that of real numbers. It is of the form
%w.ps
Where w specifies the field width for display and p instruct that only the first p characters of the string are to be
displayed. The displayed is right-justified.
The following example shows the effect of variety of specifications in printing a string NEW DELHI 110001,
containing 16 characters (including blanks).
Specification
%s

Output
1

%20s

10

%20.10s
%.5s

%-20.10s

%5s

11

12

13

14

15

16

17

18

19

20

Tips & Tricks:

1. scanf returns the number of input fields successfully scanned, converted, and stored. The return value does not
include scanned fields that were not stored. On error: if no fields were stored, scanf returns 0. if scanf attempts
to read at end-of-file or at end-of-string, it returns EOF.
On success, printf returns the number of bytes output. On error, printf returns EOF.

2.
3. The conversion specifier p displays an address in an implementation-defined manner (on many systems,
hexadecimal notation is used rather than decimal notation).

4. To print a literal percent character (%), use %% in the format control string in the printf.
5. If the field width is larger than the object being printed, the object is right justified in the field by default.
6. The - flag left justifies its argument in a field.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

23

PROGRAMING IN C - A STUDY MATERIAL


7. The + flag prints a plus sign for positive values and a minus sign for negative values. The space flag prints a
space preceding a positive value not displayed with the + flag.
8. The # flag prefixes 0 to octal values and 0x or 0X to hexadecimal values, and forces the decimal point to be
printed for floating-point values printed with e, E, f, g or G (normally the decimal point is displayed only if the
value contains a fractional part).
9. The 0 flag prints leading zeros for a value that does not occupy its entire field width.
10. Precision used with conversion specifiers indicates the number of characters to be printed.
11. scanf provides the assignment suppression character *. The assignment suppression character enables scanf to
read any type of data from the input and discard it without assigning it to a variable.
Ex:
main()
{
int day1,month1,year1,da2,month2,year2;
printf(Enter a date in the form mm-dd-yyyy:);
scanf(%d%*c%d%*c%d,&month1,&day1,&year1);
printf(month=%d\tday=%d\tyear=%d\n,month1,day1,year1);
printf(Enter a date in the form mm/dd/yyyy:);
scanf(%d%*c%d%*c%d,&month2,&day2,&year2);
printf(month=%d\tday=%d\tyear=%d\n,month2,day2,year2);

Output:
Enter a date in the form mm-dd-yyyy: 10-18-2011
month=10
day=18
year=2011
Enter a date in the form mm/dd/yyyy: 10/18/2011
month=10
day=18
year=2011
12. A sequence of characters can be input using a scan set. A scan set is a set of characters enclosed
in square brackets, [ ], and preceded by a percent sign in the format control string.
13. A scan set in a scanf scans the characters in the input, looking only for those characters that
match characters contained in the scan set. When a character is matched, it is stored in a
character array. The scan set stops inputting characters when a character not contained in the
scan set is encountered.
14. To create an inverted scan set, place a caret (^) in the square brackets before the scan characters.
This causes characters input with scanf and not appearing in the scan set to be stored until a
character contained in the inverted scan set is encountered.
15. Address values are input with scanf with the conversion specifier p.
16. Conversion specifier n stores the number of characters input previously in the current scanf. The
corresponding argument is a pointer to int.
17. The conversion specifier %% with scanf matches a single % character in the input.
18. A field width is used in scanf to read a specific number of characters from the input stream.
19. Precision used with integer conversion specifiers indicates the minimum number of digits printed. If the value
contains fewer digits than the precision specified, zeros are prefixed to the printed value until the number of
digits is equivalent to the precision.
20. Precision used with floating-point conversion specifiers e, E and f indicates the number of digits that appear
after the decimal point. Precision used with floating-point conversion specifiers g and G indicates the number
of significant digits to appear.
21. Precision used with conversion specifier s indicates the number of characters to be printed.
22. The field width and the precision can be combined by placing the field width, followed by a decimal point,
followed by the precision between the percent sign and the conversion specifier.
23. Its possible to specify the field width and the precision through integer expression in the argument list
following the format control string. To use this feature, insert and asterisk (*) in place of the field width of
precision. The matching argument in the argument list is evaluated and used in place of asterisk. The value of
argument can be negative for the field width but must be positive for the precision.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

24

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER-4 (CONTROL STRUCTURES)

Decision Making Statements:


ifelse construct:
Simple if statement:
The if statement is used to conditionally execute a block of code based on whether a test condition is
true. If the condition is true then the block is executed, otherwise its skipped.
Use of if statement:
1. Checking range (e.g. age between 15 and 25)
2. Checking yes/no or true/false problem (e.g. choice is no)
Syntax:
if (<expressions>)
{
Statements;
}
E.g.:
if(salary >= 5000)
{
bonus= (10*salary/100);
}

if else statement:

The ifelse statement provides a way to execute one block of code if a condition is true and another block
of code if its false.
Syntax:
if (<expressions>)
{
Statements 1;
}
else
{
Statements 2;
}
E.g.:
if(salary < 5000)
{
bonus=0;
}
else
{
bonus= (10*salary/100);
}

Conditional operator as replacement of if else:

The conditional operator ? : sometimes replaces the ifelse statement


E.g.:
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

25

PROGRAMING IN C - A STUDY MATERIAL

The above example can be replaced by:


salary < 5000 ? bonus=0 : bonus = (10*salary/1000);

Hanging statement in ifelse:

The scope delimiter ({ }) of an if statement can be removed if the number of statements in the if part is
one. If more than one statements written in the if part without scope delimiter, the very first statement
will be part of the if statement, but others will not belong to the if statement and are called as hanging
statement which is not allowed in c and causes
Error: misplaced else.
E.g.:
1. if(a>b)
a=0;
else
a=100;
program is valid.
2. if(a>b)
a=0;
b=1;
else
a=100;
Error: misplaced else.

Nested if statement:

When one conditional statement will be executed under another conditional statement, in other words
one if construct within another if construct, then we need a nested if statement.
Syntax:
if (<expressions>)
{
if (<expressions>)
{
if (<expressions>)
{
Statements;
}
}
}
E.g.:
if(a==1)
{
if(b==2)
{
printf(hello);
}
}

else-if ladder statement:

When therell be more than two statements and only one has to be executed in accordance with a
condition, else-if ladder is used.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

26

PROGRAMING IN C - A STUDY MATERIAL

Syntax:
if (<expression 1>)
{
Statement 1;
}
else if (expression 2)
{
Statement 2;
}
else if (expression 2)
{
Statement 2;
}
:
:
else if (expression n)
{
Statement n;
}
else
{
Statements;
}
E.g.:
If (a==1)
printf(hello);
else if (a==2)
printf(hi);
else if (a==3)
printf(how r u);
else
printf(welcome);

Tips and Tricks:


1. If the expression is evaluated as true, its replaced by 1 and the code block will be executed.
Otherwise its replaced by 0 and the code block will be skipped.
2. For multiple statements are given in the if expression, the order of the evaluation is from left to right.
The statements are separated by commas and hence the last evaluated expression will be treated as
the if condition expression.
3. Nested if can be replaced with logical && operator. e.g.
if (a==1)
If (b==2)
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

27

PROGRAMING IN C - A STUDY MATERIAL

If (c==3)
printf (great);
this can also be written as
if (a==1 && b==2 && c==3)
printf (great);
4. Hanging if is not allowed in C.

switch case construct:


When weve one value or expression that has to be exactly matched with a list of pre-defined values or
options, the switchcase is used. Four keywords are used in switch control statement.
switch - Its the control statement that allows us to make a decision from the no. of choices.
case

- This is the option to be selected or matched with the switch expression value.

default- The default case is executed when none of the cases match with the value in switch.
break - Its optional in switch case statement, but prevents unnecessary flowing of control to the
statements subsequent to the case where a match has been found.
Syntax:
switch ( expression )
{
case <constant expression>:
program statement;
program statement;
......
Break;
case <constant expression>:
program statement;
program statement;
......
Break;
......
Default:
program statement;
program statement;
}

Tips and Tricks:


1. The argument to a switch statement must be a byte, char, short or int.
2. If the case matches with an expression, which is evaluated in the switch statement, then execution
starts from that case.
3. default case does not need a break. It also has no label. If any label is given to it, itll show an
Error: a) Illegal use of default.
b) expression syntax.
4. Cases can occur in any order. E.g.
switch (k)
{
default:
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

28

PROGRAMING IN C - A STUDY MATERIAL

printf(default);
case 25:
printf(case 25);
case 10:
printf(case 10);

}
5. The continue keyword cant be used in place of break in switch statement. Itll generate an error.
6. Case labels can never be identical. A duplicate case is not allowed.
7. default case is optional. If eliminated, therell be no error.
8. The case expression can be integral constant or character constant etc. but can never be a variable.
9. If 0 is given as an argument, switch evaluates it as an expression instead of false.
10. switch statement does not need braces if it has only one case to execute.
11. There must be a space between the case keyword and the option value. If the space is omitted, itll
not show any error but will be considered as a goto label.
12. Switch statements can be nested.
13. No braces are required for the case block. But if given, itll not show any error.
14. If theres no case then therell be no error at all. E.g.
switch (4)
{
}

Looping Construct:
Iteration (repeating a process) is achieved by loop control instructions in C. Looping means repeating an
instruction set till a condition satisfies. There are 3 types of loop in C: for, while, do while.
Every loop contains 3S:

Start value (initialization)

Stop value (condition)

Step value (increment/ decrement)

for loop:
Its used to loop a portion of program for finite number of times. All parts of it are optional and hence
cause an infinite loop.
Syntax:
for (Expression opt ; Expression opt; Expression opt)
{
<statement>;
}

Use of for loops:


Infinite number of times. E.g. for ( ;;);
Finite number of times. E.g. for (i=1;i<5;i++);
Unknown number of times. E.g.
for (ch = y;ch == y || ch == Y)
{
printf (enter your option (y/n) :);
ch = getch();
}
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

29

PROGRAMING IN C - A STUDY MATERIAL

At least once. E.g.


int i = 100;
for ( ; ; )
{
printf (hello);
if (i>=5)
break;
i++;
}

Unpredictable number of times/ odd loop. E.g.


int i;
for ( ; i<=100; i++)
printf (hello:);
//unpredictable times as i is not initialized/ unknown

while loop:
Its used to loop a portion of program for unknown number of times as long as the user wants.
Syntax:
while (Expression)
{
<statement>;
}

Use of while loops:


Infinite number of times. E.g. while ( 1 );
Finite number of times. E.g.
int i=1;
while ( i<=10)
{
printf (hello\n);
i++;
}
Unknown number of times. E.g.
char ch = y;
while (ch == y || ch == Y)
{
printf (enter your option (y/n) :);
ch = getch();
}
At least once. E.g.
int i = 100;
while ( 1 )
{
printf (hello);
if (i>=5)
break;
i++;
}
Unpredictable number of times/ odd loop. E.g.
int i;
while (i<=100)
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

30

PROGRAMING IN C - A STUDY MATERIAL

printf (hello:);
i++;

//unpredictable times as i is not initialized/ unknown

do - while loop:
Its used to loop a portion of program at least once as the condition checking is being done at the end of
the loop.
Syntax:
do
{
<statement>;
} while (Expression);

Use of dowhile loops:


Infinite number of times. E.g.
do
printf (hello);
while ( 1 );
Finite number of times. E.g.
int i=1;
do
{
printf (hello\n);
i++;
}while ( i<=10);
Unknown number of times. E.g.
char ch = y;
do
{
printf (enter your option (y/n) :);
ch = getch();
} while (ch == y || ch == Y);
At least once. E.g.
int i = 100;
do
{
printf (hello);
i++;
} while ( i <= 10);
Unpredictable number of times/ odd loop. E.g.
int i;
do
{
printf (hello:);
//unpredictable times as i is not initialized/ unknown
i++;
} while (i<=10);

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

31

PROGRAMING IN C - A STUDY MATERIAL

Jumping Statements:

To transfer the control from one portion of a program to another portion, jumping statements are allowed.
Three types of jumping keywords are used: break, continue and goto.

break:
Its used in loops and switch case to transfer the control to outside the block. In loops its usually
associated with if statement. E.g.
int i = 100;
while ( 1 )
{
printf (hello);
if (i>=5)
break;
i++;
}

continue:
Its used in loops to transfer the control to the beginning of the loop by skipping the subsequent sequences
in the loop allowing the control to jump to the next iteration skipping the present. E.g.
int i;
for (i=1; i<=10; i++)
{
if (i>=5)
{
printf (hi);
continue;
}
printf (hello);
i++;
}

goto:
Its an unconditional branching statement. It causes the control to be transferred from one part to another
part of the function.
Syntax:
goto label;
//where label is a valid c identifier and marks a place where
//the control has to be transferred in a function.
The statement to which the control has to be transferred is preceded by a label and a colon.
E.g.
Forward jumping:
goto abc;
s1;
s2;
abc: s3;
s4;
Forward jumping:
abc: s1;
s2;
goto abc;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

32

PROGRAMING IN C - A STUDY MATERIAL

Its mostly avoided in C programming as it makes the program difficult to understand. Its
generally used in nested loops to transfer the control to the end of all loops from the innermost loop.

Tips and Tricks:


1. Zero (0) is treated as FALSE in loops.
2. If 0 is used in conditions, itll be false and program will not execute (in while loop and in for loop
{except turbo c}) or the program will execute at least once (in dowhile loop and in for loop {in turbo
c only}).
3. In for loop, all parts are optional and hence can be dropped but in while and dowhile all parts are
compulsory and if omitted itll show error.
4. If a loop is terminated with a semicolon (;), a for loop is finite, a while loop is infinite, but a dowhile
loop is work normally as semicolon is a must to a dowhile loop but after while keyword only. If after
do ; will be given, itll show a parse error.
int i;
for (i=0;i<=10;i++);
printf (%d,i);

int i=0;
while(i<=10);
printf (%d,i++);

int i=0;
do printf (%d,i++);
while (i<=10);

output: 10

output: infinite loop

output: 10

5. Curly braces are necessary only when we work with multiple statements inside the loop. They can be
dropped if theres a single statement.
6. The for and while are pre-tested while the dowhile is a post-tested.
7. If step value is dropped, the loop is infinite.
8. If loop counter is beyond its range, that loop will become an infinite loop. E.g.
char ch;
for (ch=5; ch<=256; ch++)
printf (%d,ch);
//infinite as range of char is -128 to 127.
9. Continue can only be used in a looping construct.
10. In for, while, etc, the order is from left to right.
int x=5, y=7;
while ( x, y)
{
printf (%d%d ,x,y);
x--; y--;
}
output: 57 46 35 24 13 02 -11
Explanation: since left to right order, the while didnt terminated when x=0; but when y becomes 0, it
evaluates as FALSE and hence terminated.
11. Loop is also used for software delay. E.g.
int i;
printf (hello);
for ( i=1; i<=10000; i++)
printf (hi);
12. Loop counter can be int, char, and float.
13. If loop counter is not initialized in a loop, that is called odd loop.
14. Loop is an alternate of function recursion and function recursion is an alternate of loop.
15. for loop is suitable for finite loop, while loop is suitable for unknown loop and do while loop is
suitable for looping at least once.
16. Loop counter has its own block scoping.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

33

PROGRAMING IN C - A STUDY MATERIAL

17. break in loop transfers the control outside of the loop.


18. continue transfers the control to the beginning of loop.
19. Every loop has a start value; step value and stop value.
20. Loop is faster than function recursion.
21. Only one statement falls under the default scope of the control structure.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

34

PROGRAMING IN C - A STUDY MATERIAL

MODULE II

CHAPTER 5 (FUNCTIONS)
Functions are the small and self-contained components of a program, which have some unique identifiable purpose.
Every C function composed of same things: name, return type, arguments and a body. These are used to break down
large programs into smaller modules. These modularize the program and this is called as the modular property of
function which makes debugging easier i.e. improves the programs readability, enhances the programming
structure and helps the programmer to detect the errors faster and more easily.
Use of Functions:
Code Reusability: saves repetition of common routines. Functions once written can be reused in different
programs without having to rewrite them again.
Program portability: This is a benefit arising from re-usability of code. Because programs will become smaller
in size and subsequent packaging or programs will become easier and faster.
Maintaining large programs become easier because of the following reasons:
Different modules work independently of each other.
We just need to understand and monitor what the large pieces or modules or functions as a whole
will do, individual statements or the program are not important.
Unnecessary details are hidden.
Changing one modules or functions code should have limited effects on other parts.
Modularizing the program: easier to debug the program.
Allows function recursion or recursive execution of a module or functionality.
TYPES OF FUNCTIONS:
1. Standard Library Functions : These are technically not a part of the C language. But theres a wide prepackaged
functions available in the standard library to reduce program development time and make programs more
portable. To use a standard library function we have to include its header file, which contains the header
information such as prototype, macros, typedef names, global variables. E.g. scanf ( ), printf ( ), strlen ( ), etc.
2. User Defined Functions
: These are defined by the programmer to perform specific tasks. E.g.
main ( )
{
int a, b;
printf (sum = %d,add(a,b));
/*function call*/
}
int add (int x, int y)
/*function definition*/
{
return x+y;
}
Here add ( ) is a user defined function, which is used to add two numbers.
PARTS OF FUNCTIONS:
Return
Type

Function
Name

Function
Argument

int add (int, int)


1. Return Type: It tells the compiler which type of data will be returned from the called function. The default return
type of a function is an integer.
2. Function Name: Its a constant pointer that gives the address of the function, where its defined.
3. Function Argument: These specify to the compiler which type of data transmitted to the called function from
the calling function.
Actual Argument: The arguments passed from the calling function are called actual arguments. In
the above example a, b are the actual arguments.
Formal Arguments: The arguments that receive the values passed from the calling function to the
called function are called formal arguments. In the above example x, y are the formal arguments.
USING A FUNCTION:
Functions are classified as one of the derived data type in C. Therefore we can define functions and use them like
any other variable in C.
Both function name and variable names are considered identifiers.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

35

PROGRAMING IN C - A STUDY MATERIAL


Like variables, functions have types (such as int) associated with them.
Like variables, function names and their types must be declared and defined before use.
1. Function Prototype Declaration: Like variables, all functions in a c program must be declared, before they are
invoked. A function declaration, also known as function prototype.
Syntax: <return type> <function name> (<data types of argument list separated by commas (,)>);
E.g.
int add ( int, float);
2. Function Definition: Function need to be defined. Function definition contains a function declarator followed by
function body.
Syntax:
<return type> <function name> (<formal argument list with data types separated by commas (,)>) //declarator
{
//function body start
statements;
return statement;
}
//function body end
E.g.
int add ( int x, float y)
{
int z;
z = x + y;
return z;
}
3. Function Call: A function can be called by the function name followed by a list of actual argument. A function
is a latent body. It gets activated only when a call to function is invoked.
Syntax:
<function name> (<actual argument list separated by commas (,)>);
E.g.
add ( x, y );
or
add ( 2, 4);
or
add ( a, 7) ;
Key Notes:
i. Function declaration tells the compiler about the availability of the function and helps the compiler to check
the return and argument type of the function.
ii. The declarator of function definition must be similar to its prototype declaration.
iii. The type of parameters in declaration must match the type of parameters in the definition both in number
and order.
iv. The function can be defined anywhere. If the function is defined before its caller, then its prototype
declaration is optional.
v. When a function reaches its return statement, the control is transferred back to the calling program. In
absence of a return statement, the closing braces act as a void return.
vi. A local variable is a variable that is defined inside a function and used without having any role in the
communication between functions.
vii. When the compiler encounters a function call, the control is transferred to the function definition with same
function name. This function is then executed and a value is returned to the calling function when a return
statement is encountered. And then the program continues its execution.
viii. A function can be called as much number of times.
ix. At each call, the control passes to the subroutine at a specified address in the memory. The CPU stores the
memory address of instruction following the function calls into the stack and also pushes the values of actual
arguments in the stack area. The compiler then pops the values to formal arguments and runs the function,
stores the return value in a memory location or register.
FUNCTION CONVENTIONS:
1. pascal: Declare a variable or a function using pascal style naming convention. When its applied to a function
header, the first parameter is pushed to the stack first. E.g.
void main(){
void pascal show();
int x=0;
show(x++,x++);
void pascal show(int x, int y)
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

36

PROGRAMING IN C - A STUDY MATERIAL


{
printf (%d %d, x, y);
}
output: 0 1
2. cdecl: Here the last parameter is pushed to the stack first, and the calling function cleans up the stack. E.g.
void main(){
void cdecl show();
int x=0;
show(x++,x++);
void cdecl show(int x, int y)
{
printf (%d %d, x, y);
}
output: 1 0
FUNCTION COMMUNICATION:
1. Forward communication: When data is transferred from calling function to called function, its called forward
communication and possible only due to function parameters.
2. Backward communication: When data is returned from called function to calling function, its called backward
communication and possible only due to the function return statement.
CATEGORY OF FUNCTION:
1. Return type having argument: Here both forward and backward communication occurs. E.g.
int add (int x, int y)
{
return (x + y);
}
2. Return type having void as argument: Here only backward communication occurs. E.g.
int add (void)
{
int x, y;
scanf (%d %d, x, y);
return (x + y);
}
3. No return type having argument: Here only forward communication occurs. E.g.
void add (int x, int y)
{
printf (%d, x + y);
}
4. No return type having no argument: Here neither forward nor backward communication occurs. E.g.
void add (void)
{
int x, y;
scanf (%d %d, x, y);
printf (%d, x + y);
}
NOTE: A function can return multiple values, but the arguments must be of reference type i.e. pointers to the
variable.
FUNCTION CALL:
1. STD CALL: When function call and the function definition are both in the same program, then the function call is
called STD call.
2. ISD CALL: When function definition is present in another file and that file is included in source file, such a
function call is called STD call.
3. Local CALL: When the same function is called by itself, its called local call or technically function recursion.
FUNCTION STANDARDS:
1. ANSI Standard:
void add (int, int);
void main ( )
{
add (5, 6);
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

37

PROGRAMING IN C - A STUDY MATERIAL


}
void add (int x, int y)
//ANSI standard
{
printf (%d, x + y);
}
2. K & R Standard:
void add (int, int)
void main ( )
{
add (5, 6);
}
void add (x, y)
int x, y;
//K & R standard
{
printf (%d, x + y);
}
PARAMETER PASSING:
The technique used to pass data from one function to another is known as parameter passing. Parameter passing
can be done in two ways:
1. Call by Value: In this type, value of actual argument is passed to the formal argument and operation is done on
the formal arguments. Any change in the formal argument does not affect the actual argument because formal
arguments are only the photocopies of actual arguments. Changes made in the formal arguments are local to the
block of called function. Once control returns back to the calling function the changes made vanish.
Point to Note: The addresses of actual and formal arguments are different. Thus changes made with the
variables are temporary.
Example:
void change ( int, int);
void main ( )
{
change ( x, y) ;
}
void change ( int a, int b)
{
//statements
}
2. Call by Address:
In this type, instead of passing values, addresses are passed. Function operates on addresses rather than values.
Here the formal arguments are pointers to the actual arguments. Hence changes made in the arguments are
permanent.
The formal arguments receive the addresses of actual arguments. The function operates of actual arguments trough
pointers.
Point to Note: The addresses of actual arguments and formal arguments are same. Hence, the changes made in the
values are permanent.
Example:
void change ( int ,int ) ;
void main ( )
{
change ( &x , &y ) ;
}
void change ( int *a , int *b )
{ //statements
}

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

38

PROGRAMING IN C - A STUDY MATERIAL


DYNAMIC FUNCTIONS (FUNCTIONS WITH VARIABLE NUMBER OF ARGUMENTS)
Some functions have a variable number of arguments and data types which can not be known at compile time, are
called as dynamic functions. The printf and scanf functions are typical examples. The ANSI standard proposes new
symbol called the ellipsis to handle such functions. The ellipsis consists of three periods () and used as shown
bellow:
int printf(const char *format, );
Both the function declaration and definition should use ellipsis to indicate that the arguments are arbitrary both in
number and type. To work with dynamic functions the following macros and typedef names play a vital role.
va_list
//typedef name
va_args
//macro
va_start
//macro
va_end
//macro
These are defined in the header file stdarg.h for ANSI and vargs.h for UNIX-V.
typedef void * va_list;
va_list p;
Here p is a variable of type va_list (generic pointer).
#define va_start(ap, parmN) ((void) ((ap) = (va_list)((char *) (&parmN) +__size(parmN))))
Load the argument list into memory and set the pointer to point to the base address of a variable number of
argument list.
#define va_arg (ap, type) (*(type *) ((( * (char **) & (ap)) += __size (type)) (__size(type))))
Reads the argument from the argument list and the pointer is shifted to the next argument.
#define va_end(ap) ((void) 0)
Unload the arguments list from memory.
Example:
#include stdarg.h
int sum(char *, );
main()
{
int x;
x = sum(total:, 2,5,3,5,7,0);
printf(%d,x);
}
int sum(char *r, )
{
int k, s=0;
va_list p;
va_start(p,r);
while (( k=va_arg(p, int)) !=0)
s = s+k;
va_end(p);
return s;
}
Output: 22
Working with variable numbers of argument without Macros:
Example:
int sum();
main()
{
int x;
x = sum(2,5,3,5,7,0);
printf(%d,x);
}
int sum()
{
int s=0;
void *p;
p = ;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

39

PROGRAMING IN C - A STUDY MATERIAL


while( *(int *) p !=0)
s = s+*((int *)p)++;
return s;
}
Output: 22

RECURSION

Nesting of the function calls can be to any level depending on the requirement. The phenomena of a function calling
itself directly or indirectly is called recursion (direct recursion or indirect recursion). The function involved in the
process is referred to as a recursive function.
Example: WAP to find factorial of a number using recursive function.
#include<stdio.h>
int fact ( int );
void main( )
{
int number,f;
printf ( enter a number \n) ;
scanf ( %d,&number) ;
f = fact ( number ) ;
printf ( fact = %d \n,f) ;
}
int fact ( int number)
{
int f;
if ( number == 0)
return 1;
else
f = number * fact (number -1);
// fact ( ) call itself
return f;
}
OUTPUT:
Enter a number
4
factorial of 4 = 24.
Properties of function recursion:
i. Alternative to looping constructs.
ii. Nature of function recursion is always an infinite loop or stack overflow.
iii. Expensive in both processor time and memory space as compare to loop.
iv. Helps in writing cryptic codes.
v. Used for some specific purpose, like in-order, pre-order and post-order traversal of a tree, tower of Hanoi,
Quick sort, etc.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

40

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 6 (STORAGE CLASSES)

Depending on where a variable is allocated required storage (CPU register or RAM), the area of existence in a
program (scope) and its longevity (lifetime), variables are classified into what are called storage classes. They help to
determine four properties, namely lifetime, storage, visibility (scope) and default initial value. Following are four
storage classes:
1. automatic
2.static
3.register
4.extern
Automatic Storage Class:
The variable declares with in a function are by default of an automatic storage class. The keyword auto can also be
used to explicitly specify it.
void fun()
{
int i;
// storage class of variable i would be auto
auto int j;
// storage class of variable j explicitly auto
}
Automatic variables are characterized by the following properties:
i) Automatic variables are stored in memory.
ii) The default initial value of automatic variable is garbage.
iii) They are visible within the block in which they are defined.
iv) Their lifetime is the duration of the function or block only.
v) Every local variable is by default auto variables.
vi) They can not be declared outside of functions.
Static storage class:
Variable can be made to belong to static storage class by explicitly using the keyword static while declaring them.
The variable of static storage class may be declared either within or outside the functions.
void fun()
{
static int a ;
}
Static variables are characterized by the following properties:
i. static variables are stored in memory.
ii. The default initial value of static object is 0(zero).
iii. They are local to the block in which they are defined.
iv. Their lifetime is the duration of the entire programs duration.
v. Static variables are initialized at compile time and therefore they are initialized only once. They can not be
reinitialized on the re-entry into the function. The previous values persist.
vi. Static variables can be used to retain values between function calls. Count the number of calls made to a
function can be done by the static variable.
Example:

void start ( void );


main ( )
{
int i ;
for ( i =1 ; i < =3 ; i++ )
start ( );
}
void start ( )
{
static int x = 0;
x=x+1;
printf ( x = %d \n , x );
}

OUTPUT:

x=1
x=2
x=3
vii. static variables can be initialized with constant expression, address of other static or extern variables.
viii. It is used to overcome dangling pointer problems.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

41

PROGRAMING IN C - A STUDY MATERIAL


Example:
int *show();
main()
{
int *p;
p = show();
printf(%d, *p); }
int *show() {
static int k = 6;
return &k;
}
Output: 6
Register Storage class:
Significance of register storage class is based on the role of memory and CPU in relation to program and data.
Memory acts as workspace for programs and data. CPU plays the role of Instruction Executer. CPU needs fetch
instructions and data from memory. Register storage class enables us to tell the compiler that some variables are to
be stored in CPU general purpose registers. CPU can act upon these data directly without requiring fetching from
memory, which results in increase in the speed of execution of the program.
void function-name()
{
register int i , j ; }
Variable i and j are allocated two register.
Register variables are characterized by the following properties:
i. Only local variables of type int, char can be declared with the keyword register.
ii. If a variable is declared as register but the processor is unable to locate an empty register, then in order to
continue program execution, the processor will allocate the variable into the RAM just like auto variables.
iii. The default initial value of the register variable is garbage.
iv. They are local to the block in which the variable is declared.
v. Their lifetime is duration of the function or block only.
vi. Faster program execution.
vii. Register variable has no memory address. Thus pointers can not be implemented on them.
Extern storage class:
Variables belonging to extern storage class used to access by more than one function, the variables are called global
variables. The keyword extern instructs the compiler that the variable is an external variable and it is defined
somewhere else in the program or in another file.
Example:
extern int i;
void f1( ){ printf ( %d , i ) ; }
void f2( ) { printf ( %d ,i ) ; }
void main( )
{
int i=5;
printf ( %d , i);
f1 ( ) ;
f2 ( ) ;
}
int i = 10;
OUTPUT:
5 10 10
Variables belonging to extern storage class are characterized by the following properties:
vi. External variables are stored in memory.
vii. They are declared outside of any functions.
viii. External variable declaration can not be initialized, because no memory is allocated for the external variable
declaration.
ix. The default initial value of external variable is 0.
x. The area of their existence is from the point of declaration till the end of the program.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

42

PROGRAMING IN C - A STUDY MATERIAL


xi. Their lifetime is the duration of the entire program.
xii. Within a multi-file program external variables can be defined in one file and accessed in another.
TIPS AND TRICKS:
1. The life time of an auto variable declared in main is the entire program execution time, although its scope is
only the main function.
2. If a variable is redeclared within its scope again, it loses its visibility in the scope of the redeclared variable.
3. A function definition can not be embedded within another function definition (Lexical scoping).
4. cdecl is the default convention of any C program.
5. Convention decides the order of parameter passing in the function.
Exception:-keyword pascal cant be used before main();
6. Default storage class of a function is extern.
7. Default return type of a function is int.
8. ISD calls to a function hides the data abstraction, increases the reusability and reliability of codes.
9. Function name gives the address of the function, like array name.
10. Functions are created in the code segment.
11. Function recursion is a substitute to using looping or iteration constructs.
12. In function recursion function, frames are created in ascending order and released in descending order that
is LIFO.
13. Storage class of a function is allocated only when the functions body is defined.
14. Function returns value, function parameters, local automatic variables of a function stores it in stack area.
15. If function return type is non integer, a prototype is required.
16. Function at a time returns only one value.
17. Copy of the variable is created when it is pass by value.
18. The size of the function is ( called function frame) manually calculated in the following way:
Size of the local auto variables.
Size of function actual parameter.
Size of return address.
Size of base address of the next function.
19. Library is a special file which hides details about the functionalities of a function.
20. When a program is linking with static library, all symbols present in static library will be copied to program.
21. A function can be called in two different ways, such as
Function name fallowed by ( ).
Function pointer.
22. Function is used to modularize the program.
23. Functions are created in stack memory in a form of doubly linked list, which fallows LIFO data structure.
24. Every library function is finally converted into system calls.
25. Library functions are user space implementation but system calls are kernel space implementation.
Storage Class:
26. Storage class decides the scope, life, storage and default initial value of variables, and functions.
27. Storage class follows four kinds of scoping rules such as:
Block scoping.
Function scoping.
File scoping
Program scoping.
28. Static storage class is used in three different places, such as:
File scoping
Sharing the same memory location in different frames of function recursion.
To avoid reinitialization of a variables.
29. External storage class is used for program scoping.
30. If a variable is defined in one file and that can be accessed in other file in the same program, we can say
variable has a program scoping.
31. If a variable is defined in one file and that cant be accessed in other file in the same program, we can say
variable has a file scoping.
32. Auto storage class allocates and reallocates memory automatically from stack area.
33. Register variable has no memory address, so pointer cant work with register variables.
34. Access time of register variables is 1 nanosecond but auto, static and external variables is 200 nanosecond.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

43

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 7 (ARRAYS)

To process large amounts of data (a group of data items), we need a powerful data type that would
facilitate efficient storing, accessing and manipulation of data items. To overcome the problem stated
above, C supports a derived data type known as array that can be used for such applications.
Definition:
An array is defined to be a group of logically related data items of similar type, stored in contiguous
memory locations, sharing a common name but distinguished by subscript(s) values. So, an array is a finite
ordered set of homogeneous elements.
Example:
List of employees in an organization.
List of products and their cost sold by a store.
Test scores of a class of students.
List of customers and their telephone numbers.
CLASSIFICATION OF ARRAY:
Depending on the number of subscripts used, arrays are classified into the following types:
One-dimensional arrays
Two-dimensional arrays
Multidimensional arrays

ONE-DIMENSIONAL ARRAYS

An array with only one subscript is termed as one-dimensional array or single-subscripted variable. It is
used to store a linear list of values.
DECLARATION OF ONE-DIMENSIONAL ARRAYS:

The general syntax to declare a one-dimensional array is as follows:


data-type array-name[size];
Example:
int num[5];
float marks[50];
char name[30];
Let A be an array with size N then, the elements of the array A may be denoted by the subscript notation
A[0], A[1], A[2], . . . , A[N-1]
Regardless of the notation, the number I in A[I] is called a subscript or an index and A[I] is called a
subscripted variable. In general, the length or the no. of data elements of the array, called its range can be
obtained from the index set by the formula
Length or size = UB LB + 1
Where UB is the largest index, called the Upper Bound, and LB is the smallest index, called the Lower
Bound of the array.
REPRESENTATION OF LINEAR ARRAYS IN MEMORY:

Example: Memory representation of


int A[5]; in a 16-bit machine is as follows:
100
102
104
106

108

A[0]
A[1]
A[2]
A[3]
A[4]
Here LB = 0, UB = 4 and the size of each element ESIZE = 2 bytes
Then address of the element present at subscript 3 can be calculated as
LOC (A[I]) = Base (A) + ESIZE * (I-LB)
LOC (A[3]) = 100 + 2 * (3 0) = 106
INITIALIZATION OF ONE-DIMENSIONAL ARRAYS:

An array can be initialized at either of the following stages:


At compile time
At run time
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

44

PROGRAMING IN C - A STUDY MATERIAL


Compile Time Initialization:

We can initialize the elements of arrays at the time of declaration. The general form of initialization of
arrays is
data-type array-name[size] = {value0, value1,value2, };
{value0, value1, , valuesize-1} are constant values.
Example: int A[5] ={10,20,30,40,50};
100
102
104
106
108
10

20

30

40

50

A[0]
A[1]
A[2]
A[3]
A[4]]
Points to remember:
1. Number of values should not exceed the size of the array.
2. If the number of values is less than the size of an array, then the remaining elements are initialized
to zero, if the array type is numeric and NULL if the type is char.
Example:
int A[5] = {10, 20, 30};
100
102
104
106
108
10

A[0]

20

A[1]

30

A[2]

A[3]

A[4]

3. If size is omitted in a 1-d array declaration, which is initialized, the compiler will supply the size by examining
the number of values in the initialize-list.
Example:
int A[ ] = {10, 20, 30, 40, 50}; Here the size of a is automatically supplied as five.
4. There is no array bound checking mechanism built into C-compiler. It is the responsibility of the programmer
to see to it that the subscript value does not go beyond size-1. If it does, the system may crash.
Example:
int A[5];
A[6] = 10;
it may lead to unpredictable results or even to system crash.
Run Time Initialization:
An array can be explicitly initialized at run time. This approach is usually applied for initializing large arrays.
For example, consider the following segment of a C program.
int num[50] , i ;
for(i = 0; i<50; i++)
{
num[i] = 1 ; // assignment statement
}
All the 50 elements are initialized to 1.
We can also use a read function such as scanf ( ) to initialize array elements with the values entered through the
keyboard.
Example:
int num[10], I ;
for(i=0 ; i<10; i++)
{
scanf(%d, &num[i]) ; }
Renaming an Array
An array can also be renamed by using of typedef.
Example:
typedef int Array[10];
Here Array becomes a data type for an array of 10 integers. i.e. if we wire:
Array my_arr;
It declares my_arr as an array of 10 integers and if we write:
Array arr2d[5];
It declares arr2d as an array of 5 arrays of 10 integers each.
Also note that:
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

45

PROGRAMING IN C - A STUDY MATERIAL


Array *ptrarr;
It makes ptrarr a pointer to an array of 10 integers.

TWO-DIMENSIONAL ARRAYS

An array with two subscripts is termed as two-dimensional array. It enables us to store multiple rows of elements,
that is, a table of values or a Matrix. For this reason, the two dimensional arrays are the perfect data structures for
storing matrices. Hence two-dimensional arrays are sometimes called matrix arrays.
Declaration of two-dimensional arrays:
The syntax of declaring a two-dimensional array is as follows:
Data-type array-name[rowsize][colsize];
Example:
int mat[3][4];
float marks[10][6];
char names[10][30];

The element of A with first subscript (row subscript) I and second subscript (column subscript) J will be
denoted by A[I][J]. The length of a dimension is the number of integers in its index set. The pair of lengths
m x n (read m by n) is called the size of the array.
The length of a given dimension can be obtained from the formula
Length = upper bound lower bound + 1
A two-dimensional 3 X 4 array A is shown bellow:
COLUMNS
0
1
2
3
A[0][0]
A[0][1]
A[0][2]
A[0][3]
0th ROW
A[1][0]

A[1][1]

A[1][2]

A[1][3]

A[2][0]

A[2][1]

A[2][2]

A[2][3]

1st Row
2nd ROW

REPRESENTATION OF TWO-DIMENSIONAL ARRAYS IN MEMORY:

Let A be a two-dimensional m x n array. Although A is pictured as a rectangular array of elements with m


rows and n columns, the array will be represented in memory by a block of m. n sequential memory
locations. Specifically, the programming language will store the array A either
1. row by row, called row-major order or
2. column by column, called column-major order
Example: Memory representation of:
int A[3][4]; in a 16 bit machine is as follows

ROW 1

ROW 2
ROW-MAJOR ORDER

Column 0

Column 1
Column 2
COLUMN -MAJOR ORDER
Computes the address LOC (A[I][J]) of A[I][J] using the formula
Row major order:
LOC(A[I][J]) = Base(A) + ESIZE [ n ( I RLB ) + ( J CLB) ]
Or the formula for Column major order:
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

ROW 3

Column 3

46

PROGRAMING IN C - A STUDY MATERIAL

LOC(A[I][J]) = Base(A) + ESIZE [ m ( J CLB ) + ( I RLB)]


Where, ESIZE- denotes the size of each element i.e number of words per memory location for the array A.
RLB - denotes the Row Lower Bound , CLB - denotes the Column Lower Bound
m - is the no.of rows and
n - is the no.of columns of the array A.
Note: In C, all multidimensional arrays are stored in row major order.

INITIALIZATION OF TWO-DIMENSIONAL ARRAYS:


Compile Time Initialization:

We can initialize the elements of a 2-d array at the time of declaration. There are two forms of initializing a
2-d array.
First form of initializing 2-d arrays is as follows:
data-type array-name [rowsize] [colsize] = { initializer-list };
Example:
int A[3][4] = { 2,5,11,6, 8,20,15,10,4,7, 13,18};
The second form of initializing a 2-d array has the following general syntax:
data-type array-name [rowsize] [colsize] = { {initializer-list1},{initializer-list2}, };
Example: int A[3][4] = { {2,5,11,6},{ 8,20,15,10},{4,7, 13,18}};
Point to Note:
If the number of values in the initializer-list is less than product of row size and column size, only the first
few matching locations of the array would get values from the initializer-list row wise. The trailing
unmatched locations would get zeros.
If the number of values specified in any initializer-list is less than colsize, only those many first locations in
the corresponding row would get these values. The remaining locations in that row would get zeros.
Example: int A[2][3] = { { 3, 4 } , { 4 , 5 , 6 } };
Run Time Initialization:

A 2-d array can be explicitly initialized at run time. For example, consider the following segment of a C
program.
int mat[3][4] , i , j ;
for(i = 0; i<3; i++)
{
for(j = 0; j<4; j++)
{ mat[i][j] = 1; // assignment statement
}
}
All the elements are initialized to 1. We can also use a read function such as scanf to initialize array
elements with the values entered through the keyboard.
Example:
int mat[3][4], i, j;
for(i=0 ; i<3; i++)
{
for(j=0; j<4; j++)
{ scanf(%d, &mat[i][j]); }
}

Multidimensional Arrays

C allows arrays of more than two dimensions (multidimensional arrays). The exact limit is determined by
the compiler. ANSI C does not specify any limit for array dimension. However, most compilers permit seven
to ten dimensions. Some allow even more.
Multidimensional Array Declaration:
The general form of a multidimensional array declaration is
data-type array-name[size1][size2][size3] . . . [sizeN];
Example:
int survey[3][5][12]; // three-dimensional array of 180 integers
float table[5][4][5][3]; // four-dimensional array of 300 floats
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

47

PROGRAMING IN C - A STUDY MATERIAL

ONE-DIMENSIONAL ARRAYS AS ARGUMENTS TO FUNCTIONS:


A function that takes an one-dimensional array as an argument need to be defined with two formal
parameters: array name with data type
Specified and the number of elements of the array being passed. The function is defined as:
return-type function-name ( data-type array-name [ ] , int s ize )
{
//function body
}
Example:
void display(int a[], int n)
{
int i;
for (i=0;i<n;i++)
printf(%d ,a[i]);
}
After the function is defined, while calling it, the calling program needs to pass just the array name of the
actual array belonging to it and the number of elements in the array as follows:
function-name(array-name, size);
Example:
int num [ 5 ] = { 3,2,45,22,10 } ;
display(num,5);
Three Rules to Pass an Array to a Function:
1. The function must be called by passing only the name of the array
2. In the function definition, the formal parameter must be an array type; the size of the array does
not need to be specified. The function prototype must show that the argument is an array.
Two-dimensional Arrays as Arguments to Functions:
A function that takes a two-dimensional array as an argument need to be defined with three formal
parameters:
a) Two-dimensional array name with data type followed by two pairs
of square brackets with
constant enclosed with the second pair of square brackets.
b) The number of rows in the array ( int )
c) The number of columns in the array ( int )
The function is defined as:
return-type function-name ( data-type array-name [ ] [size2], int rowsize, int colsize )
{
//function body
}
Example:
void display(int a[][10], int m, int n)
{ int i,j;
for (i=0;i<m;i++)
for(j=0;j<n;j++)
printf(%d ,a[i][j]);
}
While calling the function, the calling program needs to pass just the array name (with no square
brackets), number of rows and number of columns as:
function-name (array-name, rowsize, colsize);
Example:
int mat[2][3]={3,2,45,22,10,22};
display(mat,2,3);
Rules to Pass a Two-dimensional Array to a Function:
1. The function must be called by passing only the name of the array
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

48

PROGRAMING IN C - A STUDY MATERIAL

2. In the function definition, we must indicate that the array has two dimensions by including two sets
of brackets.
3. The size of the second dimension must be specified. It is to help the function select appropriate
elements when it moves to different rows. However, specification of size within the first pair of
square brackets is optional.
4. The prototype declaration should be similar to the function header.

STRINGS

A string in C is defined to be a sequence of characters terminated by the null character ( \0 ). The null
character indicates the end of a string.
Declaration of a String Variable:
C does not support strings as a data type. However, it allows us to represent strings as character arrays. In
C, therefore, a string variable is any valid C variable name and is always declared as an array of characters.
The general form of declaration of a string variable is:
char string-name[size];
Example:
char name[30];
char city[20]; char address[50];
Note: When the compiler assigns a character string to a character array, it automatically supplies a null
character (\0) at the end of the string. Therefore, the size should be equal to the maximum number of
characters in the string plus one.
Initializing String Variables (character arrays):
Character arrays may be initialized when they are declared. C permits a character array to be initialized in
either of the following two forms:
First form of initialization:
char string-name[size] = string;
Example:
char name[5] = John;
char city[10] = Berhampur;
Second form of initialization:
char string-name[size] = { chr1, chr2,,\0};
Example:
char name[5] = {J, o, h, n, \0};
char city[10] = {B, e, r, h, a, m, p, u, r};
Note that when we initialize a character array by listing its elements, we must supply explicitly the null
terminator.
STRING I/O:
Using scanf() and printf():
Syntax of using scanf() to accept a string into a string variable is as follows:
scanf(%s, string-name);
%s is the format specification for strings.
Note that string-name is not preceded by symbol & (address of operator). This is because, the
string variable name itself gives the address of the string.
The above statement accepts a string up to a white space character(Blanks, tabs, carriage returns,
form feeds, and new lines). The null character \0 will be automatically appended to the string. The
size of string-name is thus expected to be large enough to collect even the null character.
Example:
char str[10];
scanf(%s, str);
If the input is:
abcd xyz
Only abcd would be taken by str. Any subsequent scanf() to accept a string would read the string xyz.
Example:
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

49

PROGRAMING IN C - A STUDY MATERIAL

char str1[10], str2[10];


scanf(%s%s, str1, str2);
If the input is:
abcd xyz
abcd would be taken by str1 and xyz would be taken by str2.
Reading a Line of Text Using scanf():
scanf() with %s or %ws can not be used for reading a text containing more than one word. However C
supports a format specification known as the edit set conversion code %[. .] that can be used to read a line
containing a variety of characters, including whitespaces.
Example:
char line[80];
scanf(%[^\n], line);
The above program segment will read a line of input from the keyboard until a newline character is
encountered.
Using printf() to display a String:
The syntax of using printf() to display a string is:
printf(%s, string-name);
It displays the string contained in string-name. %s is the format specification for strings.
Example:
char str[10]=abcd xyz;
printf(%s, str);
Output:
abcd xyz
We can also specify the precision with which the array is displayed. For instance, the specification
%10.4s
Indicates that the first four characters are to be printed in a field width of 10 columns right-justified.
However, if we include the minus sign in the specification (%-10.4s), the string will be printed left-justified.
Using getchar() and putchar():
getchar() is used to read a character through standard input, keyboard. The syntax of its usage is
var=getchar();
Where var is a variable of type char. This can be used iteratively to accept a line of text.
Example:
char text[80], ch;
int i=0;
ch= getchar();
while (ch!=\n)
{
text[i]=ch;
ch=getchar();
i++;
}
text[i]=\0;
putchar() is used to display a character on standard output, screen. The syntax of its usage is
putchar(var);
Where var is a variable of type char. This can be used iteratively to display a line of text.
Example:
char text[80]=Ram is a good boy.;
int i=0;
for(i=0;text[i]!=\0;i++)
{
putchar(text[i]);
}
Using gets() and puts():
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

50

PROGRAMING IN C - A STUDY MATERIAL

gets () is used to read a string up to a newline character into a string variable. It automatically appends the
null character \0 to the end of the string. The syntax of its usage is
gets(string-name);
Example:
char text[80];
gets (text);
The purpose of puts() is to display a string contained in a string
variable. It also adds the new-line
character \n to the string automatically, as a result of which the cursor is moved down by one line after
the string is displayed. The syntax of its usage is
puts (string-name);
Example:
char text[80]= Ram is a good boy.;
puts (text);
Arithmetic and Relational Operations on Characters
Whenever a character constant or character variable is used in an expression, it is automatically converted
into an integer value by the system. The integer value depends on the local character set of the system. If
the machine uses the ASCII representation, then,
int x = a;
printf(%d, x);
will display the number 97 on the screen.
The expression ch>= A && ch<=Z would test whether the character contained in ch is an upper-case
letter.
We can convert a character digit to its equivalent integer value using the relationship x=ch 0
Where x is an integer variable and ch is a character variable and contains the character digit.
String Manipulation using Standard Library Functions:
Header file : <string.h>
Function
Prototype
Purpose/ Task
strlen(s)

size_t strlen(const char *s)

strcmp(s1,s2)

int strcmp(const char *s1,const


char *s2)

strncmp(s1,s2,n) int strncmp(const char *s1, const


char *s2, size_t n)

strcpy(s1,s2)
strncpy(s1,s2,n)

char *strcpy(char *s1,const char


*s2)
char *strncpy(char *s1,const char
*s2, size_t n)

strstr(str,substr)

char *strstr(const char *str, const


char *substr)

strcat(s1,s2)

char *strcat(char *s1,const char


*s2)

Returns the number of characters in string s.


Compares two strings lexicographically. Return a
negative value If s1<s2; 0 if s1 and s2 are identical;
and a positive value if s1>s2.
Compares first n characters of two strings
lexicographically. Returns the difference of the
ASCII values of the first individual mis-matched
character of two strings. If two strings are the
same in their first n characters, the return value is
zero.
Copies string s2 to string s1.
Copies first n no.of characters from the string s2 to
the string s1. If the length of the source string is
less than no.of characters specified, then strncpy
copies all of s2, followed by enough null characters
to add up to n characters in all.
Finds substring substr in the string str. If a match is
found then, returns a pointer to the first character
of the substring in the string str, otherwise returns
null.
The strcat() function appends the s2 string to the
s1 string over writing the \0 character at the end
of s1, and then adds a terminating \0 character.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

51

PROGRAMING IN C - A STUDY MATERIAL

strrev(s)

char *strrev(char *s)

The string may not overlap, and the s1 string must


enough space for the result.
Reverses the string s and returns the address of
the reverse string except the null character.

Two Dimensional Array of char Type (Table of strings):


A list of strings can be treated as a table of strings and a two-dimensional character array can be used to
store a list of strings. The syntax to declare a two-dimensional character array is
char string-name[size1][size2];
Example:
char names [5][30];
Initializing a two-dimensional character array:
char string-name [size1][size2]= { string1, string2,
,
stringN};
Example:
char names[5][30]={ John, James, jill, jack, jay};
Run time Initialization:
We can use scanf() to initialize list of strings at runtime.
int i;
char names[5][[30];
for(i=0;i<5;i++)
scanf(%s, name[i]);
Strings and Functions
When we pass a valid string (i.e a null terminated array of characters), we do not need to pass the number
of characters used unlike numerical arrays because the function can calculate this by looking for the null
character that terminates the string. A function that takes a string as an argument is defined as:
return-type function-name(char string-name[])
{
//function body
}
Example:
int stringlength(char str[])
{
int i,len=0;
for (i=0;str[i]!=\0;i++)
{
len++; }
return len;
}
While calling the function, the calling program needs to pass just the string-name (with no square brackets)
as:
function-name (string-name);
Example:
char name[30]=Jagannath;
int l;
l=stringlength(name);
Passing Table of Strings to Functions
A function that takes a two-dimensional character array as an argument needs to be defined with two
formal parameters:
a) Two-dimensional array name with data type followed by two pairs of square brackets with constant
enclosed with the second pair of square brackets.
b) The number of rows (strings) in the array (int) .
The function is defined as:
return-type function-name(char array-name[ ][size2],
int
no_of_strings)
{
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

52

PROGRAMING IN C - A STUDY MATERIAL

//function body

}
Example:
void display(char names[][30], int n)
{
int i;
for (i=0;i<n;i++)
printf(%s\n ,names[i]);
}
While calling the function, the calling program needs to pass just the array-name (with no square brackets),
number of rows(strings) as:
function-name(array-name, no_of_strings);
Example:
char names[3][30]={John, Jimy, jack};
display (names,3);
Limitations of Array:
It is static in nature.
Array size cant expand or cant be squeezed at run time
Holds only similar type of data.
Unused memory cant be used at the time of requirement
TIPS AND TRICKS:
1. Size of an array must always be mentioned as a positive, non-zero integer constant.
2. A single dimensional arrays elements can be represented in four different ways.
Example:
int a[5] = { 1,2,3,4,5};
printf(%d %d %d %d, 0[a], a[0], *(0+a), *(a+0));
3. Array size cant be variable at the time of declaration.
4. Array name is a constant pointer and gives the address of the 0th element of the array.
5. Limitation of an array is:

6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.

Unused memory of an array can not be used.


Array size can not be changed in run time.
One array can not be assigned to another array, because both are constant pointer.
The size of the zero length array is 0.
malloc memory alloction is single dimensional array equivalent and calloc memory allocation is double
dimensional array equivalents.
The major difference between strcpy and strncpy is strcpy copies the whole string including null character
but strncpy does not cpy null character.
Double dimensional array is a collection of single dimensional array, where each single dimensional array
must be used for different purpose.
Visiting double dimensional array in row major is always faster than column major.
Array name + 1 = Address of next element if it is single dimensional array.
Array name + 1 = Address of next array if it is double dimensional array.
To get the address of any elements of a double array. Use
a. Address = base address + (row number * column size + col number) + size of element.
Address of the array name gives the address of the entire array
Address of the array name + 1 = base address + entire array size.
The size of the array can be any integral constant or any macro constant or enum constant but not a
constant variable.
Mentioning the array name gives the address of 0th element (base address) of the array, except when the
array name is used with the sizeof() operatorn.
The left most dimension is optional when the array is initialized.
When initialization is a part of the declaration then the array storage class is static.
Array elements cant be variables.
An array equivalent pointer looks like an array but behaves like a pointer.
Example:

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

53

PROGRAMING IN C - A STUDY MATERIAL


main()

int arr[] = { 4,6,3,5};


show(arr,4);

}
show (int p[4],int x)
{
printf(%d,sizeof(p));
}
Output: 2 or 4
Here p[4] is used as the receiver in the function show() which acts as an array equivalent pointer.
22. The maximum number of bytes that can be allocated through an array must be less than 65536
because of the segmented architecture used with C for DOS.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

54

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 8 (POINTERS)
A pointer is a derived data type, built from one of the fundamental data types available in C.
Pointers contain memory addresses as their values. Since these memory addresses are the
locations in the memory where program instructions and data are stored, pointers can be used to
access and manipulate data stored in the memory.
Advantages of Using Pointers:
1. Pointers are more efficient in handling arrays and data tables
2. Pointers can be used to return multiple values from a function via function arguments.
3. Pointers permit references to functions and thereby facilitating passing of functions as arguments
to other functions.
4. The use of pointer arrays to character strings results in saving of data storage space in memory.
5. Pointers allow C to support dynamic memory management.
Pointers used to manipulate dynamic data structures such as structures, linked lists, queues, stacks and
trees.
7. Pointers reduce length and complexity of programs.
8. They increase the execution speed and thus reduce the program execution time.
Memory Organization
Memory is organized as a sequential collection of storage cells.
Each cell commonly known as a byte.
Each byte is identifiable by a unique number called address associated with it.
Typically, the addresses are numbered consecutively, starting from zero. The last address depends on the
memory size. A computer system having 1KB memory will have its last address as 1023.
Memory cell
Address

.
.
.

1022
1023

Underlying Concepts of Pointers


Pointers are built on the three underlying concepts as follows:
1. Pointer Constants: Memory addresses within a computer are referred to as pointer constants. We
not change them; we can only use them to store data values. They are like house numbers.
2. Pointer Values: We cannot save the value of a memory address directly. We can only obtain the
value through the variable stored there using the address operator (&). The value thus obtained is
known as pointer value. The pointer value (i.e. the address of a variable) may change from one run
of the program to another.
3. Pointer Variables: Once we have a pointer value, it can be stored into another variable. The
variable that contains a pointer value is called as a pointer variable.
Pointer Operators (& and *)
C provides two special operators known as pointer operators. They are & and *. & stands for Address of
and it is used to retrieve the address of a variable. * stands for value at address and it is used to access
the value at a location by means of its address.
Accessing the Address of a Variable
Declaration of a variable conveys two things to the compiler. As a result, the compiler does two things.
1. Allocates a location in memory. The number of bytes in the location depends on the data type of
the variable.
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

55

PROGRAMING IN C - A STUDY MATERIAL

2. Establishes a mapping between the address of the location and the name of the variable. Note that
the address is of the first byte of the location of the variable.

Example: int x = 120;

The actual location of a variable in the memory is system dependent. We can determine the address of a
variable with the help of the operator &. The operator & immediately preceding a variable returns the
address of the variable associated with it.
Example:
the statement p=&x;
would assign the address of the variable x (i.e. 5000) to the variable p.
The & operator can be used only with a simple variable or an array element. The following are illegal use of
address of operator:
1. &125 (pointing at constants).
2. &(x+y) (pointing at expressions).
3. The & operator must never appear on the left hand side of an assignment statement.
Pointer Variables:
The address of a variable can be retrieved and stored in another variable. A variable which can store the
address of another variable is called as a pointer variable (i.e. pointer).
Declaring Pointer Variables:
The syntax to declare a pointer variable is
data-type *pt-name;
This tells the compiler three things about the variable pt-name.
1. The asterisk (*) tells that the variable pt-name is pointer variable.
2. pt-name needs a memory location.
3. pt-name points to a variable of type data-type.
Example:
int *pi;
float *pf;
All un-initialized pointers will have some unknown values that will be interpreted as memory addresses.
Thus they are called wild pointers.
Initializing a Pointer Variable:
The process of assigning the address of a variable to a pointer variable is known as initialization. The syntax
to initialize a pointer variable is
data-type *pt-name = &var-name;
Or
data-type *pt-name;
pt-name = &var-name;
Example:
int x=120, *px;
px=&x;
Notes:
We could also define a pointer variable with an initial value of NULL or 0 (zero). That is the
following statements are valid.
int *p = NULL;
int *p = 0;
With the exception of NULL and 0, no other constant value can be assigned to a pointer variable. For
example, the following is wrong:
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

56

PROGRAMING IN C - A STUDY MATERIAL

int *p = 6300;
/* absolute address */
Pointers are flexible. We can make the same pointer to point to different data variables in different
statements. Example:
int x, y, z, *p;
p = &x;
..
p = &y;
..
p = &z;
..
We can also use different pointers to point to the same data variable.
Example:
int x;
int *p1 = &x;
int *p2 = &x;
int *p3 = &x;

Accessing a Variable Through Its Pointer


Accessing the value of a variable using the pointer is done by using another unary operator *(asterisk),
usually known as the indirection operator. Another name for the indirection operator is the dereferencing
operator.
Example:
int x, *px, n;
x = 10;
px = &x;
n = *px;
printf( x = %d\n n = %d \n,x,n);
Output:
x = 10
n = 10
The two statements
px = &x;
n = *px;
are equivalent to
n = *&x;
which in turn is equivalent to
n = x;
In, C the assignment of pointers and addresses is always done symbolically, by means of symbolic names.
You cannot access the value stored at the address 4523 by writing *4523. It will not work.
Pointer Arithmetic
Following are the operations that can be performed over pointers:
1. Adding an integer value to a pointer ( p + integer value)
2. Subtracting an integer value from a pointer (p integer value)
3. Comparing two pointers if they point the elements of the same array.
4. Subtracting one pointer from another pointer if both point to the same array.
5. Assigning one pointer to another pointer of same type. (p1 = p2)
6. A pointer variable can be pre-fixed and post-fixed with increment or decrement operators. ( p++ or
p--)
But the following operations are not possible:
1. Addition of two pointers
2. Subtraction of one pointer from another pointer when they do not point to the same array.
3. Multiplication of two pointers
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

57

PROGRAMING IN C - A STUDY MATERIAL

4. Division of one pointer by another pointer


5. A pointer variable cannot be multiplied by a constant
6. A value cannot be assigned to an arbitrary address (i.e. &x = 10; is illegal)
When we increment/decrement a pointer, its value is increased/decreased by the length (size) of the data
type that it points to. This length called the scale factor.
Example:
If p is an integer pointer with an initial value, say 100, then after the operation p = p +1, the value of p will
be 102(in a 16 bit machine);
i.e. p + n = p + n * scale factor
Pointers and One-dimensional Arrays
When an array is declared, the compiler defines the array name as a constant pointer to the first element
(index 0). Thus the name of an array is a pointer variable containing the address of the first element of the
array. In other words, if we declare
int x[5], *xptr;
x is a constant integer pointer containing the address of the element x[0]. Further, the statements
xptr = &x[0];
xptr = x;
xptr = &x; (unusual assignment permitted by ANSI C)
are all equivalent.
Accessing Elements of the Array Using Pointer
Suppose we declare an array x as follows:
int x[5] = { 10, 20, 30, 40, 50};
Consider the base address of x is 500.Then, In a 16 bit machine, the elements of the array x will be stored
as follows:
Elements ->
Values->
Address->

x[0]
10
500

x[1]
20
502

x[2]

x[3]

x[4]

30

40

50

504

506

508

If we declare a pointer to integer, then we can make the pointer p to point to the array x by the following
assignment:
p = x;
This is equivalent to
p = &x[0];
Now, we can access every element of x using p++ to move from one element to another. The relation
between p and x is shown as:
p = &x[0] (= 500)
p+1 = &x[1] (=502)
p+2 = &x[2] (=504)
p+3 = &x[3] (=506)
p+4 = &x[4] (=508)
The address of an element can be calculated using its index and the scale factor of the data type. For
instance
address of x[3] = base address + (3 X scale factor of int)
= 500 + (3 X 2) = 506
To access elements of the array we can use pointers instead of using array indexing. The pointer accessing
method is much faster than array indexing.
The relationship between pointer accessing method and array indexing method:
*x = *p = *(x + 0) = x[0]
*(p+1) = *(x + 1) = x[1]
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

58

PROGRAMING IN C - A STUDY MATERIAL

*(p+2) = *(x + 2) = x[2]


*(p+3) = *(x + 3) = x[3]
*(p+4) = *(x + 4) = x[4]
In general, (x+i) gives the address of ith element in the array x and *(x+i) is the element stored in the ith
location of the array.
Pointer to Pointer (chain of pointers or double pointer)
It is possible to make a pointer to point to another pointer, thus creating a chain of pointers. The syntax to
declare a pointer to another pointer is
data-type **pt-name;
Example:
int **ptr;
This declaration tells the compiler that ptr is a pointer to a pointer of int type.
A double pointer can be initialized by assigning the address of a pointer as follows:
int x = 10, *px, **ppx;
px = &x ;
ppx = &px;
We access the target value indirectly pointed to by pointer to a pointer by applying the indirection
operator twice. The statements
int n = **ppx;
printf( %d ,n);
Will assign 10 (value x) to the variable n and then print 10.
Pointers and Two-dimensional arrays
A 2-d array is essentially an array of 1-d arrays. So each element in a 2d array happens to be a 1-d array.
Here also, the 2-d array name gives its base address, i.e., the address of its first element. First element in
this case is the first 1-d array. Thus, the two dimensional array name is a pointer to its first 1-d array. Since
1-d array itself is a pointer, So the name of every two dimensional array is a pointer to an array of
pointers.
The syntax to declare a pointer to a two dimensional array is
data-type (*pt-name)[size];
Example:
int (*ptr) [4];
The above declaration declares a pointer to an array of 4 int variables. Therefore, incrementing ptr by 1,
increments the address in ptr by the size of 4 int variables. Suppose a 2-d array A of int type, which is
declared as follows:
int A[3][4];
Then, we can assign the base address of 2-d array A to the pointer ptr as follows:
ptr = A;
0

<- ptr

<- ptr+1

2,0
*(ptr 2)

2,3

<-ptr+2

*(( ptr +2) +3)

An element A[i][j] in a two-dimensional array can be represented by the pointer expression as follows:
*(*(A+i)+j) or *(*(ptr+i)+j)
ptr pointer to first row
ptr+i pointer to ith row
*(ptr+i) pointer to first element in the ith row
*(ptr+i)+j pointer to the jth element int the ith row
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

59

PROGRAMING IN C - A STUDY MATERIAL

*(*(ptr+i)+j) value stored in the cell (i,j) (ith row and jth column)
(A+0) is the address of first 1-d array *(A+0) is the first 1-d array
(A+1 ) is the address of second 1-d array
*(A+1) is the second 1-darray
(A+2) is the address of third 1-d array
*(A+2)is the third 1-d array
st
*(A+0)+0 is the address of first element in the 1 1-d array
*(A+0)+1 is the address of 2nd element in the 1st 1-d array
Similarly.
*(*(A+0)+0) gives the 1st element in the 1st 1-d array
*(*(A+1)+0) gives the 1st element in the 2nd 1-d array
*(*(A+2)+1) gives the 2nd element in the 3rd 1-d array
*(*(A+0)+1) gives the 2nd element in the 1st 1-d array
Pointers And Character Strings
C supports an alternative method to create strings using pointer variables of type char.
Example:
char *str = good;
This create a string for the literal and then stores its address in the pointer variable str. The pointer str
now points to the first character of the string good as follows:
g

\0

str

Point to Note:
The string name itself is pointer to the string. So, we do need to use indirection operator.
Pointer As Function Arguments
We can pass addresses to a function; the parameters receiving the addresses should be pointers. The
process of calling a function using pointers to pass the addresses of the variable is knows as call by
reference.
Example:
main ( )
{
int x;
x = 20 ;
change ( &x );
printf ( %d \n , x);
}
change ( int *p)
{
*p = *p + 10;
}
Thus, call by reference provides a mechanism by which the function can change the stored values in the
calling function. This mechanism is also knows as call by address or pass by pointers.
FUNCTION RETURNING POINTERS:
A function can return a single value by its name or return multiple values through pointer parameters.
Since, pointers are a data type in C, we can also force a function to return a pointer to the calling function.
int *large ( int * , int * ) ;
main ( )
{
int *p;
p = large ( &a, &b );
}
int * large ( int *x, int *y)
{
}

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

60

PROGRAMING IN C - A STUDY MATERIAL

Note: The address returned must be the address of a variable in the calling function. It is an error to return
a pointer to a local variable in the called function.
POINTERS TO FUNCTION:
In C it is possible to declare a pointer to a function, which can then be used as an argument in another
function. A pointer to a function is declared as follows:
type (*fptr ) ( ) ;
This tells the compiler that fptr is a pointer to a function, which returns type value. The parentheses
around *fptr are necessary.
We can make a function pointer to point to a specific function by simply assigning the name of the function
to the pointer. For example:
double mul ( int ,int ) ;
double ( * p1 ) ( ) ;
p1 = mul ;
declare p1 as a pointer to function and mul as a function and then make p1 to point to the function mul. To
call the function mul, we may now the pointer p1 with the list of parameters. That is,
(* p1) (x, y) / * function call */
Is equivalent to mul ( x ,y ).
Note:
type *gptr ( ); this statement declare as a function returning a pointer to type.
TIPS & TRICKS:
1.
2.
3.
4.
5.
6.
7.
8.
9.

10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.

When a pointer refers to 0 ( zero) address, it is called null pointer.


Generic pointer can not be dereferenced.
Arithmetic is not allowed in generic pointer.
Return type of malloc and calloc function is generic pointer.
Address + 1 = next address of its type.
When a pointer refers an invalid address, then it will be called wild pointer.
When the pointer loses reference, then it is called memory leak.
Size of a pointer in gcc is 4 bytes.
In TC, when a pointer works within 64KB memory, then it is called near pointer. But when the pointer
works beyond 64KB memory, then it is called far pointer.
All near pointers occupy two bytes because all the addresses in the data segment are unsigned integers.
All far and huge pointers occupy 4 bytes because they hold the address in two parts, one is a segment
which occupies 2 bytes itself and offset which also occupies 2 bytes.
Dereferencing to a wild pointer is called core dump.
When the pointer address becomes invalid in a program, then it is called dangling pointer.
Function name and array name are known as constant pointers.
When more than one pointer refers to same location and one of them is modifying the resources, at the
same moment others are waiting, then that pointer must be a restrict pointer.
Dynamic memory allocation is possible using pointer.
Random access of any memory cell of a variable will use pointer.
A function can be called or invoke using a function pointer.
Dereferencing to a null pointer is known as null pointer assignment.
Inter-casting is not allowed in case of pointers, it causes an error Cannot convert.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

61

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 9 (DYNAMIC MEMORY ALLOCATION)


The alternative to the static memory allocation is to determine the memory requirements during runtime and
allocate the necessary amount of memory. This is known as dynamic memory allocation and there are three
functions for achieving this:
Function
Task
void *malloc(size_t size_in_bytes)
Allocates request size of bytes and returns a
pointer to the first byte of the allocated
space.
void *calloc(size_t num_elements, size_t element_size) Allocates space for an array of elements,
initializes them to zero and then returns a
pointer to the memory
void free(void *ptr)
Frees previously allocated space
void *realloc(void *ptr,size_t new_size)
Modifies the size of previously allocated
space
ALLOCATION OF A BLOCK OF MEMORY: malloc( )
A block of memory may be allocated using the function malloc. The malloc function reserves a block of memory of
specified size and returns a pointer of type void. This means that we can assign it to any type of pointer. It takes the
following form:
ptr = ( cast type * ) malloc ( byte-size ) ;
ptr is a pointer of type cast-type. The malloc returns a pointer ( of cast-type ) to an area of memory with size bytesize.
Example:
x = ( int * ) malloc ( 100 * sizeof( int ) ) ;
A memory space equivalent to 100 times the size of an int bytes is reserved and the address of the first byte of the
memory allocated is assigned to the pointer x of the type of int.
Example:
cptr = ( char * ) malloc (10 ) ;
Allocates 10 bytes of space for the pointer of type char.
Point to Note: The malloc allocates a block of contiguous bytes. The allocation can fail if the space in the heap is not
sufficient to satisfy the request and it returns a NULL.
ALLOCATION OF MULTIPLE BLOCKS OF MEMORY: calloc( )
calloc is another memory allocation function that is normally used for requesting memory space at runtime for
storing derived data types such as arrays and structures. calloc alloctes memory for multiples blocks of storage each
of the same size and then sets all bytes to zero. The general form of calloc is:
ptr = ( cast-type ) calloc ( n, elem-size ) ;
Example:
struct student
{
int rno;
char name [20];
};
typedef struct student s ;
s *st_ptr ;
int size = 50 ;
st_ptr = ( s*) calloc ( size , sizeof (s ) ) ;
The calloc allocates memory to hold data for 50 records.
RELEASING THE USED SPACE: free( )
With the dynamic run time allocation, it is our responsibility to release the space when it is not required. For release
block of memory using the free function:
free ( ptr ) ;
ptr is a pointer to a memory block, which has already been created by malloc or calloc.
Points to Note:
i. It is not the pointer that is being released but rather what it points to.
ii. To release an array of memory that was allocated by calloc we need only to release the pointer once. It is an
error to attempt to release elements individually.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

62

PROGRAMING IN C - A STUDY MATERIAL


ALTERING THE SIZE OF A BLOCK: realloc( )
If the previously allocated memory is not sufficient, we need additional space for more elements. Therefore, we can
change the memory size already allocated with the help of the function realloc. This process is called the reallocation
of memory.
Example:
ptr = malloc ( size );
ptr = realloc ( ptr , newsize ) ;
This function allocates a new memory space of size new size to the pointer variable ptr and returns a pointer to the
first byte of the new memory block.
Points to be Note:
i.
The new memory block may or may not begin at the same place as the old one.
ii.
In case it is not able to find additional space in the same region , it will create the same in an entirely
new region and move the contents of the old block into the new block.
iii.
The function guarantees that the old data will remain intact.
MEMORY LEAKS:
When we allocate memory dynamically but do not deallocate it, that block of memory becomes unusable for the
lifetime of the program. The operating system keeps it reserved for our program as long as our program is running.
Example:
int *ptr ;
ptr = ( int * ) malloc (100 );
ptr = (int *) malloc (200 ) ;
ptr = ( int * ) malloc ( 300 ) ;
The first two times when memory is allocated to ptr, we do not deallocate it. This results in 300 bytes of memory
becoming unusable as we do not have any means of accessing it because we have reassigned ptr to point to a new
block of memory. This is known as a memory leak in dynamic memory allocation.
TIPS & TRICKS:
1. Dynamic Memory Allocation in C is a part of heap area.
2. Memory allocation in C is possible through variable and functions.
3. Basically dynamic memory allocation is done by a family of 3 functions in C, such as malloc( ), calloc( ), and
realloc( ).
4. Malloc, calloc and realloc always allocates memory above the break pointer.
5. Break pointer is the initial entry point in heap.
6. brk and sbrk functions are used to set and retrieve the break pointer.
7. Memory allocated in heap remains in existence for the duration of a program.
8. When memory is allocated from heap their address grow upwards and heap size decreases and when memory is
free heap size increases.
9. Free means break pointer is decreasing in the form of last break pointer melloc size header size.
10. Static allocation: when you declare a static and global variable in C program that reserves block of space, of a
fixed size when program is loaded and never free before program is unloaded.
11. Static allocation is a part of Data or BSS area.
12. Automatic allocation: when you declare automatic variables, such as function, actual arguments and local
variables in C program they reserve memory when control is entered in scope and are automatically freed when
a control leaves the scope.
13. Automatic memory allocation is a part of stack area.
14. Dynamical memory allocation is not supported by C variables; there is no storage class called dynamic to
allocate memory dynamically from the process memory in run time.
15. realloc() is used to resize the memory block either allocated by malloc and calloc.
16. Malloc memory allocation is a single dimensional array equivalent and calloc memory allocation is a double
dimensional array equivalent.
17. Free memory should not be free again.
18. It is an error to assign the return value from malloc and calloc to anything other than a pointer.
19. The major difference between calloc and malloc is that calloc initializes all the bytes of the allocated memory to
0 values where as malloc does not perform any initialization.
20. If dynamically allocated memory is not deallocated properly, some part of the memory becomes unusable. This
is known as memory leak.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

63

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 10 (COMMAND LINE ARGUMENT)


This is a mechanism to pass arguments at the command prompt to a program from external sources. The main ( )
function can have three arguments, namely the argument counter, the argument vector and the environment
vector.
SYNTAX:
main ( int argc, char *argv[] , char *env[] )
where
The 1st argument is the argument counter
The 2nd argument is the argument vector
The 3rd argument is the environment vector
1. Argument counter:
It is an integer variable that counts the number of arguments passed into the main function as command line
arguments.
Example:
void main ( int argc , char *argv[] )
{
printf ( no of arguments passed in the command line is : %d,argc );
}
2. Argument vector:
The argv is an array of pointers to string, the first string is referenced by argv[0] or by *argv. And the second
string is referenced by argv[1] or by *(argv+1) and so on.
The first string argv[0], contains the program name which is mandatory to run the program. Command line
arguments begin with argv[1] .if the application have a fixed number of arguments ,then the counter argc should
always be checked.
3. Environment vector:
It is an array of pointers to string which shows the environment variables of the operating system.
Example:
Print the environment variable settings
void main ( int argc, char *argv[],char *env[])
{
int i =0 ;
while (env [i] )
{
printf ( \n %s,env[i]);
i++;
}
}
TIPS & TRICKS:
1. Program takes input from different input devices, such as keyboard, scanner, and mouse. Where as
command line is used as another input media to a program.
2. In command line argument process use argument counter, argument vector and environment vector.
3. Space is used as a separator from one parameter to another parameter in command line argument.
4. Every parameter in command line argument is of string types.
5. Argument vector and Environment vector are array of string type.
6. argc, argv and env are used generally in command line argument.
7. Generally in the command line arguments, the names begin used are argc, argv and env. But remember
these are variables like any other and hence any name is acceptable as long as they are obeying the variable
naming conventions.
8. Since argc and argv are main ( ) function parameters, they behave like initialized local variables. They are not
directly accessible by other functions.
9. The program name is the first parameter on the command line, which is argv[0]. The command-line
arguments are argv[1] through agv[argc-1].

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

64

PROGRAMING IN C - A STUDY MATERIAL

MODULE III

CHAPTER 11 (STRUCTURES, UNIONS AND ENUMERATIONS)


STRUCTURES:

Structures sometimes referred to as aggregates are collections of related variables under one name. Structures
may contain variables of many different data types in contrast to arrays that contain only elements of the same
data type.
Structures are commonly used to define records to be stored in files.
Structures and pointers facilitate the formation of more complex data structures such as linked lists, queues,
stacks and trees.
Structure Definitions:
Structures are derived data types they are constructed using objects (variables) other types.
Syntax:
struct tag_name
{
datatype member1;
datatype member2;
.
.
datatype membern;
};
where struct is a keyword. tag_name is a user defined name (it is the name of the structure).
Example:
struct employee
{
int empno;
char name[30];
float salary;
};
Structure members are not variables by themselves. So, Structure definitions do not reserve any space in
memory; rather, each definition creates a new data type that is used to define variables. Memory locations get
allocated only when variables of the structure are declared.
A structure cannot contain an instance of itself. For example, a variable of type struct employee cannot be
declared in the definition for struct employee. However, a pointer to struct employee may be included. A
structure containing a member that is a pointer to the same structure type is referred to as a self-referential
structure. Self-referential structures are used to build linked data structures. For example:
struct linkedlist
{
int info;
struct linkedlist *link;
};
Declaration of Structure Variables:
Syntax:
struct tag_name variable_name;
As a result of this , n memory locations get allocated for n members of the structure.
Example:
struct employee e;
This results in allocation of three locations which are contiguous in nature as follows:
e.empno

e.name

e.salary

All the data items share the common name e and are distinguishable by members empno, name and salary.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

65

PROGRAMING IN C - A STUDY MATERIAL


We can even declare variables of structure type while defining the structure template itself.
Syntax:
struct tag_name
{
datatype member1;
datatype member2;
.
.
datatype membern;
} variable_1,variable_2, , variable_m;
Example:
struct tag_name
{
int rollno;
char name[30];
float salary;
} e1, e2;
Note:
The structure tag name is optional. If a structure definition does not contain a structure tag name, variables
of the structure type may be declared only in the structure definition not in a separate declaration.
Initializing Structures:
Syntax:
struct tag_name variable_name = { member1-value, member2-value, , membern-value};
Example:
struct employee e = { 1001, john, 20000.00};
e.empno
1001

e.name

e.salary

john

20000.00

If there are fewer initializers in the list than members in the structure, the remaining members are
automatically initialized to 0 (or NULL if the member is a pointer).
Structure variables may also be initialized in assignment statements by assigning a structure variable of the
same type, or by assigning values to the individual members of the structure.
Accessing Members of Structures:
Two operators are used to access members of structures: the structure member operator (.) also called the dot
operator and the structure pointer operator (->) also called the arrow operator.
The structure member operator accesses a structure member via the structure variable name.
Syntax:
structure-variable-name.member-name
Example: to print member empno of structure variable e use the statement
printf(%d,e.empno);
The structure pointer operator accesses a structure member via a pointer to the structure.
Syntax:
structure-pointer-name->member-name
Example:
struct employee *eptr = &e;
To print member empno of structure variable e with pointer eptr, use the statement
printf(%d,eptr->empno);
The expression eptr->empno is equivalent to (*eptr).empno, which dereferences the pointer and
accesses the member empno using the structure member operator. The parentheses are needed
here because the structure member operator (.) has a higher precedence than the pointer
dereferencing operator (*).

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

66

PROGRAMING IN C - A STUDY MATERIAL


Operations on Structures:
The only valid operations that may be performed on structures are following:
1. Assigning structure variables to structure variables of the same type.
2. Taking the address (&) of a structure variable.
3. Accessing the member of a structure variable.
4. Using the sizeof operator to determine the size of a structure variable.
5. Structures may not be compared using operators == and !=, because structure members are not necessarily
stored in consecutive bytes of memory. Sometimes there are holes in a structure, because computers may
store specific data types only on certain memory boundaries such as half word, word or double word
boundaries. A word is a standard memory unit used to store data in a computer usually 2 bytes or 4 bytes.
Consider the following structure definition:
struct example
{
char c;
int i;
} sample1, sample2;
A computer with 2-byte words may require that each member of struct example be aligned on a word
boundary, i.e., at the beginning of a word (this is machine dependent). The following figure shows a simple
storage alignment for a variable of type struct example that has been assigned the character a and the
integer 97 (the bit representations of the values are shown).
byte 0

01100001
00000000
01100001
(Possible storage alignment for a variable of type struct example showing an undefined area in memory)
If the members are stored beginning at word boundaries, there is a 1-byte hole (byte 1 in the figure) in the
storage for variables of type struct example. The value in the 1-byte hole is undefined. Even if the member
values of sample1 and sample2 are in fact equal, the structures are not necessarily equal, because the
undefined 1-byte holes are not likely to contain identical values.
Note: because the size of data items of particular type is machine dependent and because storage alignment
considerations are machine dependent ,so too is the representation of a structure.
Using Structures With Functions:
Structures may be passed to functions by passing individual structure members, by passing an entire
structure or by passing a pointer to a structure.
When structures or individual structure members are passed to a function, they are passed by value.
To pass a structure by reference, pass the address of the structure variable. Array of structures like all
other arrays are automatically passed by reference.
An array could be passed by value by using a structure. To pass an array by value, create a structure with the
array as a member. Structures are passed by value, so the array is passed by value.
Passing structures by reference is more efficient than passing structures by value (which requires the entire
structure to be copied).
typedef:
The keyword typedef provides a mechanism for creating synonyms (or aliases) for previously defined
data types. Names for structure types are often defined with typedef to create shorter type names. For
example, the statement
typedef struct employee Emp;
defines the new type name Emp as a synonym for type struct employee.
C programmers often use typedef to define a structure type, so a structure tag is not required. For
example, the following definition
typedef struct
{
int empno;
char name[30];
float salary;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

67

PROGRAMING IN C - A STUDY MATERIAL


}Emp;
creates the structure type Emp without the need for a separate typedef statement.
Often, typedef is used to create synonyms for the basic data types. For example, a program requiring 4byte integers may use type int on one system and type long on another. Programs designed for
portability often use typedef to create an alias for 4-byte integers, such as Integer. The alias Integer can
be changed once in the program to make the program work on both systems.
Structure within Structure (Nested Structures)
Structures of one type are made the members of another structure.
Example:
struct date
{
int day, month, year;
};
struct emp
{
int empno;
char name[30];
struct date doj;
float salary;
};
The members of the nested structure are accessed using two dots as follows;
struct emp e;
e.doj.day=11; e.doj.month=3; e.doj.year=2011;

Nesting of structure can be to any level.

UNIONS

A union is a derived data type like a structure with members that share the same storage space. The number of
bytes used to store a union must be at least enough to hold the largest member.
A union is defined with keyword union in the same format as a structure. The union definition
Syntax:
union tag_name
{
data-type member1;
data-type member2;
.
.
data-type member;
};
Example:
union number
{
int x;
double y;
};
In a declaration, a union may be initialized with a value of the same type as the first union member. For example
union number value = { 10 };
is valid initialization of union variable value.
The operations that can be performed on a union are the following: assigning a union to another union
of the same type, taking the address of a union variable, and accessing union members using the
structure member operator and structure pointer operator.
unions may not be compared using operators == and != for the same reasons that structures cannot be
compared.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

68

PROGRAMING IN C - A STUDY MATERIAL

BIT FIELDS

A bit-field is basically a set of adjacent bits in a word of memory. Members of structure can include bit-fields. Bit
fields enable better memory utilization by storing data in the minimum number of bits required. Bit field members
must
be
declared
as
int
or
unsigned
int.
The syntax of defining structure template using bit-fields is given as:
struct tag_name
{
data-type m1 : size;
data-type m2 : size;
.
.
data-type mn: size;
};
Example:
struct bitfieldexample
{
int a : 3;
int b : 3;
unsigned int c : 3;
};
Bit fields can not be arrayed
We can not retrieve the address of a bit field. Consequently, the concept of pointer to a bit fields does not
arise.
If a bit field does not fit into a word, the bit field is placed into the next word.
Some members in the structure can be of normal data type also.
It is possible to specify an unnamed bit field to be used as padding in the structure. For example, the
structure definition
struct example
{
unsigned a: 13;
unsigned : 19;
unsigned b: 4;
};
uses an unnamed 19-bit field as padding nothing can be stored in those 19 bits. Member b (on our 4-byteword computer) is stored in another storage unit.
An unnamed bit field with a zero width is used to align the next bit field on a new storage unit boundary. For
example, the structure definition
struct example
{
unsigned a : 13;
unsigned : 0;
unsigned b : 4;
};
uses an unnamed 0-bit field to skip the remaining bits (as many as there are) of the storage unit in which a is
stored and to align b on the next storage-unit boundary.
Bit field manipulations are machine dependent. For example, some computers allow bit fields to cross word
boundaries, whereas others do not.
Although bit fields save space, using them can cause the compiler to generate slower-executing machinelanguage code. This occurs because it taked extra machine language operations to access only portions of an
addressable storage unit. This is one of many examples of the kinds of space-time trade-offs that occur in
computer science.

ENUMERATED DATA TYPE

Enumerated data type offers us a way of inventing our own data type. The invented new data type enables us to
assign symbolic names to integer constants, thereby increasing the degree of readability and maintainability. An
enumeration, introduced by the keyword enum, is a set of integer enumeration constants represented by identifiers.
Values in enum start with 0, unless specified otherwise, and are incremented by 1. However, the default integer

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

69

PROGRAMING IN C - A STUDY MATERIAL


constants of the enumerators can be overridden by assigning our own values. The syntax of defining an enumerated
type is as follows:
enum tag_name { enumerator-1, enumerator-2, , enumerator-n };
Example:
enum boolean { false, true };
The syntax of declaring a variable of enum type is as follows:
enum tag_name variable;
Example:
enum Boolean f;
f = false;
TIPS & TRICKS:
1. A structure always allocates memory in a form of block and block size depends on the longest data member
of the structure.
2. If a structure contains a slack byte, that is called an imbalance structure.
3. Word alignment is required to make imbalance structure to balance structure.
4. A structure can not be nested within same structure, because it is a restriction in C.
5. A structure can be nested within the same structure if nested structure is a pointer that is called selfreferential structure.
6. Structure is used for data encapsulation, memory link and bit fields.
7. Two structure variables can not be compared because it is the restriction in C.
8. One structure variable can be assigned to another structure variable if both belong to same structure.
9. Bit field is a unique feature in c which can be applied to a structure for memory optimization.
10. Each data member of a structure begins at different places.
11. Bit field range must be between 1 and size of its data member.
12. Bit field is not allowed to float data members.
13. Storage class to data members is not allowed.
14. A function cannot be a member of a structure.
15. Each member of structure enjoys different blocks of memory and all are continuous.
16. If a structures object is created globally then, storage class is by default extern.
17. The very first member of the union is an active data member and it must be the longest type.
18. Only first member of the union can be initialized at the time of definition and rest cant be initialized.
19. Union provides a technique to share a common memory in different ways.
20. Union size depends on the longest data member of the union.
21. Union is used for memory optimization, creating message formats and share memory or locking mechanism.
22. Each data member of a union begins at same place, but each data member of a structure begins at different
places.
23. Byte offset of the union data member is always 0.
24. To create a memory link or linked list we need a structure and that structure must be a self-referential
structure.
25. Data member can be accessed using. or -> notation.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

70

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 12 (FILE HANDLING)


The console input/output operations suffer from the following drawbacks:
The data involved in the I/O operations are lost when the program is exited or when the power goes
off.
This scheme is definitely not ideal for programs, which involve voluminous data.
The concept of files enables us to store large amount of data permanently on the secondary storage device. A file is
defined to be a collection of related data stored on secondary storage device like disk. It is a stream of bits stored as
a single unit. While a file is usually presented as single stream, it is often stored as multiple fragments of data at
different places on disk (or even multiple disks).
Streams:
A stream is a channel(logical device) through which data flows to/from a disk, keyboard, printer, etc.. It is a
contiguous group of bytes or chunk or block of data. It creates an interface between files and library
functions. It is also device independent.
A stream is linked to a file using an open operation. A stream is dissociated from a file using a close
operation.
Types of Streams:
Streams can be classified as
1. Text streams
2. Binary Streams
Text Streams:
Text streams are interpreted, with a maximum length of 255 characters. With text streams, carriage return/line feed
combinations are translated to the new line \n character and vice versa. Typically, a text stream would be used for
reading and writing standard text files, printing output to the screen or printer, or receiving input from the keyboard.
Binary Streams:
Binary streams are uninterpreted and are treated one byte at a time with no translation of characters. A binary text
stream would typically be used for reading and writing binary files such as graphics or word processing documents,
reading mouse input, or reading and writing to the modem.
File Pointers:
C communicates with files using a new data-type called a file pointer. This type is defined within stdio.h, and written
as FILE *. A file pointer called fptr is declared in a statement like
FILE *fptr;
OPERATIONS ON FILES:
The commonly performed operations over files are the following:
1. Opening a file
2. Reading from a file
3. Writing to a file
4. Appending to a file (adding to the end of the file)
5. Updating a file
6. Deleting a file
7. Renaming a file
8. Closing a file
These operations are accomplished by means of standard library functions that are provided by C.

OPENING A FILE:

There are two ways of accessing the file


1. Accessing files using standard C library functions
2. Accessing files using system calls

Accessing files using standard C library functions:


fopen():
Header file
Prototype
Description

: stdio.h
: FILE *fopen(const char *filename, const char *mode);
: Opens a stream. fopen opens the file named by filename and associates a stream with it. fopen
returns a pointer to be used to identify the stream in subsequent operations. The mode string used
in calls to fopen is one of the following values:

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

71

PROGRAMING IN C - A STUDY MATERIAL


Value
Description
r
Open for reading only. (The file must exist)
w
Create for writing. If a file by that name already exists, it will be overwritten.
a
Append; open for writing at end-of-file or create for writing if the file does not exist.
r+
Open an existing file for update (reading and writing).
w+
Create a new file for update (reading and writing). If a file by that name already exists, it will
be overwritten.
a+
Open for append; open (or create if the file does not exist) for update at the end of the file.
rb
Open a binary file for reading only. (The file must exist)
wb
Create a binary file for writing. If a file by that name already exists, it will be overwritten
ab
Append to a binary file; open (or create if the file does not exist) for update at end of the
file.
rb+
Open a binary file for both reading and writing. (The file must exist)
wb+
Create a new binary file for update (reading and writing). If a file by that name already
exists, it will be overwritten.
ab+ or Open for append to a binary file; open (or create if the file does not exist) for writing at end
of file.
a+b

Return Value

: On successful completion fopen returns a pointer to the newly opened stream. In the event of

error it returns NULL or 0.


Example:

/* Program to create backup of the AUTOEXEC.BAT file */


#include <stdio.h>
int main(void)
{
FILE *in, *out;
if ((in = fopen("\\AUTOEXEC.BAT", "rt"))
== NULL)
{
fprintf(stderr, "Cannot open input file.\n");
return 1;
}
if ((out = fopen("\\AUTOEXEC.BAK", "wt"))
== NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
while (!feof(in))
fputc(fgetc(in), out);
fclose(in);
fclose(out);
return 0;
}

Closing a File:
fclose()
Header file
Prototype
Description

: stdio.h
: int fclose(FILE *stream);
: Closes a stream. fclose closes the named stream. All buffers associated with the stream are flushed

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

72

PROGRAMING IN C - A STUDY MATERIAL


before closing. System-allocated buffers are freed upon closing. Buffers assigned with setbuf or setvbuf are not
automatically freed. (But if setvbuf is passed null for the buffer pointer it will free it upon close.)
Return Value : fclose returns 0 on success. It returns EOF if any errors were detected.
Example:

#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *fp;
char buf[11] = "0123456789";
/* create a file containing 10 bytes */
fp = fopen("DUMMY.FIL", "w");
fwrite(&buf, strlen(buf), 1, fp);
/* close the file */
fclose(fp);
return 0;
}

fcloseall()

fcloseall closes all files except stdin, stdout.


Returns the number of streams closed.

Streams Manipulations
Reading and Writing a character into a stream:

fgetc()
Header file
Prototype
Description
Return Value

: stdio.h
: int fgetc(FILE *stream);
: Gets character from stream. fgetc returns the next character on the named input stream.
: On success fgetc returns the character read after converting it to an int without sign extension. On

end-of-file or error it returns EOF.


Example:

#include <string.h>
#include <stdio.h>
#include <conio.h>
int main(void)
{
FILE *stream;
char string[] = "This is a test";
char ch;
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the beginning of the file */
fseek(stream, 0, SEEK_SET);
do
{
/* read a char from the file */
ch = fgetc(stream);
/* display the character */
putch(ch);
} while (ch != EOF);
fclose(stream);
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

73

PROGRAMING IN C - A STUDY MATERIAL


return 0;
}

fputc()
Header file
Prototype
Description
Note
Return Value
Example:

: stdio.h
: int fputc(int c, FILE *stream);
: Puts a character on a stream. fputc outputs character c to the named stream.
: For Win32s or Win32 GUI applications, stdin must be redirected.
: On success, fputc returns the character c. On error, it returns EOF.

#include <stdio.h>
int main(void)
{
char msg[] = "Hello world";
int i = 0;

while (msg[i])
{
fputc(msg[i], stdout);
i++;
}
return 0;

String Oriented Functions:


fgets()

: stdio.h
: char *fgets(char *s, int n, FILE *stream);
: Gets a string from a stream. fgets reads characters from stream into the string s. The function stops
reading when it reads either n - 1 characters or a newline character whichever comes first. fgets retains the newline
character at the end of s. A null byte is appended to s to mark the end of the string.
Return Value : On success fgets returns the string pointed to by s; it returns NULL on end-of-file or error.
Example:
#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *stream;
char string[] = "This is a test";
char msg[20];
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the start of the file */
fseek(stream, 0, SEEK_SET);
/* read a string from the file */
fgets(msg, strlen(string)+1, stream);
/* display the string */
printf("%s", msg);
Header file
Prototype
Description

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

74

PROGRAMING IN C - A STUDY MATERIAL


fclose(stream);
return 0;
}

fputs()

: stdio.h
: int fputs(const char *s, FILE *stream)
: Outputs a string on a stream. fputs copies the null-terminated string s to the given output stream; it
does not append a newline character and the terminating null character is not copied.
Return Value : On success fputs returns a non-negative value. On error it returns a value of EOF.
Header file
Prototype
Description

Example:

#include <stdio.h>
int main(void)
{
/* write a string to standard output */
fputs("Hello world\n", stdout);
return 0;
}

Writing & Reading an integer into stream:


putw()

: stdio.h
: int putw(int w, FILE *stream);
: Puts an integer on a stream. putw outputs the integer w to the given stream. putw neither expects
nor causes special alignment in the file.
Return Value : On success, putw returns the integer w. On error, putw returns EOF. Because EOF is a legitimate
integer, use ferror to detect errors with putw.
Headerfile
Prototype
Description

Example:

#include <stdio.h>
#include <stdlib.h>
#define FNAME "test.$$$"
int main(void)
{
FILE *fp;
int word;
/* place the word in a file */
fp = fopen(FNAME, "wb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
word = 94;
putw(word,fp);
if (ferror(fp))
printf("Error writing to file\n");
else
printf("Successful write\n");
fclose(fp);
/* reopen the file */
fp = fopen(FNAME, "rb");
if (fp == NULL)
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

75

PROGRAMING IN C - A STUDY MATERIAL


{
printf("Error opening file %s\n", FNAME);
exit(1);
}
/* extract the word */
word = getw(fp);
if (ferror(fp))
printf("Error reading file\n");
else
printf("Successful read: word = %d\n", word);
/* clean up */
fclose(fp);
unlink(FNAME);
return 0;
}

getw()

: stdio.h
: int getw(FILE *stream);
: Gets integer from stream. getw returns the next integer in the named input stream. It assumes no
special alignment in the file. getw should not be used when the stream is opened in text mode.
Return Value : getw returns the next integer on the input stream. On end-of-file or error, getw returns EOF.
Note
: Because EOF is a legitimate value for getw to return, feof or ferror should be used to detect end-offile or error.
Headerfile
Prototype
Description

Example:

#include <stdio.h>
#include <stdlib.h>
#define FNAME "test.$$$"
int main(void)
{
FILE *fp;
int word;
/* place the word in a file */
fp = fopen(FNAME, "wb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
word = 94;
putw(word,fp);
if (ferror(fp))
printf("Error writing to file\n");
else
printf("Successful write\n");
fclose(fp);
/* reopen the file */
fp = fopen(FNAME, "rb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
/* extract the word */
word = getw(fp);
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

76

PROGRAMING IN C - A STUDY MATERIAL


if (ferror(fp))
printf("Error reading file\n");
else
printf("Successful read: word = %d\n", word);
/* clean up */
fclose(fp);
unlink(FNAME);
return 0;
}

FORMATTED INPUT/ OUTPUT: (Mixed Data Oriented Functions)


fprintf()

: stdio.h
: int fprintf(FILE *stream, const char *format[, argument, ...]);
: Writes formatted output to a stream. fprintf accepts a series of arguments applies to each a format
specifier contained in the format string pointed to by format and outputs the formatted data to a
stream. There must be the same number of format specifiers as arguments.
Return Value : fprintf returns the number of bytes output. In the event of error it returns EOF.
Header file
Prototype
Description

Example:

#include <stdio.h>
int main(void)
{
FILE *stream;
int i = 100;
char c = 'C';
float f = 1.234;
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write some data to the file */
fprintf(stream, "%d %c %f", i, c, f);
/* close the file */
fclose(stream);
return 0;
}

fscanf()

: stdio.h
: int fscanf(FILE *stream, const char *format[, address, ...]);
: Scans and formats input from a stream. fscanf scans a series of input fields one character at a time
reading from a stream. Then each field is formatted according to a format specifier passed to fscanf
in the format string pointed to by format. Finally fscanf stores the formatted input at an address
passed to it as an argument following format. The number of format specifiers and addresses must
be the same as the number of input fields.
Note
: fscanf can stop scanning a particular field before it reaches the normal end-of-field character
(whitespace) or it can terminate entirely for a number of reasons.
Return Value : fscanf returns the number of input fields successfully scanned, converted and stored. The return
value does not include scanned fields that were not stored. If fscanf attempts to read at end-of-file,
the return value is EOF. If no fields were stored, the return value is 0.
Header file
Prototype
Description

Example:

#include <stdlib.h>
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

77

PROGRAMING IN C - A STUDY MATERIAL


#include <stdio.h>
int main(void)
{
int i;
printf("Input an integer: ");
/* read an integer from the
standard input stream */
if (fscanf(stdin, "%d", &i))
printf("The integer read was: %i\n", i);
else
{
fprintf(stderr, "Error reading an integer from stdin.\n");
exit(1);
}
return 0;
}

RECORD I/O FUNCTIONS:


fread()

: stdio.h
: size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
: Reads data from a stream. fread reads n items of data each of length size bytes from the given
input stream into a block pointed to by ptr. The total number of bytes read is (n * size).
Return Value : On success fread returns the number of items (not bytes) actually read. On end-of-file or error it
returns a short count (possibly 0).
Header file
Prototype
Description

Example:

#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *stream;
char msg[] = "this is a test";
char buf[20];
if ((stream = fopen("DUMMY.FIL", "w+"))
== NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
/* write some data to the file */
fwrite(msg, strlen(msg)+1, 1, stream);
/* seek to the beginning of the file */
fseek(stream, SEEK_SET, 0);
/* read the data and display it */
fread(buf, strlen(msg)+1, 1, stream);
printf("%s\n", buf);
fclose(stream);
return 0;
}

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

78

PROGRAMING IN C - A STUDY MATERIAL

fwrite()

: stdio.h
: size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
: Writes to a stream. fwrite appends n items of data each of length size bytes to the given output file.
The data written begins at ptr. The total number of bytes written is (n x size). ptr in the declarations
is a pointer to any object.
Return Value : On successful completion fwrite returns the number of items (not bytes) actually written. On error
it returns a short count.
Header file
Prototype
Description

Example:

#include <stdio.h>
struct mystruct
{
int i;
char ch;
};
int main(void)
{
FILE *stream;
struct mystruct s;
if ((stream = fopen("TEST.$$$", "wb")) == NULL) /* open file TEST.$$$ */
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
s.i = 0;
s.ch = 'A';
fwrite(&s, sizeof(s), 1, stream); /* write struct s to file */
fclose(stream); /* close file */
return 0;
}

freopen()

: stdio.h
: FILE *freopen(const char *filename, const char *mode, FILE *stream);
: Associates a new file with an open stream. freopen substitutes the named file in place of the open
stream. It closes stream regardless of whether the open succeeds. freopen is useful for changing the file attached to
stdin, stdout, or stderr. The mode string used in calls to fopen is one of the following values:
Header file
Prototype
Description

Value

Description

r
w
a
r+
w+
a+

Open for reading only.


Create for writing. .
Append; open for writing at end-of-file or create for writing if the file does not exist.
Open an existing file for update (reading and writing).
Create a new file for update (reading and writing).
Open for append; open (or create if the file does not exist) for update at the end of the file.

To specify that a given file is being opened or created in text mode append a t to the mode string (rt w+t and so on);
similarly to specify binary mode append a b to the mode string (wb a+b and so on). If a t or b is not given in the mode
string the mode is governed by the global variable _fmode. If _fmode is set to O_BINARY files are opened in binary
mode. If _fmode is set to O_TEXT they are opened in text mode. These O_... constants are defined in fcntl.h. When a
file is opened for update, both input and output can be done on the resulting stream; however, output cannot be
directly followed by input without an intervening fseekor rewind input cannot be directly followed by output without
an intervening fseek, rewind, or an input that encounters end-of-file
Return Value : On successful completion freopen returns the argument stream. On error it returns NULL.
Example:

#include <stdio.h>
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

79

PROGRAMING IN C - A STUDY MATERIAL


int main(void)
{
/* redirect standard output to a file */
if (freopen("OUTPUT.FIL", "w", stdout)
== NULL)
fprintf(stderr, "error redirecting stdout\n");
/* this output will go to a file */
printf("This will go into a file.");
/* close the standard output stream */
fclose(stdout);
return 0;
}

RANDOM ACCESSING OF FILE:


fseek()
Header file
Prototype
Description

: stdio.h
: int fseek(FILE *stream, long offset, int whence);
: Repositions a file pointer on a stream. fseek sets the file pointer associated with stream to a new
position that is offset bytes from the file location given by whence. For text mode streams offset
should be 0 or a value returned by ftell. whence must be one of the values 0. 1, or 2 which represent
three symbolic constants (defined in stdio.h) as follows:

Constant

whence

SEEK_SET
SEEK_CUR
SEEK_END

0
1
2

File location

File beginning
Current file pointer position
End-of-file

fseek discards any character pushed back using ungetc. fseek is used with stream I/O; for file handle I/O use lseek.
After fseek the next operation on an update file can be either input or output.
Return Value : fseek returns 0 if the pointer is successfully moved and nonzero on failure. fseek might return a 0
indicating that the pointer has been moved successfully when in fact it has not been. This is because
DOS, which actually resets the pointer, does not verify the setting. fseek returns an error code only
on an unopened file or device.
In the event of an error return the global variable errno is set to one of the following values:
EBADF
Bad file pointer
EINVAL
Invalid argument
ESPIPE
Illegal seek on device
Example:

#include <stdio.h>
long filesize(FILE *stream);
int main(void)
{
FILE *stream;
stream = fopen("MYFILE.TXT", "w+");
fprintf(stream, "This is a test");
printf("Filesize of MYFILE.TXT is %ld bytes\n", filesize(stream));
fclose(stream);
return 0;
}
long filesize(FILE *stream)
{
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

80

PROGRAMING IN C - A STUDY MATERIAL


fseek(stream, curpos, SEEK_SET);
return length;
}

ftell()

: stdio.h
: long int ftell(FILE *stream);
: Returns the current file pointer. ftell returns the current file pointer for stream. The offset is
measured in bytes from the beginning of the file (if the file is binary). The value returned by ftell can
be used in a subsequent call to fseek.
Return Value : ftell returns the current file pointer position on success. It returns -1L on error and sets the global
variable errno to a positive value. In the event of an error return the global variable errno is set to
one of the following values:
EBADF
Bad file pointer
ESPIPE
Illegal seek on device
Header file
Prototype
Description

Example:

#include <stdio.h>
int main(void)
{
FILE *stream;
stream = fopen("MYFILE.TXT", "w+");
fprintf(stream, "This is a test");
printf("The file pointer is at byte %ld\n", ftell(stream));
fclose(stream);
return 0;
}

rewind()

: stdio.h
: void rewind(FILE *stream);
: Repositions a file pointer to the beginning of a stream. rewind(stream) is equivalent to
fseek(stream, 0L, SEEK_SET), except that rewind clears the end-of-file and error indicators, while
fseek clears the end-of-file indicator only. After rewind, the next operation on an update file can be
either input or output.
Return Value : None.
Header file
Prototype
Description

Example:

#include <stdio.h>
#include <dir.h>
int main(void)
{
FILE *fp;
char *fname = "TXXXXXX", *newname, first;
newname = mktemp(fname);
fp = fopen(newname,"w+");
fprintf(fp,"abcdefghijklmnopqrstuvwxyz");
rewind(fp);
fscanf(fp,"%c",&first);
printf("The first character is: %c\n",first);
fclose(fp);
remove(newname);
return 0;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

81

PROGRAMING IN C - A STUDY MATERIAL


}

fgetpos()

: stdio.h
: int fgetpos(FILE *stream, fpos_t *pos);
: Gets the current file pointer. fgetpos stores the position of the file pointer associated with the
given stream in the location pointed to by pos. The exact value is unimportant; its value is opaque
except as a parameter to subsequent fsetpos calls.
Return Value : On success fgetpos returns 0. On failure it returns a nonzero value and sets the global variable
errno to
EBADF
Bad file number
EINVAL
Invalid number
Header file
Prototype
Description

Example:

#include <stdlib.h>
#include <stdio.h>
void showpos(FILE *stream);
int main(void)
{
FILE *stream;
fpos_t filepos;
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* save the file pointer position */
fgetpos(stream, &filepos);
/* write some data to the file */
fprintf(stream, "This is a test");
/* show the current file position */
showpos(stream);
/* set a new file position, display it */
if (fsetpos(stream, &filepos) == 0)
showpos(stream);
else
{
fprintf(stderr, "Error setting file pointer.\n");
exit(1);
}
/* close the file */
fclose(stream);
return 0;
}
void showpos(FILE *stream)
{
fpos_t pos;
/* display the current file pointer
position of a stream */
fgetpos(stream, &pos);
printf("File position: %ld\n", pos);
}

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

82

PROGRAMING IN C - A STUDY MATERIAL


TIPS & TRICKS:
1. The flow of data from buffer to device or device to buffer is called stream.
When data moves from device to buffer it is called an input stream and when it moves from buffer to device
it is called output stream.
2. When operating system allocates memory from a kernel space for special use, that memory is called buffer;
in Linux buffer size is 4k.
3. The contents of a file are stored in data block of disk.
4. The active file pointer write_ptr and read_ptr moves automatically to next character when any read /write
operation is perform.
5. When a stream is not associated in memory its file descriptor value is 1.
6. getc returns -1 when it reads ctrl + z character.
7. EOF(ctrl + z) is a macro whose expansion is -1 which is End of File indicator(ASCII value 26).
8. File handling is possible using std.library and system calls.
9. Read / Write operation using std.library and system call are possible in buffer instead of file.
10. fwrite and fread only works with low level file.
11. There are three file opening modes, such as read, write, and append.
12. When program execution begins the operating system opens the following five files automatically and stores
them in an array that is _streams[].
stdin the standard input stream
stdout the standard output stream
stdprn the standard printer stream
stderr the standard errors stream
stdaux the standard auxiliaries stream
these are the macros defined in stdio.h
Example:
#define stdin (&_streams[0])
#define stdout (&_streams[1])
..
13. when we create a file using fopen() or open(), our file may be created in the 5th element of the stream array.
14. open() is a function used to open a low level file from the disk, if it is available then it returns 1 other wise it
returns -1, this is called file handler.
15. fopen() is a function which is used to open a high level text or binary file and associate a stream with it and
load into memory. It returns a pointer if the file is available in the disk or else it will return NULL. This
address returned by fopen() is called File pointer.
16. fclose() is used to close the high level file (unload the file pointer from the RAM and write the ACSII value of
26 (ctrl+z) into that file which is the end of the file (EOF).
17. close() is used to close the low level file associated with the handle and write the ASCII value of 26 (ctrl+z) to
the end of file.
18. fcloseall() closes all files which are opened by the program except the files opened by default such as stdin,
stdout, stderr, stdprn, stdaux.
19. The operating system reserves 512 bytes for file buffer. When 512 bytes buffer is completed, automatically a
temporary file is created in the disk and contents of the buffers are copied to file. When the original file is
saved, the temporary file is automatically deleted.
20. fflush() is used to copy the contents of buffer to temporary file and clear the buffer.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

83

PROGRAMING IN C - A STUDY MATERIAL

CHAPTER 13 (PREPROCESSORS)

In C, the source program is first passed to the program called as PREPROCESSOR , the preprocessor acts on the
source program according to the instructions specified to it in the source program and the output produced by the
preprocessor is then submitted to the C compiler.
The instructions specified in the source program to the preprocessor are called the PREPROCESSOR DIRECTIVES.
Compilation of C program:
Source Program

Preprocessor

Expanded source
program

C compiler

In the first step, the process of preprocessor directive substitution is carried out by the preprocessor. The end result
is a modified C program.
In the second step, the modified source code is compiled into machine language code.
General Rules of Preprocessor Directives:
All preprocessor directives should start with the symbol #. ANSI allows the symbol to be preceded by space
or tabs.
Only one directive can appear in a line.
The directives are not terminated by semicolons.
The preprocessor directives can be placed anywhere in a source program. The directives apply to the source
code, which follows them.
Classification of Preprocessor Directive
The preprocessor directives are broadly classified into three types based on the purpose for which they are used.
1. Files Inclusion Directives
2. Macros Definition Directives
3. Conditional Compilation Directives.
FILE INCLUSION DIRECTIVES:
The #include preprocessor directive is used to include a file as part of the source program file. In response to the
directive #include <stdio.h> , the preprocessor expands the source file by embedding the contents of the header file
stdio.h, before the source program is submitted to the C compiler.
As a matter of fact, contents of any text file can be included as part of a source program with the help of the
directive. If the file name is enclosed within double quotes then the file is expected to be available in the current
working directory.
Example: suppose a file by name function.c in the current working directory, contains the definitions for the
functions used by a program, the file function.c can be included as part of the source program with the
directive #include function.c.
#include <stdio.h>
#include function.c
void main ( )
{
}
Here, the preprocessor embeds the contents of the header file stdio.h and the contents of the file function.c into the
source program before the program is passed onto the compiler.
MACROS DEFINITION DIRECTIVES-[#DEFINE, #UNDEF]:
A MACRO is defined to be a symbolic name assigned to a segment of text. The preprocessor directive #define is used
for defining macros. The syntax of its usage is as follows:
#define MACRO_NAME segment_of_text
Here macro_name is the name of a macro; which is used to construct valid identifiers and normally it is written using
upper case letters just to distinguish it from the identifiers. Segment_of_text is actually the string referred to bt the
MACRO_NAME.
Once a symbolic name (macro_name) is assigned to segment of text throughout the program, the symbolic name
can be used in place of the segment of text. The preprocessor then replaces all the occurrences of the macro_name
by the segment of text.
Example:
#define COUNT 10
// segment of text is numeric value
#define NO_OF_STUDENT 100
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

84

PROGRAMING IN C - A STUDY MATERIAL


#define ACCEPT printf (enter two numbers \n)

//segment of text is string

Example 1:
Wap to illustrate macro definition.
#define PI 3.14
#include<stdio.h>
main ( )
{
int area ,r ;
printf ( Enter the redius :) ;
scanf (%d , &r ) ;
area = PI * r * r ;
printf ( arer = %d , area );
}
Explanation: The macro PI has been replaced by the value 3.14 by the preprocessor. The process of replacement
of macros by their corresponding segments of texts is termed as macros substitution.
Example 2:
#define ACCEPT printf (enter two number :)
#include<stdio.h>
main ( )
{
ACCEPT;
}
MACROS WITH ARGUMENTS:
The preprocessor permits us to pass arguments to macros in such the same way as we pass arguments to functions.
Examples:
#define INCRE(x) if (x > 0) x = x +1
#define SQUARE ( x ) x * x
#define SQUARE(x) (x) * (x)
Then INCRE (a ) would be expanded to the statement if ( a > 0 ) a= a + 1
INCRE (b) would be expanded to the statement if (b > 0) b= b + 1
Example:
#include <stdio.h>
#define INCRE( x ) if ( x>0 ) x = x + 1
main ( )
{
int a , b ;
printf ( enter value of a: ) ;
INCRE ( a ) ;
printf ( %d , a ) ;
}
Q. T find the square of a number using macro with argument
#include <stdio.h>
#define SQUARE( x ) ( ( x ) * ( x ) )
main ( )
{
int a =5 ,sqr ;
sqr = SQUARE ( 4 ) ;
printf ( %d , sqr ) ;
}
Points to Note:
Consider two cases of macro as below
#define SQUARE(x) x * x
#define SQUARE(x) ((x) * (x))
Let us take the 1st case; SQUARE (3) expands to 3*3. We would get the square of 3, which is 9. To find square of the
expression a+2, we would use the macro SQUARE (a+2) expands to
a+2 * a+2
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

85

PROGRAMING IN C - A STUDY MATERIAL


the value of the expression will not be the square of a+2. This problem is eliminated by enclosing the argument
within parentheses in the replacement string as (x) * (x). New definition of the macro would be #define SQUARE ( x )
(x)*(x)
Now SQUARE ( a+2 ) is expanded to ( a + 2 ) * ( a + 2 ), which evaluates correctly to the square of a+2.
Self-Referential Macros:
A self-referential macro is one whose name appears in its definition. A special feature of ANSI standard C is that the
self-reference is not considered a macro call. It is passed into the preprocessor output unchanged.
Example:
#define CAL(x, CAL ) printf(%d %d,x,CAL)
void main( )
{
CAL(4,7) ;
}
Output: 4 7
Cascade use of Macro:
A cascaded of macros is when one macros body contains a reference to another macro.
Example:
#define BUFFSIZE 512
#define MEMSIZE BUFFSIZE
Stringification:
Working with # (string forming operator) and ## (token passing operator or Concatenation operator)
String forming operator (#):
It is used only in preprocessor function like macro expression and substitutes a string
literal for formal argument.
Example:
#define cal(x) printf(%s,#x);
void main ( )
{
cal( India is my country) ;
}
Output :
India is my country
Token Pasting Operator (##): it is used both in preprocessor function like macro expression and object like macro
expression to combine adjacent token before macro substitution occurs.
Example:
#define CAL(x) printf ( %d , A##x ) ;
void main( )
{
int A1 = 56 ;
CAL(1);
}
Output: 56
CONDITIONAL COMPILATION PREPROCESSOR DIRECTIVES:
As the name itself indicates that a way for compiling only the required sections of code in a source program.
Conditional compilation directives are as follows:
#ifdef, #ifndef, #endif, #if, #else
#ifdef - #endif Directives
The #ifdef -#endif directives check for the definition of a macro. The syntax of their usage is as follows:
#ifdef Macro_name
Statements;
#endif
Here, The statements will be considered for compilation only when macro_name has been defined. Otherwise the
statement will be ignored by the compiler.
#ifdef - #else - #endif Directives
The #ifdef-#else-#endif directives check for the definition of a macro. The syntax of their usage is as follows:
#ifdef Macro_name
Statement-1;
#else
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

86

PROGRAMING IN C - A STUDY MATERIAL


Statement-2:
#endif
Here, if Macro_name has been defined previously, statement-1 will be compiled. Otherwise, statement -2
will be compiled.
Q. To illustrate conditional compilation: usage of #ifdef - #else -#endif
#include<stdio.h>
#define SUM
void main( )
{
int a = 1, b = 5, r ;
#ifdef SUM
r=a+b;
printf ( Sum = %d , r ) ;
#else
r=ab;
printf ( Difference = %d \n , r ) ;
#endif
getch ( ) ;
}
Output:
Sum = 6
Explanation:
A macro by name SUM has been defined with the directive #define SUM, in the main ( ), since #ifdef SUM
evaluates to true, the statement r = a + b; printf (sum = %d , r ); are selected for compilation. The statements
between #else and #endif are ignored by the compiler.
If we remove the definition of the macro SUM and, compile and run the program, the program finds the
difference between a and b, and display it. This is because in the absence of the macro SUM.
#ifndef Directive:
The #ifndef directive is just the negative of the #ifdef directive. It is normally used to define a macro after
ascertaining that the macro has not been defined previously. The syntax of the directive for the purpose is as
follows:
#ifndef macro
#define macro
#endif
Example:
#ifndef SUM
#define SUM
#endif
#if Directive:
The #if directive is to select a block of code for compilation when a test-expression (rather than a macro) evaluates
to true, Otherwise to ignore the block of code for compilation.
Syntaxes of these directives are as follows:
#if - #endif
#if - #else - #endif
These are similar to their #ifdef counterparts except the fact that, here, macro are replaced by testexpression.
Example:
#if
#pragma: it is an implementation as specific directives. Pragma varies from one computer to another computer. If
the compiler does not recognize, it ignores the #pragma directives without any warning and errors.
#pragma inline: tells the compiler, we are dealing with asm keyword
Example:
#pragma inline
void main ( )
{
asm mov ax, 5 ;
asm mov bx, 6 ;
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

87

PROGRAMING IN C - A STUDY MATERIAL


asm add ax, bx ;
printf( %d , _AX ) ;
}
Output:
11
#pragma startup and #pragma exit: It allows the user to specify functions that are called upon program startup or
program exit.
startup called before main( )
exit called just before program terminates.
Example:
void show ( ) ;
void disp ( ) ;
#pragma startup show
#pragma exit disp
void main ( )
{
printf ( Hello:);
}
void show ( )
{
printf( Goodbye: );
}
void disp ( )
{
printf ( Bye Bye: ) ;
}
Output: Goodbye Hello Bye Bye
Precedence of Pragma Directives:
Functions with highest priorities are called first at start up and last at exit.
Here, in startup 1 enjoys the highest priorities and 1 enjoys the lowest in exit.
Example:
void show ( ) ;
void disp ( ) :
void cal ( ) ;
#pragma startup show 1
#pragma startup disp 2
#pragma startup cal 3
#pragma exit cal 2
#pragma exit show 3
#pragma exit disp 1
void main ( )
{
printf ( Hello ) ;
}
void show ( )
{
Printf ( Goodbye ) ;
}
void disp ( )
{
printf ( Bye Bye ) ;
}
void cal ( )
{
printf ( Hai ) ;
}
Output: Goodbye Bye Bye Hai Hello Goodbye Hai Bye Bye
Dealing with #error
VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

88

PROGRAMING IN C - A STUDY MATERIAL


Display the error message in the system window
Example:
void main ( )
{
#ifndef _STUDIO_H
#error STDIO.H is not included
#endif
}
#line Preprocessor Directive:
Tells the compiler to transfer the program control to the specified line number.
Example:
#line 5
void main ( )
{
int x ;
clrscr ( ) ;
printf ( hello . ) ;
printf ( Hie ) ;
getch ( ) ;
}
Output: Hello. Hie
TIPS & TRICKS:
1. When a macro takes a parameter it is called a parameterized macro or macro call.
2. Startup pragma is executed at first before control goes to main and exit pragma is executed at last once
control leaves main.
3. The C preprocessor CPP only process source file such as .c and .cpp but does not process object and
executable file.
4. The file inclusion preprocessor directive includes file using or < > where searches the file from the
current directory path and std.include path but < > searches the file only from the std.include path.
5. # is used as string forming where as ## is used as token pasting operator.

VIGNAN INSTITUTE OF TECHNOLOGY AND MANAGEMENT

89

You might also like