C Programming
C Programming
Copyright
C Programming
Page 1
Introduction
Copyright
C Programming
Page 2
Session 1
Copyright
C Programming
Page 3
Objectives
In this session, you will learn to:
Describe the evolution of the C programming language
Describe C as a second-generation as well as a thirdgeneration language
State the data types in C
Write simple C functions for input and output
Write C functions that employ conditional constructs
Write C functions that employ iterative constructs
Copyright
C Programming
Page 4
Evolution ???
Ken Thompson created the
B language in 1969 from
Martin Richard's BCPL
Martin Richard
Copyright
C Programming
Page 5
Copyright
C Programming
Page 6
C Programming
Page 7
Copyright
C Programming
Page 8
C Programming
Page 9
Copyright
C Programming
Page 10
C Programming
Page 11
Copyright
C Programming
Page 12
Copyright
C Programming
Page 13
/* Comment statements */
Preprocessor directives
main()
{
Program statements;
}
Copyright
C Programming
Page 14
Copyright
/* A sample C program */
# include <stdio.h>
int sum();
int a=10, b=20;
main()
{
int c;
c = sum();
printf(%d+%d = %d \n,a,b,c);
}
int sum()
{
return(a+b);
}
C Programming
Page 15
Copyright
C Programming
Page 16
C Programming
Page 17
C Programming
Page 18
Copyright
C Programming
Page 19
Defining Data
The general format for defining a variable of a data type is
[data type] [variable name]
All data is normally defined at the beginning of a function.
The definition:
char var;
defines a memory location of size one byte, of character type,
referred to as var.
Copyright
C Programming
Page 20
Defining Data
Data Definition
Data
Type
Memory
Defined
Size
Value
Assigned
char x, y
char
1 byte
1 byte
4 bytes
22
4 bytes
int a;
int m=22;
int
float num
float
num
4 bytes
float
num1
4 bytes
9.67
Copyright
C Programming
Page 21
Defining Data
The definition:
char var; defines a variable location called var, which is
one byte in size, and can therefore hold only one character.
To define a memory location that can store characters in
contiguous locations as in a name, and addressable by one
variable name, you would need to use the following
definition:
char name[10];
The above definition defines a memory location called
name containing 10 contiguous bytes for storing up to 9
valid characters.
Copyright
C Programming
Page 22
Copyright
C Programming
Page 23
Input/Output Functions
C supports Input/Output operations through functions
written in C, and that are part of the standard C library
along with other functions.
These input/output functions may be incorporated into any
program by a programmer.
Any input or output operation happens as a stream of
characters. The standard I/O functions are available for
character-based I/O, or for string-based I/O.
Copyright
C Programming
Page 24
Buffered I/O
The standard I/O functions are buffered, i.e., each device
has an associated buffer through which any input or output
operation takes place.
After an input operation from the standard input device has
occurred, care must be taken to clear the standard input
buffer. Otherwise, the previous contents of the buffer may
interfere with subsequent input.
After an output operation, the buffer need not be cleared
since subsequent output data will flush the previous buffer
contents.
Copyright
C Programming
Page 25
Character-Based I/O
The function getch( ) is used to accept a character from
standard input. By default, it accepts characters from the
keyboard, and returns the character input from the
keyboard.
The function putch( ) displays the character input on to
standard output. It takes one argument, namely, the
character to be output.
The function fflush( ) clears the buffer associated with the
particular device.
Copyright
C Programming
Page 26
Copyright
C Programming
Page 27
Character-Based I/O
The function getchar( ) by default accepts a character from
the keyboard. Hence, it does not need any parameters.
The function putchar( ) is used to display the character on
to standard output. It takes the character to be output as an
argument.
Copyright
C Programming
Page 28
Copyright
C Programming
Page 29
String-Based I/O
The function gets( ) accepts as a parameter, a string
variable, or a string literal (enclosed in double quotes)
from the keyboard.
The function puts( ) accepts a string variable, or a string
literal to be displayed to standard output.
After displaying the output, the puts( ) function causes the
cursor to be positioned at the beginning of the next line.
Copyright
C Programming
Page 30
String-Based I/O
#include <stdio.h>
main( )
{
char str[11];
puts(Enter a string of maximum 10 characters);
gets(str);
fflush(stdin);
puts(str);
}
Copyright
C Programming
Page 31
Conditional Constructs
The C language provides different conditional constructs
for evaluating a condition in a program.
The relational operators required for evaluating the
conditions are similar to those in other third-generation
languages, though the symbols are different.
Copyright
C Programming
Page 32
Conditional Constructs
Relational Operators:
Operator
Meaning
==
Equal to
!=
Not equal to
<
Less than
>
Greater than
<=
>=
Copyright
C Programming
Page 33
start
ch =
Input ch
is ch = *
Print *
Not a *
stop
Copyright
C Programming
Page 34
Copyright
C Programming
Page 35
Copyright
C Programming
Page 36
char chr;
chr = getchar( );
if (chr = = 0)
else if (chr = = 1)
Copyright
C Programming
Page 37
else if (chr = = 3)
puts(You entered the number 3);
else if (chr = = 4)
puts(You entered the number 4);
else if (chr = = 5)
puts(You entered the number 5);
else if (chr = = 6)
puts(You entered the number 6);
else if (chr = = 7)
puts(You entered the number 7);
else if (chr = = 8)
puts(You entered the number 8);
else if (chr = = 9)
puts(You entered the number 9);
Else
puts(You did not enter a number);
}
Copyright
C Programming
no
yes
no
yes
no
yes
Page 38
Nested if Construct
A nested if statement is
encountered if the
statement to be executed
after a condition evaluates
to true is another if
statement.
Both the outer if statement
and the inner if statement
have to evaluate to true for
the statement following the
inner if condition to be
executed.
Copyright
C Programming
no
ye
s
ye
s
no
Page 39
if (ch <= Z)
if (inp <= z)
Copyright
C Programming
Page 40
else
else
else
Copyright
C Programming
Page 41
#include< stdio.h>
main( )
{
char ch;
ch = getchar( );
fflush(stdin);
if (ch >= A)
{
if (ch <= Z)
puts (Its an Uppercase alphabet);
else if (ch >= a)
{
if (inp <= z)
puts (Its a lowercase alphabet);
else
puts (Input character > z);
}
Copyright
C Programming
Page 42
else
puts (Input character greater than Z but less than a);
}
else
puts (Input character less than A);
}
Copyright
C Programming
Page 43
Copyright
C Programming
Page 44
Copyright
C Programming
Page 45
C Programming
Page 46
char chr;
chr = getchar( );
fflush (stdin);
Copyright
C Programming
Page 47
switch ( chr)
{
case 0
case 1
case 2
case 3
case 4
case 5
case 6
Copyright
C Programming
Page 48
case 7
case 8
case 9
default
}
}
Copyright
C Programming
Page 49
Evaluate Condition
true
C Programming
false
Page 50
#include <stdio.h>
/* function to accept a string and display it 10 times
main( )
{
int counter=0;
char message[10];
gets( message);
fflush( stdin);
while (counter <= 9)
{
puts( message);
counter = counter + 1;
gets( message);
fflush (stdin)
}
}
Copyright
C Programming
Page 51
Evaluate Condition
true
Copyright
C Programming
Page 52
false
Copyright
C Programming
Page 53
Copyright
C Programming
Page 54
Copyright
C Programming
Page 55
#include <stdio.h>
/* this function displays a message 10 times */
main( )
{
int i;
for( i = 0; i <= 9; i = i + 1)
{
puts( message);
}
}
Copyright
C Programming
Page 56
Copyright
C Programming
Page 57
Copyright
C Programming
Page 58
Summary
In this session, you learnt to:
Describe the evolution of the C programming language
Describe C as a second-generation as well as a thirdgeneration language
State the data types in C
Write simple C functions for input and output
Write C functions that employ conditional constructs
Write C functions that employ iterative constructs
Copyright
C Programming
Page 59
Copyright
C Programming
Page 60
SESSION 2
Copyright
C Programming
Page 61
Objectives
In this session, you will learn to:
Write compound conditions employing the logical
operators
Write functions that perform formatted input/output
Declare, initialize, manipulate, and address onedimensional arrays
Copyright
C Programming
Page 62
Operator
Notation
NOT
AND
&&
OR
||
Copyright
C Programming
Page 63
C Programming
Page 64
Copyright
C Programming
Page 65
Copyright
C Programming
Page 66
Copyright
C Programming
Page 67
C Programming
Page 68
C Programming
Page 69
Logical Expressions
a && b
a || b
Copyright
C Programming
Page 70
Formatted I/O
Copyright
C Programming
Page 71
Formatted Output
The function printf( ) is used for formatted output to
standard output based on a format string.
The format string, along with the data to be output, are the
parameters to the printf( ) function.
The syntax of the printf( ) function is:
printf( format string, var1,var2..)
Format string is a string containing the format
specification introduced by the character %, and ended by
a conversion character.
Copyright
C Programming
Page 72
Formatted Output
An example:
printf(%c\n, var);
The conversion characters and their meanings are:
Conversion character
Copyright
Meaning
C Programming
Page 73
Formatted Output
Between the % character and the conversion character, there may be:
A minus sign
A digit
A period
A digit
To signify that the data item is a long integer, and not an integer.
Copyright
C Programming
Page 74
Formatted Output
Format String
Data
Output
%2d
| 4|
%2d
224
|224|
%03d
|008|
%-2d
|4 |
%5s
Sherlock Holmes
| Sherlock Holmes|
%15s
Sherlock Holmes
| Sherlock Holmes |
%-15s
Sherlock Holmes
| Sherlock Holmes |
%f
22.44
|22.440000|
Copyright
C Programming
Page 75
#include<stdio.h>
main( )
{
int number = 97;
printf(Value of num is %d\n, number);
printf(The Character equivalent of %d is %c\n, number, number);
}
Copyright
C Programming
Page 76
Formatted Input
The function scanf( ) is used for formatted input, and
provides many of the conversion facilities of printf( ).
The syntax of the function scanf( ) is:
scanf( format string, var1, var2.)
The scanf( ) function reads and converts characters from
standard input according to the format string, and stores
the input in memory locations specified by the other
arguments.
Copyright
C Programming
Page 77
Formatted Input
#include<stdio.h>
main( )
{
char name[10];
int age;
char gender;
scanf (%s%c%d, name, &gender, &age);
fflush(stdin);
printf( % s %c %d, name, gender, age);
Copyright
C Programming
Page 78
#include<stdio.h>
main( )
{
char string[40];
printf(Enter a string of maximum 39 characters);
scanf(%s, string);
fflush(stdin);
printf(%s, string);
}
Copyright
C Programming
Page 79
One-Dimensional Arrays
An array can be defined as a collection of elements of
identically typed data items that are stored contiguously in
memory.
Each array element shares the same name as the array
name, but distinguishes itself from other elements in the
array using a subscript, or an index.
The subscript or the index of each array element is
determined based on the number of offset positions it
Copyright
C Programming
Page 80
Array Representation
The declaration int a[10]; defines an array a of size 10, as a block of 10
contiguous elements in memory.
a[0]
a[1]
Copyright
a[2]
a[3] a[4]
a[5] a[6]
C Programming
a[7] a[8]
a[9]
Page 81
Character Arrays
To define a character array for storing a string of n characters, we
would need to define a character array of size n+1 characters.
This is because all character arrays are terminated by a NULL
character (\0).
To define a character array called name for storing a ten-character
name, we will define the array as:
Char name[11];
where name[0] through name[9] will contain the characters
comprising the name, and name[10] will store the NULL character.
Copyright
C Programming
Page 82
name
name[0]
name[1]
name[2]
name[3]
name[4]
name[5]
name[6]
name[7]
Copyright
C Programming
i
name[8]
\0
name[9]
name[10]
Page 83
Array Initialization
Since an array is a set of elements located at contiguous
memory locations, its initialization involves moving
element by element, or one data at a time into the array.
An array is initialized by specifying each element in an
initialization list separated by commas.
The size of the array, in this case, may or may not be
specified. The number of elements stored in the array
determines its size.
Copyright
C Programming
Page 84
#include<stdio.h>
main( )
{
char array1[ ] = {A, R, R, A, Y, \0};
char array2[ ] = {ARRAY};
char dayofweek[ ] = {M, T, W, T, F, S, S, \0};
float values[ ] = {100.56, 200.33, 220.44, 400.22, 0};
}
Copyright
C Programming
Page 85
Array Processing
#include<stdio.h>
main( )
{
char array1[ ] = {A, R, R, A, Y, \0};
char array2[ ] = {ARRAY};
char dayofweek[ ] = {M, T, W, T, F, S, S, \0};
float values[ ] = {100.56, 200.33, 220.44, 400.22, 0};
int i = 0;
printf( String 1 is %s\n, array1);
printf( String 2 is %s\n, array2);
for( i = 0; dayofweek[i] != \0; i = i +1)
printf ( The Day %d in a week is %c\n, i + 1, dayofweek[i];
for( i = 0; values[i] != 0; i = i +1)
printf ( The amount %d in a week is %f\n, i + 1, values[i];
}
Copyright
C Programming
Page 86
Copyright
C Programming
Page 87
char array[11];
gets(array);
fflush(stdin);
Copyright
C Programming
Page 88
Copyright
C Programming
Page 89
Copyright
C Programming
Page 90
/* function to extract a substring from a main string starting at a specified position, and
containing a specified number of characters */
main( )
{
int i, start_pos, no_of_chars;
char string[101], substring[101];
printf(Enter a string of upto 100 characters\n);
gets(string);
fflush( stdin);
printf(Enter start position, and no. of characters to extract\n);
scanf(%d,%d, &start_pos, &no_of_chars);
fflush(stdin);
start_pos = start_pos -1;
for (i = 0; i < no_of_chars; i = i + 1, start_pos = start_pos + 1)
{
substring[i] = string[sp];
}
substring[i] = \0;
printf(The substring is %s\n, substring);
}
Copyright
C Programming
Page 91
/* the following function accepts numbers as long as 0 is not entered as an array element, and displays
the sum of the numbers in the array along with the array elements */
main( )
{
int total, int_array[20], i = -1;
do
{
i = i + 1;
printf(Enter number %d (0 to terminate)\n);
scanf(%d, &int_array[i]);
}while (int_array[i] != 0);
i = 0;
while (int_array != 0)
{
printf(Element number %d is %d\n, i + 1, int_array[i]);
total = total + int_array[i];
}
printf(The sum of the numbers in the array is %d \n, total);
}
Copyright
C Programming
Page 92
Array Addressing
In the declaration:
char string[11];
the name of the array refers to the starting address of the
area that gets allocated for storing the elements of the array.
Thus, string contains the address of string[0].
In the aforesaid declaration, string refers to the starting
position of the array, and the subscript refers to the offset
position from the starting position.
Copyright
C Programming
Page 93
Array Addressing
string
100
100
101
102
103
Copyright
104
105
106
107
108
109
110
\0
10
C Programming
Page 94
Array Addressing
In the previous declaration, string represents the starting
point of the array, and the subscript refers to the offest
position from the starting point.
To arrive at the address of the particular element, the
compiler applies the following simple formula:
starting address of the array + ( offset position * size of data
type)
Address of element 4 = 100 + ( 3 * 1) = 100 +3 = 103
Copyright
C Programming
Page 95
Summary
Copyright
C Programming
Page 96
Copyright
C Programming
Page 97
Session 3
Copyright
C Programming
Page 98
Objectives
In this session, you will learn to:
Apply the unary, binary, ternary, compound assignment
operators, increment/decrement operators
Use character arithmetic and understand the rules of
conversion between different data types
Declare, initialize, manipulate and print from a twodimensional array
Copyright
C Programming
Page 99
Unary Operators
Unary operators, as the name suggests, works on one operand
or variable.
The ++ and the -- operators are examples of unary operators.
When these operators prefix an operand, they are referred to as
prefix operators, and when they are suffixed to an operand,
they are referred to as postfix operators.
Prefix and postfix operators, when used in an expression, can
have totally different results, and hence it is necessary to know
their workings.
Copyright
C Programming
Page 100
Unary Operators
Incrementing and decrementing by 1 is such a ubiquitous
operation that C offers the prefix and postfix implementations
of the ++ and the -- operators.
The expression i = i + 1; can also be written as i++.
When used as a standalone statement, writing i++, or ++i does
not make any difference at all.
It is only when they are used as part of an expression that the
prefix and the postfix operators can have totally different
results.
Copyright
C Programming
Page 101
Unary Operators
Consider the following two statements:
total = i++;
total = ++i;
Copyright
C Programming
Page 102
Unary Operators
Copyright
C Programming
Page 103
Binary Operators
Binary operators as the name suggests, works on two
operands.
The binary operators in C (as in other programming
languages) are:
Copyright
C Programming
Page 104
Binary Operators
Copyright
C Programming
Page 105
Type Conversions
When an operator has operands of different types, they are
converted to a common type according to a small number
of rules.
In general, the only automatic conversions are those that
convert a ``narrower' operand into a ``wider'' one without
losing information, such as converting an integer into
floating point
Copyright
C Programming
Page 106
Type Conversions
Expressions that might lose information, like assigning a longer
integer type to a shorter, or a floating-point type to an integer, may
draw a warning, but they are not illegal.
A char is just a small integer, so chars may be freely used in
arithmetic expressions. This permits considerable flexibility in
certain kinds of character transformations.
Implicit arithmetic conversions work much as expected. In general,
if an operator like + or * that takes two operands (a binary
operator) has operands of different types, the lower'' type is
promoted to the ``higher'' type before the operation proceeds.
Copyright
C Programming
Page 107
Type Conversion
The following informal set of rules will suffice:
If either operand is long double, convert the other to long double.
Otherwise, if either operand is double, convert the other to
double.
Otherwise, if either operand is float, convert the other to float.
Otherwise, convert char and short to int.
Then, if either operand is long, convert the other to long.
Conversions take place across assignments; the value of the
right side is converted to the type of the left, which is the type
of the result.
Copyright
C Programming
Page 108
Type Conversions
In the aforesaid assignment, the data type on the right (char) is converted
to the data type on the left (int) which is the type of the result.
If x is float and i is int, then x = i and i = x both cause conversions; float
to int causes truncation of any fractional part. When a double is
converted to float, whether the value is rounded or truncated is
implementation dependent.
Copyright
C Programming
Page 109
Copyright
C Programming
Page 110
Copyright
C Programming
Page 111
C Programming
Page 112
Ternary Operators
if (a > b)
z = a;
else
z = b;
Copyright
C Programming
Page 113
Ternary Operators
If it is non-zero (true), then the expression expr2 is
evaluated, and that is the value of the conditional
expression.
Otherwise expr3 is evaluated, and that is the value. Only
one of expr2 and expr3 is evaluated.
Thus to set z to the maximum of a and b,
z = (a > b) ? a : b; /* assign z the maximum of a and b */
Copyright
C Programming
Page 114
Copyright
C Programming
Page 115
Copyright
C Programming
Page 116
Two-Dimensional Arrays
While a one-dimensional array can be visualized in onedimension as either a row of elements, or a column of
elements, a two-dimensional array needs to be visualized
along two dimensions, i.e., along rows and columns.
To be precise, a two-dimensional array can be represented
as an array of m rows by n columns.
A general way of representing or visualizing a twodimensional array is in the form of a two-dimensional grid.
But, in memory, even a two-dimensional array is arranged
contiguously as an array of elements.
Copyright
C Programming
Page 117
Two-dimensional Arrays
col 0
col 1
col 2
row 0
row 1
row 2
r0,c0
r0,c1
Copyright
r0,c2
r1,c0
r1,c1
C Programming
r1,c0
r2,c0
r2,c1
r2,c2
Page 118
Two-Dimensional Arrays
The Scenario: Consider a situation where you want to
record the region-wise, product-wise figures of sales. The
regions are A, B and C. The products are X, Y and Z
Sales data for the region-wise, product-wise breakup
should be shown as follows:
Copyright
C Programming
Page 119
Two-Dimensional Arrays
Prod X
Prod Y
Prod Z
reg A
reg B
reg C
Copyright
C Programming
Page 120
C Programming
Page 121
0, 0, 0,
0, 0, 0
};
To improve the legibility of the initialization, it can be
written as: int rp_array[3][3] = { {0,0, 0},
{0, 0, 0},
{0, 0, 0}
};
Copyright
C Programming
Page 122
rp_array[r_counter][p_counter] = 0;
Copyright
C Programming
Page 123
r_counter + 1, p_counter + 1)
scanf(%d, &rp_array[r_counter][p_counter]);
fflush( stdin);
Copyright
C Programming
Page 124
/* Program for converting these sales figures into percentages of total sales. */
main( )
{
int r_counter, p_counter, rp_array[3][3], total_sales = 0;
float rp_array_perc[3][3];
/* initialization of rp_array using the for loop */
for (r_counter = 0; r_counter < 3; r_counter ++)
{
for (p_counter = 0; p_counter < 3; p_counter ++)
{
rp_array[r_counter][p_counter] = 0;
}
}
Copyright
C Programming
Page 125
r_counter + 1, p_counter + 1)
scanf(%d, &rp_array[r_counter][p_counter]);
fflush( stdin);
Copyright
C Programming
Page 126
total_sales += rp_array[r_counter][p_counter];
Copyright
C Programming
Page 127
rp_array[r_counter][p_counter] ) / total_sales ;
}
} /* end of main( ) */
Copyright
C Programming
Page 128
C Programming
Page 129
The #define constitutes the preprocessor phase, wherein the value/s specified as
part of the macro or #define is substituted into the code prior to compilation. This is
also known as macro substitution.
#include <stdio.h>
#define RG 3
#define PR 3
main( )
{
int r_counter, p_counter, rp_array[RG][PR], total_sales = 0;
float rp_array_perc[RG][PR];
/* initialization of rp_array using the for loop */
for (r_counter = 0; r_counter < RG; r_counter ++)
{
for (p_counter = 0; p_counter < PR; p_counter ++)
{
rp_array[r_counter][p_counter] = 0;
}
}
Copyright
C Programming
Page 130
Copyright
C Programming
Page 131
Virendra Sehwag,
Rahul Dravid
Sachin Tendulkar,
V.V.S. Laxman,
Yuvraj Singh,
Ajit Agarkar,
Parthiv Patel,
Anil Kumble,
L. Balaji,
Irfan Pathan
};
Copyright
C Programming
Page 132
Virendra Sehwag,
Rahul Dravid
Sachin Tendulkar,
V.V.S. Laxman,
Yuvraj Singh,
Ajit Agarkar,
Parthiv Patel,
Anil Kumble,
L. Balaji,
Irfan Pathan
};
Copyright
C Programming
Page 133
printf(%s, team_india[i]);
}
Particular elements can also be printed from a two dimensional array
by using the second subscript.
Printf(%c, team_india[10][6] would print the character P from the
string Pathan
Copyright
C Programming
Page 134
Copyright
C Programming
Page 135
Session 4
Copyright
C Programming
Page 136
Pointers
Copyright
C Programming
Page 137
Objectives
At the end of this session, you should be able to:
Declare, initialize, and manipulate pointers
Use pointers for manipulating one-dimensional and twodimensional arrays
Distinguish between arrays and pointers
Use pointer arithmetic
Copyright
C Programming
Page 138
Pointer Definition
When a variable is declared (such as int i = 22) in a
program, space is reserved in memory for the variable i.
To be precise, each variable is assigned a particular
memory location referenced by its address.
In our case, the integer i would be stored at a specific
memory location having the address, say, 1000 (addresses
are typically hexadecimal values).
The declaration of i can be conceptualized as follows:
Copyright
C Programming
Page 139
Pointer Definition
i
22
1000
variable name
value
address
Copyright
C Programming
Page 140
Pointer Definition
In C, it is possible to manipulate a variable either by its
name, or by its address. The address of a variable can be
stored in another variable (called a pointer variable), and
access can be had to the variable through this pointer
variable.
A pointer can therefore be defined as a variable that
holds the address of another variable.
If you want to define a pointer to hold the address of an
integer variable, then you must define the pointer as a
pointer to an integer.
Copyright
C Programming
Page 141
C Programming
Page 142
C Programming
Page 143
pointer_to_an_integer
1000
Copyright
variable name
22
variable value
1000
C Programming
variable address
Page 144
Dereferencing a Pointer
Returning the value pointed to by a pointer is known as
pointer dereferencing. To deference the contents of a
pointer, the * operator is used.
#include<stdio.h>
main( )
{
int x, y, *pointer;
x = 22;
pointer = &x;
y = *pointer; /* obtain whatever pointer is pointing to */
}
Copyright
C Programming
Page 145
Copyright
C Programming
Page 146
variable name
pointer1
22
variable value
1000
1000
variable address
pointer2
1000
Copyright
C Programming
Page 147
Copyright
C Programming
Page 148
1000
22
p2
y
44
2000
pointer1
1000
44
pointer2
1000
Copyright
44
C Programming
Page 149
Copyright
C Programming
Page 150
C Programming
Page 151
Copyright
C Programming
Page 152
Copyright
C Programming
Page 153
C Programming
Page 154
C Programming
Page 155
Copyright
C Programming
Page 156
Copyright
C Programming
Page 157
C Programming
Page 158
Pointer Arithmetic
The most common arithmetic operation using pointers is
incrementing by 1. Consider the following statement:
char *p = Sherlock H;
printf(%s\n, p);
The initialization of the character pointer with the string
Sherlock H can be visualized as shown in the following
slide.
Copyright
C Programming
Page 159
Pointer Arithmetic
p
100
100
101
102
103
Copyright
104
105
106
107
C Programming
108
109
110
\0
10
Page 160
Pointer Arithmetic
Now, let us increment the pointer p by 1, as in:
p++;
p initially pointed to the base address of the string
Sherlock H, i.e., 100.
After incrementing the pointer p by 1, it points to the next
element in the string or the character array, i.e., character
h after S.
p now contains the address of the element h, i.e., 101
Copyright
C Programming
Page 161
Pointer Arithmetic
p
101
100
101
102
103
Copyright
104
105
106
107
C Programming
108
109
110
\0
10
Page 162
Pointer Arithmetic
But will the statement p++; always make p point to the
next memory location.
The answer is an emphatic No.
This depends upon the data type that p is pointing to.
Copyright
C Programming
Page 163
Pointer Arithmetic
p
100
100
4
Copyright
104
8
108
12
C Programming
Page 164
Pointer Arithmetic
Copyright
104
8
108
12
C Programming
Page 165
Pointer Arithmetic
The key point to note is that when pointers are
incremented by 1, the size of the data type to which it is
pointing to (4 bytes in our case, since an integer needs 4
bytes of storage) is taken into account.
To summarize, the operation p++; will result in the
following computation:
New address of p = old address of p + size of data type
Copyright
C Programming
Page 166
Pointer Arithmetic
Consider the following declaration of a two-dimensional
integer array:
int p[3][5] = {
{ 2, 4, 6, 8, 10},
{ 3, 6, 9, 12, 15},
};
The aforesaid declaration declares an array of three integer
pointers, each pointing to the first element of an array of 5
integers. This can be visualized as follows:
Copyright
C Programming
Page 167
Pointer Arithmetic
p
100
100
104
108
200
200
300
400
Copyright
204
208
212
216
10
300
304
308
312
316
12
15
400
404
408
412
416
20
25
C Programming
10
15
Page 168
Pointer Arithmetic
Here, p points to the first element of the array of pointers.
*p equals p[0], i.e., it returns the address 200. This address
points to the element at offset [0,0], i.e., element 2.
Therefore, *(*p) returns the value 2.
Since p is a pointer to another pointer, incrementing p by 1
makes it point to the next element in the array of pointers,
i.e., it now points to the element containing the address
300.
Copyright
C Programming
Page 169
Pointer Arithmetic
Hence, *(p + 1) returns the address 300.
Therefore, * (*(p + 1)) returns the value at this address,
i.e., the element with the value 3. In other words, the
element at the offset [1,0].
The following table gives various pointer expressions, and
their values:
Copyright
C Programming
Page 170
Pointer Arithmetic
Pointer
Expression
Resulting
Address
Variable
Value
*(*p)
200
p[0][0]
*(*p+1)
204
p[0][1]
*(*(p + 1))
300
p[1][0]
*(*(p+1)+1)
304
p[1][1]
*(*(p+1)+1)+1
304
p[1][1] + 1
6+1=7
Copyright
C Programming
Page 171
Copyright
C Programming
Page 172
Copyright
C Programming
Page 173
Summary
In this session, you learnt to:
Declare, initialize, and manipulate pointers
Use pointers for manipulating one-dimensional and twodimensional arrays
Distinguish between arrays and pointers
Use pointer arithmetic
Copyright
C Programming
Page 174
Copyright
C Programming
Page 175
Session 5
Copyright
C Programming
Page 176
Objectives
In this session, you will learn to:
Write programs that invoke functions through a:
Call by value
Call by reference
C Programming
Page 177
Advantages of Function
Functions facilitate the factoring of code. Every C program
consists of one main( ) function typically invoking other
functions, each having a well-defined functionality.
Functions therefore facilitate:
Reusability
Procedural abstraction
C Programming
Page 178
Function Parameters
Function parameters are defined as part of a function
header, and are specified inside the parentheses of the
function.
The reason that functions are designed to accept
parameters is that you can embody generic code inside the
function.
All that would be required by the function would be the
values that it would need to apply the generic code on the
values received by it through its parameters.
Copyright
C Programming
Page 179
Function Parameters
Consider the following printf( ) statement:
printf(%d, i);
This is actually a call to the printf( ) function with two
pieces of information passed to it, namely, the format
string that controls the output of the data, and the variable
that is to be output.
The format string, and the variable name can be called the
parameters to the function printf( ) in our example.
Copyright
C Programming
Page 180
Function Parameters
Function parameters are therefore a mechanism wherein
values can be passed down to a function for necessary
processing, and the processed value returned back from the
function, as the case may be.
It is important to remember that not all function need be
defined to accept parameters, though most functions do.
This brings us now to the important concept of a
function returning a value, and also the return type of a
function.
Copyright
C Programming
Page 181
Invoking Functions
In C, functions that have parameters are invoked in one of
two ways:
Call by value
Call by reference
Copyright
C Programming
Page 182
Call by Value
void swap(int,int );
main()
{ int a=10, b=20;
swap(a, b);
printf( %d %d \n,a,b);
}
void swap (int x, int y)
{ int temp = x;
x= y;
y=temp;
}
Copyright
C Programming
Page 183
Call by Value
In the preceding example, the function main( ) declared and initialized
two integers a and b, and then invoked the function swap( ) by
passing a and b as arguments to the function swap( ).
The function swap( ) receives the arguments a and b into its
parameters x and y. In fact, the function swap( ) receives a copy of
the values of a and b into its parameters.
The parameters of a function are local to that function, and hence, any
changes made by the called function to its parameters affect only the
copy received by the called function, and do not affect the value of the
variables in the called function. This is the call by value mechanism.
Copyright
C Programming
Page 184
Call by Reference
Call by reference means that the called function should be
able to refer to the variables of the calling function directly,
and not create its own copy of the values in different
variables.
This would be possible only if the addresses of the
variables of the calling function are passed down as
parameters to the called function.
In a call by reference, therefore, the called function directly
makes changes to the variables of the calling function.
Copyright
C Programming
Page 185
Call by Reference
Consider the same swap( ) that we discussed earlier now rewritten using
a call by reference.
void swap( int *, int *);
main()
{ int a=10, b=20;
swap(&a, &b);
printf( %d %d \n,a,b);
}
void swap (int *x, int *y)
{ int temp=*x;
*x=*y;
*y=temp;
}
Copyright
C Programming
Page 186
C Programming
Page 187
Copyright
C Programming
Page 188
fflush(stdin);
Copyright
C Programming
Page 189
return (a + b);
}
In the aforesaid example, the function add( ) sends back the value of
the expression (a + b) to the function main( ). The value returned to
main( ) from add( ) is stored in the variable value which appears on the
left hand side of the statement in which the function add( ) is called.
Copyright
C Programming
Page 190
Copyright
C Programming
Page 191
Function Prototype
C assumes that a function returns a default value of int if
the function does not specify a return type.
In case a function has to return a value that is not an
integer, then the function itself has to be defined of the
specific data type it returns.
Consider the following code:
#include <stdio.h>
main( )
{
Copyright
C Programming
Page 192
Function Prototype
Functions should be declared before they are used.
Consider the situation where you want to use the pow( )
function, called the power function, one of many functions
in the mathematics library available for use by the
programmer.
A function call such as pow(x, y) returns the value of x
raised to the power y.
To elucidate further, pow(2.0, 3.0) yields the value 8.0
Copyright
C Programming
Page 193
Function Prototype
The declaration of the function is given by:
double pow( double x, double y);
Function declarations of this type are called function
prototypes.
An equal function prototype is given by:
double pow( double, double);
Copyright
C Programming
Page 194
Function Prototype
A function prototype tells the compiler the number and
data types of arguments to be passed to the function and
the data type of the value that is to be returned by the
function.
ANSI C has added the concept of function prototypes to
the C language.
Copyright
C Programming
Page 195
Function Prototype
return (a + b);
}
Copyright
C Programming
Page 196
Function Prototype
#include <stdio.h>
main( )
{
void add( float, float);
float i, j, value;
scanf(%f %f, &i, &j);
fflush(stdin);
add(i, j);
printf( the total is %d\n, value);
}
Copyright
C Programming
Page 197
Function Calls
It is important for us to know what happens under the hood when a
function executes.
A logical extension of the aforesaid point is the situation that arises
when a function calls another function.
It is important to know how the CPU manages all this, i.e., knowing
where to look for when a function call is encountered, and having
executed the function, to also know where it has to return to.
In short, we need to know the call mechanism, and the return
mechanism.
Copyright
C Programming
Page 198
Copyright
C Programming
Page 199
Copyright
C Programming
Page 200
C Programming
Page 201
Copyright
C Programming
Page 202
Code Area
Entry point for procedure 1
Entry point for procedure 2
Code for
Procedure 1
Code for
Procedure 2
.
.
Code for
Procedure n
Copyright
C Programming
Page 203
Data Area
small part of data can be assigned fixed locations before
execution begins
Global and/or static data
Compile-time constants
Large integer values
Floating-point values
Literal strings
Copyright
C Programming
Page 204
Dynamic Memory
The memory area for the allocation of dynamic data can be
organized in many different ways.
A typical organization divides the dynamic memory into
stack area (LIFO protocol)
heap area
Copyright
C Programming
Page 205
Memory Organization
code area
global/static area
stack
free
free space
space
heap
Copyright
C Programming
Page 206
A Procedure Activation
Record or a Stack Frame
arguments
bookkeeping information
(return address)
C Programming
local data
local temporaries
Page 207
Registers
Registers may be used to store temporaries, local variables,
or even global variables.
When a processor has many registers, the entire static area
and whole activation records may be kept in the registers.
Special purpose registers:
Program counter (PC)
Stack pointer (SP)
Copyright
C Programming
Page 208
Calling Sequence
The calling sequence is the sequence of operations that
must occur when a procedure or function is called.
Allocation of memory for the activation record
The computation and storing the arguments
Storing and setting registers
Copyright
C Programming
Page 209
Return Sequence
The return sequence is the sequence of operations needed
when a procedure or function returns.
The placing of the return value where it can be
accessed by the caller
Readjustment of registers
Releasing of activation record memory
Copyright
C Programming
Page 210
C Programming
Page 211
C Programming
Page 212
Global Procedures
In a language where all procedures are global (the C
language), a stack-based environment requires two things:
1. A pointer to the current activation record to allow access to local
variables.
This pointer is called the frame pointer (fp) and is usually kept in a
register.
Copyright
C Programming
Page 213
int z;
main( )
{
int x;
fn_a( );
.. .
.
.
.
}
return instruction
fn_a( int m )
fn_b( int n )
{
int y;
int b;
fn_b( );
..
..
return instruction
Copyright
C Programming
Page 214
S
t
a
c
k
G
r
o
w
t
h
x
m
y
control link
return address
fp
sp
Copyright
n
control link
return address
b
C Programming
Page 215
Access to Variables
In static environment, parameters and local variables can
be accessed by fixed addresses.
In a stack-based environment, they must be found by offset
from the current frame pointer.
In most languages, the offset for each local variable is still
statically computable by compiler.
The declarations of a procedure are fixed at compile time and the
memory size to be allocated for each declaration is fixed by its
data type.
Copyright
C Programming
Page 216
Calling Sequence
1. Compute the arguments and store them in their correct
positions in the new activation record (pushing them in
order onto the runtime stack)
2. Store (push) the fp as the control link in the new
activation record.
3. Change the fp so that it points to the beginning of the new
activation record (fp=sp)
4. Store the return address in the new activation record.
5. Jump to the code of the procedure to be called.
Copyright
C Programming
Page 217
Return Sequence
1.
2.
3.
4.
Copyright
C Programming
Page 218
Variable Length-Data
Two examples:
Copyright
C Programming
Page 219
C Programming
Page 220
Local Temporaries
Local temporaries are partial results of computations that
must be saved across procedure calls.
Example:
x[i]=(i+j)*(i/k+f(i));
Three partial results need to be saved: the address of x[i], the sum
i+j, and the quotient i/k.
Copyright
C Programming
Page 221
Nested Declarations
Nested declarations can be treated in a similar way to temporary expressions, allocating them
on the stack as the block is entered and deleting them on exit.
}
{ double x; // block B
int j;
}
{ char *a; // block C
int k;
}
}
Copyright
C Programming
Page 222
C Programming
Page 223
Command-Line Arguments
The function main( ) can receive arguments from the
command line.
Information can be passed to the function main( ) from the
operating system prompt as command line arguments.
The command line arguments are accepted into special
parameters to main( ), namely, argc and argv. Their
declarations are as follows:
main(int argc, char * argv[ ])
Copyright
C Programming
Page 224
C Programming
Page 225
C Programming
Page 226
Command-Line Arguments
argv
argc = 3
100
argv[0]
argv[1]
200
n \
o l
u p p
300
S
Copyright
C Programming
s \0
Page 227
Copyright
C Programming
Page 228
Storage Qualifiers
The storage qualifier determines the lifetime of the storage
associated with the identified variable.
A variable also has a scope, which is the region of the
program in which it is known.
C Programming
Page 229
automatic Variables
automatic variables are local to a block, and are discarded
on exit from the block.
Block implies a function block, a conditional block, or an
iterative block.
Declarations within a block create automatic variables if
no storage class specification is mentioned, or if the auto
specifier is used.
Variable declarations, therefore, are by default, auto.
Copyright
C Programming
Page 230
automatic Variables
#include<stdio.h>
main( )
{
char var;
while ((var = getchar( )) != *)
{
if ((var >= A) && (var <= Z))
{
uppercase_count( );
}
}
}
uppercase_count( )
{
auto int counter = 0;
counter ++;
}
Copyright
C Programming
Page 231
Global Variables
Global variable is defined outside all functions.
A typical convention of defining global variables is before
the main( ) function.
A variable declared as global is visible to the function
main( ) as well as to any other functions called from main( ).
A variable defined as global has file scope, that is, it is
visible to all the functions written within the scope of a
program file.
Copyright
C Programming
Page 232
Global Variables
/* A sample C program */
# include <stdio.h>
int sum( ); /* function prototype */
int a=10, b=20; /* a and b are global variables, visible to main( ) as well as to sum( ) */
main()
{
int c;
c = sum();
printf(%d+%d = %d \n,a,b,c);
}
int sum()
{
return(a+b);
}
Copyright
C Programming
Page 233
Static Variables
Static variables may be local to a block or external to all
blocks, but in either case retain their values across exit
from, and reentry to functions and blocks.
Within a block, including a block that provides the code
for a function, static variables are declared with the
keyword static.
Let us rewrite the code for the example involving auto
variables to incorporate the declaration of static variables.
Copyright
C Programming
Page 234
Static Variables
#include<stdio.h>
main( )
{
char var;
while ((var = getchar( )) != *)
{
if ((var >= A) && (var <= Z))
{
uppercase_count( );
}
}
}
uppercase_count( )
{
static int counter = 0;
counter ++;
}
Copyright
C Programming
Page 235
Copyright
C Programming
Page 236
Extern Variables
Variables declared as extern are useful especially when
building libraries of functions.
This means that functions required to run a program can be
saved in separate program files, which can be compiled
separately, and linked up with the file containing the
function main( ) prior to running the program.
In such a case, if the functions use the same global
variables, then their declarations would involve the use of
the extern qualifier
Copyright
C Programming
Page 237
Extern Variables
Program a.c
int val /* global */
main( )
{
printf(Enter value);
scanf(%d, &val);
compute( ); /* function call
*/
}
Copyright
Program b.c
compute( )
{
extern int val; /* implies
that val is defined in
another program containing
a function to which the
current function will be
linked to at the time of
compilation */
}
C Programming
Page 238
Extern Variables
From the preceding example, it is clear that though val is
declared global in the function main( ) in program a.c, it
has been declared again within the function compute( ),
which is defined in its own program file, b.c.
However, the qualifier extern has been added to its
declaration.
The extern qualifier in the function compute( ) in b.c
indicates to the compiler (when a.c and b.c are compiled
together) that the variable used in this program file has
been declared in another program file.
Copyright
C Programming
Page 239
Implication
Example
Less than 0
i = strcmp(XYZ, xyz)
Greater than 0
i = strcmp(xyz, XYZ)
Equal to 0
i = strcmp(XYZ, XYZ)
Copyright
C Programming
Page 240
Copyright
C Programming
Page 241
Copyright
C Programming
Page 242
Copyright
C Programming
Page 243
Copyright
C Programming
Page 244
C Programming
Page 245
Copyright
C Programming
Page 246
Copyright
C Programming
Page 247
Summary
In this session, you learnt to:
Write programs that invoke functions through a:
Call by value
Call by reference
C Programming
Page 248
Copyright
C Programming
Page 249
Session 6
Copyright
C Programming
Page 250
File Input/Output
Copyright
C Programming
Page 251
Objectives
fseek( )
ftell( )
rewind( )
feof( )
Copyright
C Programming
Page 252
Files
A collection of logically related information
Examples:
An employee file with employee names, designation, salary etc.
A product file containing product name, make, batch, price etc.
A census file containing house number, names of the members,
age, sex, employment status, children etc.
Two types:
Sequential file: All records are arranged in a particular order
Random Access file: Files are accessed at random
Copyright
C Programming
Page 253
File Access
The simplicity of file input/output in C lies in the fact that
it essentially treats a file as a stream of characters, and
accordingly facilitates input/output in streams of characters.
Functions are available for character-based input/output, as
well as string-based input/output from/to files.
In C, there is no concept of a sequential or an indexed file.
This simplicity has the advantage that the programmer can
read and write to a file at any arbitrary position.
Copyright
C Programming
Page 254
File Access
The examples so far have involved reading from standard
input, and writing to standard output, which is the standard
environment provided by the operating system for all
applications.
You will now look at the process that a program needs to
follow in order to access a file that is not already
connected to the program.
Before a file can be read from, or written into, a file has to
be opened using the library function fopen( )
Copyright
C Programming
Page 255
File Access
The function fopen( ) takes a file name as an argument,
and interacts with the operating system for accessing the
necessary file, and returns a pointer of type FILE to be
used in subsequent input/output operations on that file.
This pointer, called the file pointer, points to a structure
that contains information about the file, such as the
location of a buffer, the current character position in the
buffer, whether the file is being read or written, and
whether errors, or end of file have occurred.
Copyright
C Programming
Page 256
File Access
This structure to which the file pointer point to, is of type
FILE, defined in the header file <stdio.h>.
The only declaration needed for a file pointer is exemplified
by:
FILE *fp;
FILE *fopen(char *name, char *mode);
fp = fopen( file name, mode);
Copyright
C Programming
Page 257
Access
Explanation
Copyright
C Programming
Page 258
Access
Explanation
Append mode
r+
Read + Write
mode
w+
Write + Read
mode
a+
Read +
Append mode
Copyright
C Programming
Page 259
Copyright
C Programming
Page 260
#include<stdio.h>
main( )
{
FILE *fp1, *fp2;
fp1 = fopen( source.dat, r);
fp2 = fopen( target.dat, w);
char ch;
while ( (ch = fgetc( fp1)) != EOF)
{
fputc (ch, fp2);
}
fclose(fp1);
fclose(fp2);
}
Copyright
C Programming
Page 261
#include<stdio.h>
main( )
{
char ch;
while ( (ch = fgetc( stdin)) != EOF)
{
fputc (ch, stdout);
}
}
Copyright
C Programming
Page 262
C Programming
Page 263
Copyright
C Programming
Page 264
printf(Error Message);
exit( );
}
Copyright
C Programming
Page 265
Copyright
C Programming
Page 266
Copyright
C Programming
Page 267
Copyright
C Programming
Page 268
Copyright
C Programming
Page 269
C Programming
Page 270
Copyright
C Programming
Page 271
Random Access
Input from, or output to a file is effective relative to a
position in the file known as the current position in the file.
For example, when a file is opened for input, the current
position in the file from which input takes place is the
beginning of the file.
If, after opening the file, the first input operation results in
ten bytes being read from the file, the current position in
the file from which the next input operation will take place
is from the eleventh byte position.
Copyright
C Programming
Page 272
Random Access
It is therefore clear that input or output from a file results
in a shift in the current position in the file.
The current position in a file is the next byte position from
where data will be read from in an input operation, or
written to in an output operation.
The current position advances by the number of bytes read
or written.
A current position beyond the last byte in the file indicates
end of file.
Copyright
C Programming
Page 273
Random Access
For example, when a file is opened for input, the current
position in the file from which input takes place is the
beginning of the file.
If, after opening the file, the first input operation results in
ten bytes being read from the file, the current position in the
file from which the next input operation will take place is
from the eleventh byte position.
This is sequential access, in which a file is opened, and you
start reading bytes from the file sequentially till end of file.
The same argument cab be extended to sequential write.
Copyright
C Programming
Page 274
Random Access
In sharp contrast to sequential access is random access that
involves reading from any arbitrary position in the file, or
writing to any arbitrary position in the file.
Random access therefore mandates that we must have a
mechanism for positioning the current position in the file
to any arbitrary position in the file for performing input or
output.
To facilitate this, C provides the fseek( ) function, the
prototype of which is as follows:
Copyright
C Programming
Page 275
The function fseek( ) is used for repositioning the current position in a file
opened by the function fopen( ).
Copyright
C Programming
Page 276
current offset
Copyright
C Programming
Page 277
current offset
Copyright
C Programming
Page 278
current offset
Copyright
C Programming
Page 279
current offset
Copyright
C Programming
Page 280
Copyright
C Programming
Page 281
Copyright
C Programming
Page 282
Copyright
salary
C Programming
Page 283
/* function to read the salary field (beginning at byte no. 5 and ending at
byte 10) for each record in the file, and increase it by 100 */
#include<stdio.h>
main( )
{
FILE *fp;
char empno[5], salary[7];
double fsalary, atof( );
long int pos = 4L, offset = 4L;
/* open the file SALARY.DAT in read-write mode */
if ((fp = fopen( SALARY.DAT, r+)) = = NULL)
{
printf(Error opening file SALARY.DAT);
exit( );
}
Copyright
C Programming
Page 284
Copyright
C Programming
Page 285
C Programming
Page 286
Summary
fseek( )
ftell( )
rewind( )
feof( )
Copyright
C Programming
Page 287
Copyright
C Programming
Page 288
Session 7
Copyright
C Programming
Page 289
Copyright
C Programming
Page 290
Objectives
In this session, you will learn to:
Trace down the genesis of user-defined data types
Declare user-defined data types, namely
Structures
Unions
Enumerations
C Programming
Page 291
C Programming
Page 292
Copyright
C Programming
Page 293
C Programming
Page 294
C Programming
Page 295
C Programming
Page 296
Declaring a Structure
The C language provides the struct keyword for declaring
a structure. The following is a structure declaration for
employee attributes.
struct empdata {
int empno;
char name[10];
char job[10];
float salary;
};
Copyright
C Programming
Page 297
Declaring a Structure
The keyword struct introduces a structure declaration,
which is a list of declarations enclosed in braces.
An optional name called a structure tag may follow the
word struct, as with employee in the previous example.
C Programming
Page 298
C Programming
Page 299
int empno;
char name[10];
char job[10];
float salary;
} emprec; /* emprec is a variable of structure type empdata */
Or a structure can be declared separately as:
struct empdata emprec;/* emprec is a variable of structure type
empdata */
Copyright
C Programming
Page 300
Declaring a Structure
Declaring a structure only defines a template or a blueprint for a
data type. It does not therefore result in the allocation of memory.
Memory is allocated only when a variable of a structure type is
declared in the program.
Till a variable of a structure type is created, a structure declaration
is only identified as a type, and no memory is allocated.
Even for fundamental data types, the compiler does not allocate
memory for types. Rather, it allocates memory for implementations
of fundamental data types, in short, memory is allocated only for a
variable declaration.
Copyright
C Programming
Page 301
struct empdata {
int empno;
char name[10];
char job[10];
float salary;
}
struct empdata emprec;
emprec.empno /* referring to the element of the structure variable
emprec */
Copyright
C Programming
Page 302
#include<stdio.h>
struct salesdata
{
int transaction_number;
int salesman_number;
int product_number;
int units_sold;
float value_of_sale;
};
main( )
{
struct salesdata salesvar;
Copyright
C Programming
Page 303
Copyright
C Programming
Page 304
compute(&salesvar);
.
.
.
}
compute( salesdata *salesptr)
{
static float product_unit_price = {10.0, 20.0, 30.0, 40.0};
/*product unit price for products numbered 1 through 4 */
product_unit_price[salesptr->product_number 1]
Copyright
C Programming
Page 305
Array of Structures
Just as it is possible to declare arrays of primitive data
types, it should also be possible to declare arrays of
structures as well.
Consider the structure declaration for the employee details
used earlier.
struct empdata {
int empno;
char name[10];
char job[10];
float salary;
};
Copyright
C Programming
Page 306
Array of Structures
If one were to define an array of structure variables, one
would do so as follows:
struct empdata employee_array[4];
Copyright
C Programming
Page 307
Copyright
C Programming
Page 308
Copyright
C Programming
Page 309
C Programming
Page 310
Copyright
C Programming
Page 311
Union
Unions
In cnvt, both integer i and character ch share the same
memory location. Of course, i occupies 2 bytes (assuming
2-byte integers, and ch uses only one byte.
i
Byte 0
Byte 1
ch
Copyright
C Programming
Page 313
Unions
To access a member of a union, use the same syntax that
you would use for structures: the dot and arrow operators.
If you are operating on the union directly, use the dot
operator. If the union is accessed through a pointer, use the
arrow operator.
For example, to assign the integer 10 to element i of cnvt,
write cnvt.i = 10;
Copyright
C Programming
Page 314
Unions
In the following code snippet, a pointer to cnvt is passed to a
function:
void func1( union u_type *un)
{
un->i = 10; /* assign 10 to cnvt using function */
}
Using a union can aid in the production of machineindependent (portable) code. Because the compiler keeps
track of the actual size of the union members, no unnecessary
machine dependencies are produced.
Copyright
C Programming
Page 315
Unions
Unions are used frequently when specialized type conversions
are needed because you can refer to the data held in the union
in fundamentally different ways.
Consider the problem of writing a short integer to a disk file.
The C standard library defines no function specifically
designed to write a short integer to a file.
While you can write any type of data to a file using fwrite( ),
using fwrite( ) incurs excessive overhead for such a simple
operation.
Copyright
C Programming
Page 316
Unions
However, using a union, you can easily create a function called
putw( ), which represents the binary representation of a short integer
to a file one byte at a time.
The following example assumes that short integers are 2 bytes long.
First, create a union consisting of one short integer and a 2-byte
character array:
union pw
{
short int i;
char ch[2];
};
Copyright
C Programming
Page 317
Unions
Now, you can use pw to create the version of putw( )
shown in the following program:
#include <stdio.h>
union pw
{
short int i;
char ch[2];
};
int putw( short int num, FILE *fp);
Copyright
C Programming
Page 318
Unions
int main (void)
{
FILE *fp;
fclose( fp );
return 0;
}
Copyright
C Programming
Page 319
Unions
int putw( short int num, FILE *fp)
{
union pw word;
word.i = num;
C Programming
Page 320
Enumeration
Is a set of named integer constants that specify all the legal
values a variable of that type can have.
The keyword enum signals the start of an enumeration type.
The general form for enumeration is
enum enum-type-name { enumeration list } variable_list;
enum coin { penny, nickel, dime, quarter, half_dollar,
dollar};
enum coin money;
Copyright
C Programming
Page 321
Enumeration
Given these declarations, the following types of statements
are perfectly valid:
money = dime;
if (money = = quarter)
printf( Money is a quarter. \n);
The key point to understand about an enumeration is that
each of the symbols stands for an integer value.
As such, they may be used anywhere that an integer may
be used.
Copyright
C Programming
Page 322
Enumeration
Each symbol is given a value one greater than the symbol
that precedes it. The value of the first enumeration symbol
is 0. Therefore,
printf( %d %d, penny, dime);
displays 0 2 on the screen.
You can specify the value of one or more of the symbols
by using an initializer.
Do this by following the symbol with an equal sign and an
integer value.
Copyright
C Programming
Page 323
Enumeration
For example, the following code assigns the value of 100
to quarter:
enum coin { penny, nickel, dime, quarter=100, half_dollar,
dollar};
Now, the values of these symbols are:
penny
0
nickel
1
dime
2
quarter
100
half_dollar
101
dollar
102
Copyright
C Programming
Page 324
Enumeration
One common but erroneous assumption about enumerations
is that the symbols can be input and output directly. This is
not the case.
For example, the following code fragment will not perform
as desired:
money = dollar;
printf( %s, money);
Dollar is simply a name for an integer; it is not a string.
Copyright
C Programming
Page 325
Enumeration
For the same reason, you cannot use this code to achieve
the desired results:
/* this code is wrong */
strcpy (money, dime);
That is, a string that contains the name of a symbol is not
automatically converted to that symbol.
Actually creating code to input and output enumeration
symbols is quite tedious (unless you are willing to settle
for their integer values).
Copyright
C Programming
Page 326
Enumeration
For example, you need the following code to display, in words, the kind of
coins that money contains:
switch (money)
{
case penny : printf( penny);
break;
case nickel : printf( nickel);
break;
case dime : printf( dime);
break;
case quarter : printf( quarter);
break;
case half_dollar : printf( half_dollar);
break;
case dollar : printf( dollar);
break;
}
Copyright
C Programming
Page 327
Typedef Statements
Creates synonyms (aliases) for previously defined datatypes
Used to create shorter type names
Format: typedef type new-type;
Example: typedef struct Card * CardPtr;
defines a new type name CardPtr as a synonym for type
struct Card *
typedef does not create a new datatype
Only creates an alias
Copyright
C Programming
Page 328
Summary
In this session, you learnt to:
Trace down the genesis of user-defined data types
Declare user-defined data types, namely
Structures
Unions
Enumerations
C Programming
Page 329
Copyright
C Programming
Page 330
Session 8
Copyright
C Programming
Page 331
Recursion
Copyright
C Programming
Page 332
Objectives
Copyright
C Programming
Page 333
Introduction
Many concepts typically in mathematics are defined by
presenting a process leading up to that concept. For
example, is defined as ratio of the circumference of a
circle to its diameter.
This is equivalent to the following set of instructions:
Copyright
C Programming
Page 334
C Programming
Page 335
C Programming
Page 336
0! = 1
1! = 1
2! = 2 * 1
3! = 3 * 2 * 1
4! = 4 * 3 * 2 * 1
It is cumbersome for you to list the formula for the factorial of each
integer.
To avoid any shorthand, and to avoid an infinite set of definitions,
but yet to define the function precisely, you may present an
algorithm that accepts an integer n and returns the value of n!.
Copyright
C Programming
Page 337
C Programming
Page 338
C Programming
Page 339
Copyright
C Programming
Page 340
Copyright
C Programming
Page 341
Copyright
C Programming
Page 342
C Programming
Page 343
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1 * 0!
0! = 1
Copyright
C Programming
Page 344
C Programming
Page 345
0! = 1
1! = 1 * 0! = 1 * 1 = 1
2! = 2 * 1! = 2 * 1 = 2
3! = 3 * 2! = 3 * 2 = 6
4! = 4 * 3! = 4 * 6 = 24
5! = 5 * 4! = 5 * 24 = 120
Copyright
C Programming
Page 346
x = n 1;
fact = n * y;
Copyright
C Programming
Page 347
C Programming
Page 348
C Programming
Page 349
Copyright
C Programming
Page 350
Copyright
C Programming
Page 351
int x, y;
if ( n == 0)
return (1);
else
x = n-1;
y = fact(x);
return ( n * y);
Copyright
C Programming
Page 352
Mechanics of Recursion
In the statement y = fact(x), the function fact( ) makes a
recursive call to itself.
This is the essential ingredient of a recursive routine.
The programmer assumes that the function being
computed has already been written, and uses it in its own
definition.
However, the programmer must ensure that this does not
lead to an endless series of calls.
Copyright
C Programming
Page 353
Mechanics of Recursion
It is important to examine the execution of this function
when it is called by another program.
For example, the calling program (main( )) contains the
statement: printf(%d, fact(4));
When the calling function calls fact( ), the parameter n is
set equal to 4. Since n is not 0, x is set equal to 3.
At that point, fact( ) is called a second time with an
argument of 3.
Copyright
C Programming
Page 354
Mechanics of Recursion
Therefore, the function fact( ) is reentered and the local
variables (x and y) and parameter (n) of the block are
reallocated.
Since execution has not yet left the first call of fact( ), the
first allocation of these variables remains.
Thus, there are two generations of each of these variables
in existence simultaneously in the stack for the first call,
and the second recursive call to the function fact( )
respectively.
Copyright
C Programming
Page 355
Mechanics of Recursion
From any point within the second execution of fact( ), only
the most recent copy of these variables can be referenced.
In general, each time the function fact( ) is entered
recursively, a new set of local variables and parameters is
allocated on the stack, and only this new set may be
referenced within that call of fact( ).
When a return from fact( ) to a point in a previous call
takes place, the most recent allocation of these variables is
freed from the stack when the function returns, and the
previous copy is reactivated (belonging to the previous
recursive call to the function fact( )).
Copyright
C Programming
Page 356
Mechanics of Recursion
This previous copy is the one that was allocated upon the
original entry to the previous call and is local to that call.
This description suggests the use of a stack to keep the
successive generations of local variables and parameters.
This stack is maintained by the C system and is invisible to
the programmer.
Each time that a recursive function is entered, a new
allocation of its variables is pushed on top of the stack.
Copyright
C Programming
Page 357
Mechanics of Recursion
Any reference to a local variable or parameter is through
the current top of the stack.
When the function returns, the stack is popped, the top
allocation is freed, and the previous allocation becomes
the current top of the stack to be used for referencing local
variables and parameters.
You will now see how this mechanism is applied in
computing the factorial function.
Copyright
C Programming
Page 358
Mechanics of Recursion
The following figure contains a series of snapshots of the
stack for the variables n, x, and y as execution of the fact( )
function proceeds.
Initially, the stacks are empty, as illustrated in (a).
After the first call on fact( ) by the calling procedure, the
situation is as shown in (b) with n equal to 4. The variables
x and y are allocated but not initialized.
Copyright
C Programming
Page 359
Mechanics of Recursion
Since n does not equal 0, x is set to 3 and fact(3) is called
as shown in (c).
The new value of n does not equal 0; therefore, x is set to 2
and fact(2) is called as shown in (d).
This continues until n equals 0 as shown in(f).
At that point, the value 1 is returned from the call to
fact(0).
Copyright
C Programming
Page 360
Mechanics of Recursion
Execution resumes from the point at which fact(0) was
called, which is the assignment of the returned value to the
copy of y declared in fact(1).
This is shown by the status of the stack shown in figure
(g), where the variables allocated for fact(0) have been
freed and y is set to 1.
The statement return (n * y) is then executed, multiplying
the top values of n and y to obtain 1, and returning the
value to fact(2) as shown in (h).
Copyright
C Programming
Page 361
Mechanics of Recursion
This process is repeated twice more, until finally the value
of y in fact(4) equals 6.
The statement return (n * y) is executed one more time.
The product 24 is returned to the calling function where it
is printed by the statement printf(%d, fact(4));
Note that each time that a recursive routine returns, it
returns to the point immediately following the point from
which it was called.
Copyright
C Programming
Page 362
Mechanics of Recursion
Thus, the recursive call to fact(3) returns to the assignment
of the result to y within fact(4), but the call to fact(4)
returns to the printf( ) statement in the calling function.
(a) initially
(b) fact(4)
4
n
Copyright
*
n
(c) fact(3)
*
x
(c) fact(2)
C Programming
Page 363
Mechanics of Recursion
(e) fact(1)
(f) fact(0)
(g) y = fact(0)
Copyright
(h) y = fact(1)
C Programming
Page 364
Mechanics of Recursion
(i) y = fact(2)
(j) y = fact(3)
4
n
Pritnf(%d, fact(4))
6
y
The stack at various times during execution. An asterisk indicates an uninitialized value.
Copyright
C Programming
Page 365
Function Pointers
Function Pointers are pointers, i.e. variables, which point
to the address of a function.
You must keep in mind, that a running program gets a
certain space in the main-memory.
Both, the executable compiled program code and the used
variables, are put inside this memory.
Thus a function in the program code is, like e.g. a
character field, nothing else than an address.
Copyright
C Programming
Page 366
Function Pointers
It is only important how you, or better, your
compiler/processor, interpret the memory a pointer points to.
When you want to call a function fn() at a certain point in
your program, you just put the call of the function fn() at that
point in your source code.
Then you compile your code, and every time your program
comes to that point, your function is called.
But what can you do, if you don't know at build-time which
function has got to be called? Or, invoke functions at runtime.
Copyright
C Programming
Page 367
Function Pointers
You want to select one function out of a pool of possible
functions.
However you can also solve the latter problem using a
switch-statement, where you call the functions just like
you want it, in the different branches.
But there's still another way: Use a function pointer!
Consider the example on the following slide:
Copyright
C Programming
Page 368
Copyright
C Programming
Page 369
return 0;
}
Copyright
C Programming
Page 370
C Programming
Page 371
C Programming
Page 372
Copyright
C Programming
Page 373
Summary
Copyright
C Programming
Page 374