Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by Arun Umrao

ssuserd6b1fd 566 views 101 slides Oct 10, 2021
Slide 1
Slide 1 of 101
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73
Slide 74
74
Slide 75
75
Slide 76
76
Slide 77
77
Slide 78
78
Slide 79
79
Slide 80
80
Slide 81
81
Slide 82
82
Slide 83
83
Slide 84
84
Slide 85
85
Slide 86
86
Slide 87
87
Slide 88
88
Slide 89
89
Slide 90
90
Slide 91
91
Slide 92
92
Slide 93
93
Slide 94
94
Slide 95
95
Slide 96
96
Slide 97
97
Slide 98
98
Slide 99
99
Slide 100
100
Slide 101
101

About This Presentation

C programming language notes for beginners and Collage students. Written for beginners. Colored graphics. Function by Function explanation with complete examples. Well commented examples. Illustrations are made available for data dealing at memory level.


Slide Content

300 Array & Pointer
int(* a) [3];
10 ar = mat ;
printf (" ar [2][2] element is = %d \n" , *(*( ar +2) +2) );
12 printf (" ar [0][2] element is = %d \n" , *(*( ar +0) +2) );
return0;
14}



mat [2][2] element is = 99
mat [0][2] element is = 53



# include< stdio .h >
2
intmain () {
4 intArr [3][3] = {
{1 , 2, 3} ,
6 {4 , 5, 6} ,
{7 , 8, 9}
8 };
int(* mat ) [3];
10 mat = Arr ;
printf (" Element at mat [0][1] = % d\n" , *(*( mat +0) +1) );
12 printf ("8 th element from positino of mat [0][0] = %d\n" ,
(*( mat + 0) ) [8]) ;
14 printf ("6 th element from position of mat [0][2] = %d\n" ,
(*( mat + 0) + 2) [6]) ;
16 return0;
}



Element at mat [0][1] = 2
8 th element from the position of mat [0][0] = 9
6 th element from the position of mat [0][2] = 9


Following is an example in which a 3D matrix is accessed by using a pointer.

1# include< stdio .h >
3intmain () {
intArr [3][3][3] = {
5 {/* [x ][ y] matrix with [z =0] */
{11 , 12 , 13} ,
7 {14 , 15 , 16} ,
{17 , 18 , 19}
9 },
{/* [x ][ y] matrix with [z =1] */
11 {21 , 22 , 23} ,
{24 , 25 , 26} ,
13 {27 , 28 , 29}
},
15 {/* [x ][ y] matrix with [z =2] */

2.2. POINTER 301
{31 , 32 , 33} ,
17 {34 , 35 , 36} ,
{37 , 38 , 39}
19 }
};
21 int(* mat ) [3][3];
mat = Arr ;
23 printf (" Element at mat [0][1][1] = %d\n" ,
*(*(*( mat + 0) + 1) + 1) );
25 printf ("8 th element from position of mat [0][2][0] = %d\n" ,
(*(*( mat + 0) + 2) ) [8]) ;
27 printf ("8 th element from position of mat [0][2][0] = %d\n" ,
(*( mat + 0) ) [2][8]) ;
29 return0;
}



Element at mat [0][1][1] = 15
8 th element from the position of mat [0][2][0] = 26
8 th element from the position of mat [0][2][0] = 26


2.2.3 Pointers and Text Strings
Historically, text strings in C have been implemented as array of characters, with the
last byte in the string being a character code zero, or the null character ‘\0’. Most
C implementations came with a standard library of functions for manipulating strings.
Many of the more commonly used functions expect the strings to benull terminated string
of characters. To use these functions requires the inclusion of the standard C header file
“string.h”. A statically declared, initialized string would look similar to the following:

1static const char * myFormat =" Total Amount Due : % d";


The variable ‘myFormat’ can be view as an array of 21 characters. There is an implied
null character (’\0’) tacked on to the end of the string after the ’d’ as the 21st item in
the array. You can also initialize the individual characters of the array as follows:

1static const char myFlower [ ]
= {’P ’,’e ’,’t ’,’u ’,’n ’,’i ’,’a ’,’ \0 ’};


An initialized array of strings would typically be done as follows:

static const char * myColors [ ] = {" Red "," Green "," Blue "};


The initialization of an especially long string can be splitted across lines of source code
as follows.

1static char * longString =" My name is XYZ .";


The library functions those are used with strings are discussed in later. A simple example
of copying string from one variable to other by using pointer is given below.

302 Array & Pointer

1# include< stdio .h >
/* Defined two arrays to be copied */
3charA [80] =" Lucknow is capital city ." ;
charB [80];
5
intmain (void) {
7 /* First pointer A */
char* ptrA ;
9 /* Second pointer B */
char* ptrB ;
11 /* Assign string pointer of *
* array A to pointer ptrA */
13 ptrA = A;
/* Assign string pointer of *
15 * array B to pointer ptrB */
ptrB = B;
17 /* do loop */
while(* ptrA !=’\0 ’) {
19 /* Copy text from array A to array *
*B using pointers prtA and ptrB */
21 * ptrB ++ = * ptrA ++;
}
23 /* Add line terminating value */
* ptrB =’\0 ’;
25 /* Show array B on screen */
puts ( B);
27 return0;
}


From above example, always remember that a pointer to an array always points to the
elements of the array and make copy-paste an element from one array to another array.
Pointer never stores elements itself. The output of the above example is given below:

Lucknow is capital city .


By default, strings are pointer to itself. For example “I am a king” is apointer to
itself. This pointer points to the first character “I”. See example

1# include< stdio .h >
3intmain (intargc ,char* argv [ ]) {
inti =0;
5 for(i =0;*("I am king "+ i) !=’\0 ’;i ++)
printf ("%c\n",*("I am king "+ i));
7 return0;
}


In above example

*("I am king "+ i)

2.2. POINTER 303
extracts character by character from the string pointed by string itself.forloop is used to
print all characters. When string pointer encountered by a null character, loop is halted.
Output of above example is

I
a
m
k
i
n
g


Pointers to Function
To declare a pointer-to-function do:

1int(* pf ) () ;


The question rises why this declaration is not written as

1int* pf () ;


The reason is that parentheses operator, ( ), has higher precedence than that of derefer-
encing operator (*). Hence for pointer-to-function variable, dereferencing of function is
grouped by parentheses. Example for pointer-to-function is given below.

1# include< stdio .h >
3intmain () {
int(* r) () ;
5 r = puts ;
(* r)(" My String ");
7 return0;
}


Here, the function line is equivalent to

puts (" My String ");



My String


Unlike the normal pointers, a function pointer points to code, not data. A function
pointer points to the memory address where execution codes are stored. Remember that,
we do not allocate or de-allocate memory using function pointers.

1# include< stdio .h >

304 Array & Pointer
3voidmyFunc (inta) {
printf (" Value of a is %d\n" , a);
5}
7intmain () {
void(* ptrFunc )(int) = & myFunc ;
9 (* ptrFunc ) (10) ;
return0;
11}



Value of a is 10


Function name is also points to the address of execution code. Therefore, use of ‘myFunc’
at the place of ‘&myFunc’ in the following example give same result as given by above
example.

1# include< stdio .h >
3voidmyFunc (inta) {
printf (" Value of a is %d\n" , a);
5}
7intmain () {
void(* ptrFunc )(int) = myFunc ;
9 ptrFunc (10) ;
return0;
11}



Value of a is 10


A pointer-to-function that returns output as string pointer is shown in the following
example:

1# include< stdlib .h >
# defineSTRLEN 1024
3
char* str_func (char* str ) {
5 char* s = NULL ;
/* Allocate the required memory space . */
7 s = malloc (sizeof(char) *( STRLEN + 1) );
/* Copy contents of str into memory */
9 memcpy (s , str , STRLEN );
/* Return the pointer of memory location */
11 returns;
}
13
main (intargc ,char* argvc [ ]) {
15 /* Test string . */
chars[ STRLEN ] =" The Sarnath .";
17 /* Returned string pointer . */

2.2. POINTER 305
char* st ;
19 /* Pointer to function declaration . */
int(* fn ) () ;
21 /* Get the function object pointer . */
fn = str_func ;
23 /* Pass the func object to declared function . */
st = (* fn )(s);
25 /* Print returned string . */
printf ("%s\n", st );
27 return0;
}



The Sarnath .


C also allows to create pointer-to-function. Pointer-to-functioncan get rather messy.
Declaring adata typeto a function pointer generally clarifies the code. Here’s an example
that uses a function pointer, and a (void *) pointer to implement what’s known as a
callback. A switch case example

1# include< stdio .h >
intadd (inta ,intb);
3intsub (inta ,intb);
intmul (inta ,intb);
5intdiv (inta ,intb);
7intmain () {
inti , result ;
9 inta = 10;
intb = 5;
11 printf (" Enter the value between [0 , 3] : " );
scanf ("%d", &i);
13 switch(i) {
case0:
15 result = add (a , b);
break;
17 case1:
result = sub (a , b);
19 break;
case2:
21 result = mul (a , b);
break;
23 case3:
result = div (a , b);
25 break;
}
27 printf (":-> Result is %d" , result );
return0;
29}
31intadd (inti ,intj) {
return(i + j);

306 Array & Pointer
33}
35intsub (inti ,intj) {
return(i - j);
37}
39intmul (inti ,intj) {
return(i * j);
41}
43intdiv (inti ,intj) {
return(i / j);
45}



Enter the value between 0 and 3 : 2
:-> Result is 50


Array of function pointers may also be used to access a function byusing array pointer
index. See the example given below:

# include< stdio .h >
2# include< math .h >
typedef int *(* func )(int);
4
intmySum (inti) {
6 return(i + 2) ;
}
8
intmySub (inti) {
10 return(i - 2) ;
}
12
intmain () {
14 func myFuncArray [10] = { NULL };
myFuncArray [0] = & mySum ;
16 myFuncArray [1] = & mySub ;
printf ("%d\n", (* myFuncArray [0]) (5) );
18 printf ("%d\n", (* myFuncArray [1]) (5) );
return0;
20}



7
3


In above example, a array function pointer is created by usingtypedefand each array
function pointer is assigned the address of the function object.

typedef int *(* func )(int);// array function pointer
2myFuncArray [0] = & mySum ; /* assigning function pointer *
* to array function pointer . */

2.2. POINTER 307
When array function pointer is called, we get desired result. Above array function pointer
is re-implemented in the following example.

1# include< stdio .h >
intadd (inta ,intb);
3intsub (inta ,intb);
intmul (inta ,intb);
5intdiv (inta ,intb);
/* Function pointer used for execution of *
7* four functions called by their positions . */
int(* operator [4]) (inta ,intb) = { add , sub , mul , div };
9
intmain () {
11 inti , result ;
inta = 10;
13 intb = 5;
printf (" Enter the value between [0 , 3] : " );
15 scanf ("%d", &i);
result = operator [i ]( a , b);
17 printf (":-> Result is %d" , result );
return0;
19}
21intadd (inti ,intj) {
return(i + j);
23}
25intsub (inti ,intj) {
return(i - j);
27}
29intmul (inti ,intj) {
return(i * j);
31}
33intdiv (inti ,intj) {
return(i / j);
35}



Enter the value between 0 and 3 : 1
:-> Result is 5


A struct member function can also be created by using pointer. Following is the example
for the purpose.

# include< stdio .h >
2# include< string .h >
/* Global declaration of file pointer . */
4FILE * fp ;
6data typestruct{

308 Array & Pointer
int(* open )(void);
8 int(* del )(void);
} file ;
10
intmy_file_open (void) {
12 fp = fopen (" my_file . txt ","w");
if( fp == NULL ) {
14 printf (" File can not be opened .\ n" );
}else{
16 printf (" File opened .\ n");
fputs (" Hello World !", fp );
18 }
}
20
voidmy_file_del (void) {
22 printf (" Try to remove .\ n");
if( remove (" my_file . txt ") == 0) {
24 printf (" File is removed .\ n");
}else{
26 printf (" No file to remove .\ n ");
}
28}
30file create (void) {
file my_file ;
32 my_file . open = my_file_open ;
my_file . del = my_file_del ;
34 my_file . open () ;
my_file . del () ;
36 returnmy_file ;
}
38
intmain (intargc ,char* argv [ ]) {
40 create () ;
return0;
42}


Casting of Pointer
To assign an integer type pointer ‘iptr’ to a floating type pointer ‘fptr’, we cast ‘iptr’ as
a floating type pointer and then carry out the assignment, as shown :

fptr = (float*) iptr ;


When a pointer is casted from old data type to new data type then it only keeps the
address of a size of new data type. For example, in Linux GCC, data size of integer is 4
byte while data size of character is 1 byte. Hence when integer datatype is casted into
character data type and pointed by a pointer then pointer keep the address one byte at
time.

2.2. POINTER 309

1# include< stdio .h >
3intmain () {
inta = 320;
5 /* Integer 320 = binary 00000001 01000000 */
char* ptr ;
7 ptr = (char*) &a;
/* Cast intger into character and point to first *
9 * byte of the integer containing value 01000000 */
11 printf ("%d ", * ptr );/* Print 01000000 as decimal 64 */
return0;
13}



64


Address Copying Vs Content Copying
A pointer points to location of content stored in the memory. It does not point to value
stored in the memory. For example, take a string “This”, that is stored in memory
location 0×001250. Now this value is assigned to a pointer variable (say ‘str’) then pointer
holds address value 0×001250 not to the value “This”. When one pointer is assigned to
the other pointer then only location of contents is assigned. See the example:

1# include< stdio .h >
3intmain () {
char* str =" This ";/* location at 0 x0011 ( say ) */
5 char* pt =" That ";/* location at 0 x0022 ( say ) */
printf (" str :% s , pt :% s\n",str , pt );
7 str = pt ;/* str ’s memory location changed to 0 x0022 */
printf (" str :% s\n", str );
9 return0;
}



str : This , pt : That
str : That


Here, address of ‘pt’ is copied to address of ‘str’. If we wants to copy contents from the
memory location pointed by ‘pt’ to the memory location pointed by pointer ‘str’, then
strcpyfunction is used.

# include< stdio .h >
2# include< string .h >
4intmain () {
char* str =" This ";/* location at 0 x0011 ( say ) */
6 char* pt =" That ";/* location at 0 x0022 ( say ) */

310 Array & Pointer
printf (" str :% s , pt :% s\n",str , pt );
8 str = malloc (5) ;/* Memory allocation is required as *
* compiler do not kew the memory size *
10 * assigned to str pointer while copy . */
strcpy ( str , pt );/* contents of memory location of ’pt ’ *
12 * is copied at memory location of ’ str ’*/
printf (" str :% s\n", str );
14 free ( str );
return0;
16}



str : This , pt : That
str : That


Here, contents from the memory location pointed by pointer ‘pt’ are copied into the
memory location pointed by pointer ‘str’.
2.2.4 Dangling & Wild Pointers
Dangling pointers and wild pointers are pointers that do not point to avalid object of the
appropriate type. Dangling pointers arise when it points to the location that is deallocated
without modifying the value of the pointer. The pointer still points tothe memory
location of the deallocated memory. Dangling pointers causes memory sharing violation
and returns error of segmentation faults in UNIX and Linux, or general protection faults
in Windows.

# include< stdio .h >
2
intmain () {
4 {
char* dp = NULL ;
6 {
charc;
8 dp = &c;
printf ("%d\ n", dp );
10 }
/* dp is now a dangling pointer */
12 }
14 return0;
}



2280807


Another example of dangling pointer, in which function ‘func’ returns the addresses of a
stack-allocated local variable. Once called function returns, the space for these variables
gets deallocated and technically they have “garbage values”.

2.2. POINTER 311

1# include< stdio .h >
3int* func (void) {
intnum = 1234;
5 return& num ;
}
7
intmain () {
9 printf ("%d\n", func () );
printf ("%d\n", * func () );
11 return0;
}



2280756
2280756


Wild pointers arise when a pointer is used prior to initialization to some known state,
which is possible in some programming languages. They show the same erratic behavior
as dangling pointers, though they are less likely to stay undetectedbecause many com-
pilers will raise a warning at compile time if declared variables are accessed before being
initialized.

# include< stdio .h >
2
intmain () {
4 inti ;// Declared but not initialized
printf ("%d\n", i);// i acts as wild pointer
6 return0;
}


Output is strange:

1629773328


2.2.5 Pointer, Variable & Address
A variable is a literal name which addresses to a memory location. An address is a
reference to a variable. Pointer points to the address of a variable. One of the most
common problem arises in C programming is analyses of pointer variablesize, position
of its current address and next address after arithmetic operations. The pointers and
their locations are similar to milestones along the road. Suppose, a road along-with the
distance milestone separated by one meter (for concept purpose).

312 Array & Pointer
0
1
2 3
4
5
6
7
8
9
10
Initially, we are at the 3
rd
milestone. One meter long unit is used to measure the
distances between two consecutive milestones. In one step measurement, next milestone
will be 4
th
one. It means that, if initially pointer location is at 3
rd
milestone then after
one increment (by one meter), the pointer location will be at 4
th
milestone.
0
1
2 3
bc
4
b
5
6
7
8
9
10
Now, we change measurement count from one meter long unit to twometer long unit.
Assume that initially location pointer is at 3
rd
milestone. In one increment to the location
pointer (two meter unit), next milestone will be 5
th
one.
0
1
2 3
bc
4
5
b
6
7
8
9
10
In C programming, integer type variable is four byte long. So, if initiallypointer
location of the integer variable is at 3
rd
milestone then after one increment (by four
bytes) to the integer variable, the pointer location shall be at 7
th
milestone.
0
1
2 3
bc
4
5
6
7
b
8
9
10
In the following example a character data-type pointer is declared as variable ‘a’.
Pointer arithmetic is performed. New locations of pointers fetchedto see the change in
the length between two consecutive addresses of pointer.

2.2. POINTER 313

1# include< stdio .h >
3intmain () {
char* a;
5 printf ("%p\n", a);
a ++;/* First increment of pointer */
7 printf ("%p\n", a);
a ++;/* Second increment of pointer */
9 printf ("%p\n", a);
return0;
11}



0 xb 7758000% First address location of character
% pointer is here
0 xb 7758001% New location of character pointer after
% first increment . Distance from the
% first address location is 1 bytes .
0 xb 7758002% New location of character pointer after
% second increments . Distance from the
% first address location is 2 bytes .


Bytes Memory Blocks Memory Address
0×b7758000Byte No. 0
0×b7758001Byte No. 1
0×b7758002Byte No. 2
0×b7758003Byte No. 3
0×b7758004Byte No. 4
0×b7758005Byte No. 5
0×b7758006Byte No. 6
0×b7758007Byte No. 7
0×b7758008Byte No. 8
a
a+ 1
a+ 2
In the following example an integer data-type pointer is declared as variable ‘a’. Pointer
arithmetic is performed. New locations of pointers fetched to see the change in the length
between two consecutive addresses of pointer.

# include< stdio .h >
2
intmain () {
4 int* a;
printf ("%p\n", a);
6 a ++;/* First increment of pointer */
printf ("%p\n", a);
8 a ++;/* Second increment of pointer */
printf ("%p\n", a);

314 Array & Pointer
10 return0;
}



0 xb 7758000% First address location of integer pointer is here
0 xb 7758004% New location of integer pointer after first increment .
% Distance from the first address location is 4 bytes .
0 xb 7758008% New location of integer pointer after second increments .
% Distance from the first address location is 8 bytes .


Bytes Memory Blocks Memory Address
0×b7758000Byte No. 0
0×b7758001Byte No. 1
0×b7758002Byte No. 2
0×b7758003Byte No. 3
0×b7758004Byte No. 4
0×b7758005Byte No. 5
0×b7758006Byte No. 6
0×b7758007Byte No. 7
0×b7758008Byte No. 8
a
a+ 1
a+ 2
In the following example a two dimensional integer data-type array isdeclared and initial-
ized as variable ‘a’. Pointer arithmetic is performed. New locations of pointers fetched to
see the change in the length between two consecutive addresses of pointer for first column.

1# include< stdio .h >
3intmain (void) {
int* mPtr [ ][3] = {
5 { -1 , 2, 3} ,/* 8 bytes , 8 bytes , 8 bytes */
{4 , -3, 5} ,/* 8 bytes , 8 bytes , 8 bytes */
7 {5 , 6, -5} /* 8 bytes , 8 bytes , 8 bytes */
};/* 3 By 3 matrix */
9 inti , j;
for( i = 0; i < 3; i ++) {
11 printf (" %2 d -> %p\t", *(* mPtr + (3 * i)) , ( mPtr + (3 * i)));
printf ("\n");
13 }
return0;
15}



-1 -> 0 xbfa 09 b8c%1X1 element is at this address
4 -> 0 xbfa 09 bb 0%2X1 element is at this address
% Distance from 1X1 element is 24 Bytes
5 -> 0 xbfa 09 bd 4%3X1 element is at this address
% Distance from 1X1 element is 48 Bytes

2.2. POINTER 315
% Distance from 2X1 element is 24 Bytes


In pointers, we must be cautious, that pointers holds address values. The pointers are used
to hold addresses of other memory bytes not the numbers, henceonly pointer comparison,
addition and subtraction operations are allowed . For example, in following code lines,
the memory byte pointed by the variablexholds value 20 as binary 10100.

int*x = 20;// assign address


0×45 0×46 0×47 0×48
00000000 00000000 00000000 00010100
∗x
When pointer is assigned a value, it is treated as address value. Now,we can retrieve this
address by just calling pointer as

1printf ("% d", x);


We shall get value 20 as its result. But when we dereference the variablexas

1printf ("% d", *x);


It tries to read the value at address 0×14 (equal to decimal 20 and binary 00010100), it
gives access status violation as we try to access restricted memory space set by the OS.
It is because, dereference is the retrieving of value from that address which is stored in
the memory bytes pointed by the dereferencing pointer. If we change the value ofxas

1int*x = 2346192; // assign address
printf ("% d", *x);


0×45 0×46 0×47 0×48
00000000 00100011 11001100 11010000
∗x
We get a random value which is stored at address 0×23CCD0 (equal to decimal 2346192 or
binary 1000111100110011010000). Note that, the address location 0×23CCD0 is beyond
the restricted memory region set by OS, hence it returns random output.
2.2.6 Constant Pointers
A pointer may be declared as constant by usingconstkeyword.

inti = 5;
2const int*p = &i;
// Or
4int const*p = &i;

316 Array & Pointer
There are two cases, (i) where a pointer pointed to constant data(pointee) and pointee
can not be changed, and (b) where constant pointer (address) can not be changed. The
usual pointer-pointee relation are given below:

# include< stdio .h >
2# include< stdlib .h >
4intmain () {
inti = 2;
6 intj = 3;
int* k = &j;// k points to j and *k is 3
8 printf ("%d \n", *k);
j = 6;// Now both j and *k are 6
10 printf ("%d %d\n", j , *k);
*k = 7;// j and *k are 7. Pointee changes
12 printf ("%d %d\n", j , *k);
k = & i;// k points to i. *k is 2. Pointer changes
14 printf ("%d %d\n", i , *k);
*k = 8;// i and *k are 8 now . Pointee changes
16 printf ("%d %d\n", i , *k);
return0;
18}



3
6 6
7 7
2 2
8 8


Now theconstkeyword is used as shown in modified example. There are errors shows by
the compiler.

1# include< stdio .h >
# include< stdlib .h >
3
intmain () {
5 inti = 2;
const intj = 3;
7 const int*k = &j;
j = 6;// Error ! assignment of read - only variable ’j ’
9 *k = 7;// Error ! assignment of read - only location ’* k ’
k = & i;// k points to i. *k is 2. Pointer changes
11 *k = 8;// Error ! assignment of read - only location ’* k ’
return0;
13}


Here, code line

1// +-- Pointee type , i.e. constant pointee
// |
3const int*k = &j;

2.2. POINTER 317
2
0×50
3
0×51
4
0×52
5
0×53
6
0×54
7
0×55
8
0×56
const int *k = &j
j
&j
(const) j
represents that ‘k’ is a non constant type pointer and the value towhich it is pointing
is constant type. Therefore, value of ‘j’ can not be changed while address of ‘k’ can be
changed.

1# include< stdio .h >
# include< stdlib .h >
3
intmain () {
5 inti = 2;
const intj = 3;
7 const int*k = &j;
// int const *k = &j ; // Or state
9 printf (" Address of k is %x\n" , k );
k = & i;// k points to i. *k is 2. Pointer changes
11 printf (" New address of k is %x\n " , k);
//
13 printf ("i : %d , k : %d\n", i , *k );
return0;
15}



Address of k is 0x 22 ff 44
New address of k is 0x 22 ff 48
i : 2, k : 2


Similarly, if

1// +-- Pointer type , i.e. constant pointer
// |
3int*constk = &j;


then, pointer becomes constant while value of pointee can be changed. Notice the position
of asterisk (*) not theconstkeyword.
2
0×50
3
0×51
4
0×52
5
0×53
6
0×54
7
0×55
8
0×56
int * const k = &j
(const) *k
j
&j

318 Array & Pointer

1# include< stdio .h >
# include< stdlib .h >
3
intmain () {
5 inti = 2;
intj = 3;
7 int*constk = &j;
printf (" Address of k is %d\n" , k );
9 printf (" Old values - j : %d , k : %d\n" , j , *k);
j = 5;// k points to i. *k is 2. Pointer changes
11 printf (" New values - j : %d , k : %d\n" , j , *k);
// k = &i ;// Error ! assignment of read - only variable ’k ’
13 return0;
}



Address of k is 0x 22 ff 44
Old values - j : 3, k : 3
New values - j : 5, k : 5


The change in the position of the asterisk (*) and keywordconstchanges the pointer and
pointee type. The general representation is

1intn = 5;
int* p = &n;// non - const - Pointer to non - const - Pointee
3const int* p = &n;// non - const - Pointer to const - Pointee
int*constp = &n;// const - Pointer to non - const - Pointee
5const int*constp = & n;// const - Pointer to const - Pointee


The data type keywords before the asterisk symbol represent the nature of the pointee
(the address location where data is stored). The data type keywords after the asterisk
symobl represent the nature of the pointer itself. This contentsadd in C just before
Memory Allocation section.
2.2.7 Memory Allocation
There are two types of memory allocation. (i) Static memory allocation and (ii) dynamic
memory allocation. When a static or global variable is declared, it allocates static memory
of one block of space or of a fixed size. The space is allocated once is never freed until
program is not exit. Automatic variables, such as a function argument or a local variable
allocate memory space dynamically. The allocated space is deallcoated(freed) when the
compound statement that contains these variable is exited.
Dynamic Memory Allocation
mallocis used to allocate dynamic memory to a pointer. It returns pointer to newly
allocated memory space block and null pointer if memory allocation failed. This is why,
before using the memory block, the size of the memory block should be checked. The
contents of the block are undefined. It should be initialized manually.The syntax of the
function is given as

2.2. POINTER 319

1void* malloc ( size_t size );


The address of a block returned bymallocorreallocin GNU systems is always a multiple
of eight. Casting ofmalloc() function is required as shown in the above syntax. The
function,mallocis meant for implementing dynamic memory allocation. It is defined in
stdlib.hormalloc.h, depending on what operating system is used.malloc.hcontains only
the definitions for the memory allocation functions and not the restof the other functions
defined instdlib.h. It is good programming practices that when allocated memory is no
longer needed,freeshould be called to release it back to the memory pool. Overwriting
a pointer that points to dynamically allocated memory can result in that data becoming
inaccessible. If this happens frequently, eventually the operatingsystem will no longer
be able to allocate more memory for the process. Once the processexits, the operating
system is able to free all dynamically allocated memory associated withthe process. A
simple example is

1# include< stdio .h >
3intmain (void) {
int* MemAllo ;
5 /* Allocate the memory space */
MemAllo = (char*) malloc (100) ;
7 if( MemAllo ) {
printf (" Memory allocation successfull !!\ n" );
9 }else{
printf (" Memory allocation un - successfull !! " );
11 exit (0) ;
}
13 /* Allocated memory is not freed here .*
* It is not C programming standards . */
15 return0;
}



Memory allocation successfull !!!!!


In standard C programming, each allocated memory should be freedwhen it is not in use.
Unfreed memory is locked by the allocating program and can not be accessed by other
programs until the program which allocates memory space is not terminated.free() is
used to free the allocated memory.

1# include< stdio .h >
3intmain (void) {
int* p;
5 /* Allocate space for 3490 integers ! */
p = malloc (sizeof(int) * 3490) ;
7 if(p == NULL ) {
printf (" Out of memory ...\ n");
9 }else{
printf (" Memory allocated ...\ n");

320 Array & Pointer
11 }
/* Out of memory for integer allocation *
13 * while allocating memory space block *
* for 349000000 integers bytes ! */
15 p = malloc (sizeof(int) * 349000000) ;
if(p == NULL ) {
17 printf (" Out of memory for integer size ...\ n" );
}else{
19 printf (" Memory allocated ...\ n");
}
21 /* Second method of memory allocation . */
if(( p = malloc (100) ) == NULL ) {/* Allocates 100 bytes space . */
23 printf (" Ooooopps ! Out of memory !\ n");
exit (1) ;
25 }else{
printf (" 100 Byte memory allocated ...\ n" );
27 }
/* Free memory */
29 free ( p);
return0;
31}



Memory allocated ...
Out of memory for integer size ...
100 Byte memory allocated ...


The operand of sizeof only has to be parenthesized if it’s a type name, as shown in example
below.

1float* fp ;
fp = (float*) malloc (sizeof(float));


If there are the name of a data object instead, then the parentheses can be omitted, but
they rarely are.

int*ip , ar [100];
2ip = (int*) malloc (sizeofar );


In the above example, the array ‘ar’ is an array of 100 integers; after the call tomalloc
(assuming that it was successful), ‘ip’ will point to a region of store that can also be treated
as an array of 100 integers. The fundamental unit of storage in C isthe character, and
by definitionsizeof(char)is equal to 1, so there could allocate space for an array of ten
characters withmalloc(10)while to allocate room for an array of ten integers, it have to
use as

malloc (sizeof(int[10]) )


mallocfunction should be used cautiously. Loosely use of this function cause memory
leakage. For example,

2.2. POINTER 321

1voidmyF () {
int* p =(int*) malloc (sizeof(int)) ;
3 return;
}


function creates a local pointer with dynamic size of array. But pointer is not freed here.
In this case, the memory contents are not accessible by other pointers with same address.
This is why, memory allocated on heap should always be freed when it is not needed.

voidmyF () {
2 int* p =(int*) malloc (sizeof(int)) ;
free ( p);
4 return;
}


If you want to allocate memory and set all memory bits to ‘0s’ then usecalloc() function
as given in the following syntax.

1in *i = (int*) calloc (5 ,sizeof(int)) ;


It shall allocate memory space equal to the product of 5 and size ofinteger, i.e. 20 bytes
and each bit is set to ‘0’. Note that,mallocis much faster thancalloc.
Reallocate Memory
realloc() function is used to reallocate the size of the memory block created by themalloc
function previously.

1realloc (< ptr >, < new size >)


If the new size specify is the same as the old size,reallocchanges nothing and return the
same address.

1# include< stdio .h >
# include< stdlib .h >
3
intmain (intargc ,char** argv ) {
5 int* p = malloc (1024 * sizeof(int));
if(p == NULL )
7 printf (" Memory not allocated .");
int* q = realloc (p , 512 *sizeof(int));
9 if(q == NULL )
printf (" Memory not reallocated ." );
11 return0;
}


Memory ManagementSometimes, in a string pointer, we erase few memory bytes in a
programming process. These memory bytes remain unused if stringarray is not refreshed.
For example, we have an array of characters as shown in the following figure.

322 Array & Pointer
ptr G
1
H
2
I
3
J
4
K
5
L
6
Q
7
R
8
S
9
T
10
U
11
V
12
[
13

14
]
15
ˆ
16
˙
17

18
The number over the byte are index numbers of the memory byte location. Let the
memory bytes having values Q to V are erased. Now, we rearrange the memory bytes as
shown in the following figure to free some memory space.
ptr G
1
H
2
I
3
J
4
K
5
L
6
[
7

8
]
9
ˆ
10
˙
11

12
Actually, memory bytes are not shifted leftward, but the contents of the memory
bytes at indices from 13 to 28 are copied into the memory bytes at indices from 7 to 12.
Rearranging of the memory space is good where contents are linear, i.e. contents are not
structured. For example, it is good in case of string, but it is hard tomanipulate the
matrix of 6×3 order if few memory bytes are erased.
2.2.8 Pointer Arithmetic
In normal mathematics numbers are used for addition, subtraction, division and multipli-
cation etc. A pointer to an integer has different behavior to the integer. This is why, in
pointer arithmetic, we have to arrange or conform the pointers sothat they can behave in
properly. A pointer-to-variable always points to the address where value of the variable
is stored. This is why direct arithmetic of the pointers is of the arithmetic of the address
rather than the values stored at the addresses.

# include< stdio .h >
2
intmain (void) {
4 inta [4] = {50 , 99 , 3490 , 0};
int* p;
6 p = a ;
while(* p > 0) {
8 printf ("%i\n", * p);
/* Go to next integer in memory */

2.2. POINTER 323
10 p ++;
}
12 return0;
}



:-> 50
:-> 99
:-> 3490


Another example, using pointer for addition of numbers in an array.

1# include< stdio .h >
3intsum_ptr (char*s) {
/* Array is passed to function as pointer . *
5 * sum is variable that store result . */
intsum = 0;
7 /* Until the array not become empty . */
while(* s !=’\0 ’) {
9 /* Get the pointer value and add it to sum . */
sum += *s;
11 /* Jump to the next pointer position . */
s ++;
13 }
/* Return the answer as sum . */
15 returnsum ;
}
17
intmain (intargc ,char** argv ) {
19
/* Array s containing integers . */
21 chars[ ] = {20 , 15 , 50 , 42};
/* Print the answer . */
23 printf (" Sum : %d\n", sum_ptr (s));
25 return0;
}



Sum : 127


A pointer based integer array is shown in the following example.

1# include< stdio .h >
# include< stdlib .h >
3
intmain () {
5 int* i;/* one row multiple columns , 1 Xn array */
intj = 0;
7 i = (int*) malloc (5 *sizeof(int));
while(j < 5) {

324 Array & Pointer
9 i [j] = j;/* Assign values to i */
j ++;
11 }
j = 0;
13 while(j < 5) {
printf ("%d ", * i);
15 i ++;
j ++;
17 }
return0;
19}



0 1 2 3 4


Pointers follow increment or decrements operations. For example,if pointer ‘i’ represents
to first element of the array (either integer or character type arrays) then ‘i++’ (or ‘i+1’)
represents to the next element of the array. See following figure:
bytes xxxx
i
yyyyzzzznnnn
bytes xxxxyyyy
i+ 1
zzzznnnn
bytes xxxxyyyyzzzz
i+ 2
nnnn
Computer Character Codes
In English language, there are 26 alphabets, ten numerals, other punctuation marks
and special characters. These alpha-numeric characters are put in sequence to form
meaning full words. Computer is an electronic device which operateson alternate
current or direct current. There are only two wave forms of alternate current. First is
positive wave form and second is negative wave form. Thus, there issequences of these
two waveforms when we operate a computer.

2.2. POINTER 325
1
−1
bits
y
0 0
1
0
1
0
1 1
Conventionally, positive waveform is taken as ‘1’ and negative waveform or no
waveform is taken as ‘0’. If computer operates in direct current then there is no negative
wave form to represent ‘0’ bit. In this condition, bit ‘0’ means no current. These
two symbols are binary digits and called as bits. To identify alpha-numeric symbols,
computer uses sequences of these binary digits to form a unique code for each character
or symbol. These unique codes are known as character codes of the computer. Computer
uses eight binary digits for recognition of each character. There are 256 different types
of characters that can be recognized by computer. These 256 characters are assigned
unique decimal character codes ranging from ‘0’ to ‘256’. For example character ‘a’
has character code ‘97’, ‘A’ has character code ‘65’ etc. All the sequential alphabets
and numerals have sequential character codes. For example, upper case alphabets have
character codes ranging from 65 to 90 and lower case alphabets have character codes
ranging from 97 to 122.
Code Symbol Binary
0 00000000
5 00000101
9 00001001
46 . 00101110
47 / 00101111
48 0 00110000
49 1 00110001
50 2 00110010
56 8 00111000
57 9 00111001
65 A 01000001
90 Z 01011010
97 a 01100001
122 z 01111010
Character codes are not same to the user defined binary numbers. This is why,
character code ‘9’ does not represent to numeric decimal ‘9’. Computer accepts ‘9’ as
number digit 9 and computer recognizes it by its equivalent binary sequence 00111001,
i.e. character code 57 rather than binary sequence 00001001. The signal waveform of

326 Array & Pointer
binary 00111001 is given below:
1
bits
y
0 0 1 1 1 0 0 1
Decimal digit 9
2.2.9 Pointer Address
Pointers are used to point the memory address where data is stored. Four memory bytes
are required for a pointer variable to store the address that it is pointing. During the
declaration of a pointer, data type preceded to it tells the nature of data stored at the
address which is being pointed by it. For example, in the pointer variable declaration

1string * ptr =newstring [8];


data type ‘string’ tells that the pointer ‘ptr’ points to memory address 0×00 where a string
of one byte long character is stored. Whenever we will perform pointer’s increment or
decrement operation, like ‘ptr++’ pointer’s pointing address will increase by the size of
character, i.e. one byte. Here, ‘ptr++’ will point to the memory address 0×01 as shown
in the following figure.
d
0×00
e
0×01
f
0×02
g
0×03
h
0×04
i
0×05
j
0×06
k
0×07
Bytes
ptr ptr++
*ptr *(ptr++)
Again ‘*ptr’ dereference to the character ‘d’ which is stored at the memory ad-
dress pointed by the pointer ‘ptr’. To get the next character ‘e’, dereference is done
as ‘*(ptr++)’. Similarly, if pointer is integer type as declared below:

1int* ptr =new int[10];


The size of the pointer variable is always equal to the address bus size. In 32 bit micro-
processor system, it is 4 bytes long. Now, if pointer ‘prt’ points to the memory address
0×00 then ‘ptr++’ points to the memory address 0×04 as shown in the figure given below:

2.2. POINTER 327
xxxx
0×00
xxxx
0×01
xxxx
0×02
xxxx
0×03
yyyy
0×04
yyyy
0×05
yyyy
0×06
yyyy
0×07
Bytes
ptr ptr++
*ptr *(ptr++)
Again ‘*ptr’ dereference to the integer value stored at the memory address pointed by
the pointer ‘ptr’. To get the next integer value, de-reference is done as ‘*(ptr++)’.

1# include< stdio .h >
# defineSIZE 4
3
intmain (void) {
5 shortidx ;
doubled[ SIZE ];
7 double* ptd ;// data type at pointed address is
// 8 bytes long
9 ptd = d;// assign address of array to pointer
printf (" %18 s\n"," double ");
11 for( idx = 0; idx < SIZE ; idx ++)
printf (" pt + %d : %10 p\n",
13 idx , ptd + idx );
return0;
15}



double
pt + 0: 0x 22 cd 30 //
pt + 1: 0x 22 cd 38 //38 is more than 8 from 30
pt + 2: 0x 22 cd 40 //40 is more than 16 from 30
pt + 3: 0x 22 cd 48 //48 is more than 24 from 30


The value assigned to a pointer is the address of the object to whichit points. The
address of a large object, such as type double variable, typically is the address of the first
byte of the object. Applying the ‘*’ operator to a pointer yields thevalue stored in the
pointed-to object. Adding ‘1’ to the pointer increases its value by the size, in bytes, of
the pointed-to type. There is close connection between arrays and pointers. They mean
that a pointer can be used to identify an individual element of an array and to obtain its
value. In arrays and pointers

1arr [n] == *( arr + n) /* same value */
arr +2 == & arr [2]/* same address */



# include< stdio .h >
2# defineMONTHS 12
4intmain (void) {
intdays [ MONTHS ] = {31 , 28 , 31 , 30 , 31 , 30 , \

328 Array & Pointer
6 31 , 31 , 30 , 31 , 30 , 31};
intind ;
8 for( ind = 0; ind < MONTHS ; ind ++)
printf (" Month %2 d has %d days .\ n", ind + 1,
10 *( days + ind ));// same as days [ ind ]
return0;
12}



Month 1 has 31 days .
Month 2 has 28 days .
Month 3 has 31 days .
Month 4 has 30 days .
Month 5 has 31 days .
Month 6 has 30 days .
Month 7 has 31 days .
Month 8 has 31 days .
Month 9 has 30 days .
Month 10 has 31 days .
Month 11 has 30 days .
Month 12 has 31 days .


Above program can be written as shown below:

# include< stdio .h >
2# defineMONTHS 12
4intmain (void) {
intdays [ MONTHS ] = {31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 ,
31};
6 intind ;
for( ind = 0; ind < MONTHS ; ind ++)
8 printf (" Month %2 d has %d days .\ n", ind + 1,
days [ ind ]) ;// same as *( days + ind )
10 return0;
}



Month 1 has 31 days .
Month 2 has 28 days .
Month 3 has 31 days .
Month 4 has 30 days .
Month 5 has 31 days .
Month 6 has 30 days .
Month 7 has 31 days .
Month 8 has 31 days .
Month 9 has 30 days .
Month 10 has 31 days .
Month 11 has 30 days .
Month 12 has 31 days .

2.2. POINTER 329
Here, days is the address of the first element of the array, ‘days +ind’ is the address of
elementdays[ind]and*(days + ind)is the value of that element, just asdays[ind]is.
The loop references each element of the array, in turn, and printsthe contents of what it
finds. Another example is

# include< stdio .h >
2
intmain () {
4 int* ptr ;
intarrVal [7] = {44 , 55 , 66 , 77};
6 ptr = & arrVal ;
inti ;
8 for( i = 0; i <= 4; i ++) {
printf (" arrVal [% d ]: value is %d and address is %p\n" , i ,
*( ptr + i) , ( ptr + i));
10 }
return0;
12}



arrVal [0]: value is 44 and address is 0 xbf 85 ad 84
arrVal [1]: value is 55 and address is 0 xbf 85 ad 88
arrVal [2]: value is 66 and address is 0 xbf 85 ad 8c
arrVal [3]: value is 77 and address is 0 xbf 85 ad 90


In C, when an integer is pointed as pointer-to-address-of-integer by a character pointer
variable, then the character variable can addressed to each byteof the integer. An integer
variable is a 4 bytes long. If the address of this integer variable is pointed by character
pointer, i.e. which is one byte long then it can points to each of the byte of the integer
variable. Assume an integer variable is ‘a’. This integer variable is 4 bytes long. The
allocated memory for this integer variable shall be looked like
B[2] B[3] B[4] B[5] B[6] B[7] B[8] B[9] B[10] B[11]
xxxxxxxxxxxxxxxx
a
Here, bytes are labeled asB[2] and so on. The address of integer variable ‘a’ is pointed
by a pointer variable, which ischardata type, as shown in syntax given below.

inta;
2char*x;
x = (char*) &a;


Variable ‘x’ can access to each byte of the integer variable ‘a’.
B[2] B[3] B[4] B[5] B[6] B[7] B[8] B[9] B[10] B[11]
xxxxxxxxxxxxxxxx
x

330 Array & Pointer
See the example below:

1# include< stdio .h >
3intmain () {
inta ;/* Integer variable . */
5 char* x;/* Character pointer */
x = (char*) &a;/* Pointer to the address of integer . */
7 a = 512;
x [0] = 0;/* Change value of first byte of integer */
9 printf ("%d\n", a);
return0;
11}



512


Initially, the value assigned to integer variable is stored in memory as shown in the figure
given below.
x[3] x[2] x[1] x[0]
00000000 00000000 00000001 00000000
x a
When we change the data of bytex[0] the new value of integer variable ‘a’ is 512. The
above example is modified as

1# include< stdio .h >
3intmain () {
inta ;/* Declare integer variable . */
5 char* x;/* Presumes that , data at pointed *
* address is characters type . */
7 x = (char*) &a;/* Pointer to the address of integer . */
a = 512;
9 x [0] = 1;/* Change value of first byte of integer */
printf ("%d\n", a);
11 return0;
}



513


Now, the memory representation is like
x[3] x[2] x[1] x[0]
00000000 00000000 00000001 00000001
x a
It gives the resulta= 513.

2.2. POINTER 331
2.2.10 Pointer to Pointer
Expression of N-element array of pointer ‘ptr’ can be converted into a pointer ‘ptr’ and
its value is the address of first element of the array. If “ptr” is “pointer to char”, then an
expression of type “N-element array of pointer to char” will be converted to “pointer to
pointer to char”.

1# include< stdio .h >
# include< string .h >
3# include< stdlib .h >
5/* The function printIt returns as character pointer */
char* printIt (const char** strs , size_t size ) {
7
size_t i , len = 0;
9 for( i = 0; i < size ; i ++)
len += strlen ( strs [i ]) ;
11 printf (" Total characters in array are : %d .\ n" , len );
char* s = malloc ( len *sizeof(* s));
13 if(! s) {
perror (" Can ’t allocate memory !\ n");
15 exit ( EXIT_FAILURE );
}
17
for( i = 0; i < size ; i ++) {
19 strcat (s , strs [ i ]) ;
}
21 returns;
free ( s);
23}
25intmain (void) {
const char* test [ ] = {" ABC "," DEF ","G","H"};
27 /* Character pointer for s */
char* s;
29 /* Character pointer s is pointed - to *
* character pointer printIt */
31 s = printIt ( test , 4) ;
printf (" Concated string is : %s\ n" , s);
33 /* Free allocated memory that was *
* allocated by function printIt . */
35 free ( s);
returnEXIT_SUCCESS ;
37}



Total characters in array are : 8.
Concated string is : ABCDEFGH


Another example of the pointer is given below

# include< stdio .h >

332 Array & Pointer
2
intmain (void) {
4 /* Character to pointer . */
charch =’A ’;
6 char* chptr = & ch ;
/* Integer to pointer . */
8 inti = 20;
int* intptr = &i;
10 /* Float to pointer . */
floatf = 1.20000;
12 float* fptr = &f;
/* String to pointer . */
14 char* ptr =" It is string .";
/* Print all . */
16 printf (" [% c], [% d] ", * chptr , * intptr );
printf (" [% f], [% c] ", * fptr , * ptr );
18 printf (" [% s ]\ n", ptr );
return0;
20}



[A], [20] , [1.200000] , [ I], [ It is string .]


The following is an example for pointer to an array of integer.

1# include< stdio .h >
3intmain () {
/* Pointer to array having only 5 integer *
5 * elements . Size of integer is four bytes . */
int(* ptr ) [5];
7 /* Array of 5 integers , each integer is 4 bytes long . *
* Elements should equal to the size of pointer to array . */
9 intarr [5] = {1 , 2, 3, 4, 5};
inti ;
11 /* Take the contents of what *
* the array pointer points at */
13 ptr = & arr ;
/* Prints the contents . */
15 for( i = 0; i < 5; i ++) {
printf (" value : %d\n", (* ptr )[ i ]) ;
17 }
}



value : 1
value : 2
value : 3
value : 4
value : 5

2.2. POINTER 333
In above example, if number of elements in pointer to array (ptr) are not equal to the
number of elements in the array (arr) then relation

1ptr =& arr


will give the warning “assignment of incompatible type”. Following is another example
in which pointer to an array of character points to the array of integers. And values are
printed in output at fourth byte position.

1# include< stdio .h >
3intmain () {
/* Pointer to array of 5 characters . *
5 * Size of each character is one byte . */
char(* ptr ) [5];
7 /* Array of 5 integers , each integer is 4 bytes long . */
intarr [5] = {1 , 2, 3, 4, 5};
9 inti ;
/* Take the contents of what the arr pointer *
11 * points at by the ptr . Here character type *
* pointer points to integer array . Pointer *
13 * ptr is itself one byte long but points to *
*4 byte long integer . So , value shall be *
15 * printed after each four bytes position */
ptr = & arr ;
17 /* Prints the contents . */
for( i = 0; i <5; i ++) {
19 printf (" value : %d\n", (* ptr )[ i ]) ;
}
21}



value : 1
value : 0
value : 0
value : 0
value : 2


In following example, pointer of array points to the array of characters.

1# include< stdio .h >
3intmain () {
/* Pointer to array of 5 characters . *
5 * Size of each character is one byte . */
char(* ptr ) [5];
7 /* Array of 5 characters . Each character size is one byte . */
chararr [5] = {’1 ’,’2 ’,’3 ’,’4 ’,’5 ’};
9 inti ;
/* Take the contents of what the arr *
11 * pointer points at by the ptr . */
ptr = & arr ;

334 Array & Pointer
13 /* Prints the contents . */
for( i = 0; i < 5; i ++) {
15 printf (" value : %c\n", (* ptr )[ i ]) ;
}
17}



value : 1
value : 2
value : 3
value : 4
value : 5


In the following example, a function prototype

1char* str_func (char* str )


is declared, which returns a pointer to an character string.

1# include< stdlib .h >
3char* str_func (char* str ) {
/* Flush the pointer value to NULL . */
5 char* s = NULL ;
/* Pass the pointer of str to s*
7 * from the location of str +0. */
s = str ;
9 returns;
}
11
main (intargc ,char* argvc [ ]) {
13 /* sample string . */
chars [100] =" The Sarnath .";
15 char* st ;
/* Pass pointer of char string returned *
17 * by the function str_func (s) to st . */
st = str_func (s);
19 /* Print the result */
printf ("%s\n", st );
21 return0;
}



The Sarnath .


Above example is similar to the example given below.

1# include< stdlib .h >
# defineSTRLEN 1024
3
char* str_func (char* str ) {
5 char* s = NULL ;

2.2. POINTER 335
/* Allocate the required memory space . */
7 s = malloc (sizeof(char) *( STRLEN + 1) );
/* Copy contents of str into memory */
9 memcpy (s , str , STRLEN );
/* Return the pointer of memory location */
11 returns;
free ( s);
13}
15main (intargc ,char* argvc [ ]) {
/* sample string . */
17 chars[ STRLEN ] =" The Sarnath .";
char* st ;
19 /* Pass pointer of char string returned *
* by the function str_func (s) to st . */
21 st = str_func (s);
/* Print the result */
23 printf ("%s\n", st );
return0;
25}



The Sarnath .


In the following example, we pass the pointer location of ‘str’ pointerto another pointer
‘s’ after increasing the pointer of ‘str’ bycharposition (equivalent to 2 bytes) instrfunc()
body.

1# include< stdlib .h >
3char* str_func (char* str ) {
char* s = NULL ;
5 /* Pass the pointer of str to s*
* from the location of str +2. */
7 s = str + 2;
returns;
9}
11main (intargc ,char* argvc [ ]) {
/* sample string . */
13 chars [100] =" The Sarnath .";
char* st ;
15 /* Pass pointer of char string returned *
* by the function str_func (s) to st . */
17 st = str_func (s);
/* Print the result */
19 printf ("%s\n", st );
return0;
21}



e Sarnath .

336 Array & Pointer
Again modified form of above example.

1# include< stdlib .h >
3char* str_func (char* str ) {
char* s = NULL ;
5 while(* str !=’\0 ’) {
if(! s && * str ==’ ’) {
7 /* Pass the pointer of str to s*
* from the location of str +1 *
9 * where str has ’ ’ character . */
s = str +1;
11 }
str ++;
13 }
returns;
15}
17main (intargc ,char* argvc [ ]) {
/* sample string . */
19 chars [100] =" The Sarnath .";
char* st ;
21 /* Pass pointer of char string returned *
* by the function str_func (s) to st . */
23 st = str_func (s);
/* Print the result */
25 printf ("%s\n", st );
return0;
27}



Sarnath .


Parentheses are used to define the priority of the pointer. See two declarations

1char* fp ()/* Type 1 */
char(* fp ) ()/* Type 2 */


In first type declaration, ‘fp’ is a function that returns a pointer tochar. In second type
declaration the parentheses around ‘*fp’ have the highest priority, so ‘fp’ is a pointer to
a function returningchar, i.e. it holds the address of function object which returns char
data type. A pointer of pointer example is given below.

# include< stdio .h >
2intmain () {
intvar ;/* Variable var . */
4 int* ptr ;/* Pointer ptr . */
int** pptr ;/* Pointer of the pointer , pptr . */
6 var = 1234;
/* Take the address of var */
8 ptr = & var ;
/* Take the address of ptr */

2.2. POINTER 337
10 pptr = & ptr ;
/* Read the value using pptr */
12 printf (" Value of var = %d\n" , var );
printf (" Value at * ptr = %d\n", * ptr );
14 printf (" Value at ** pptr = %d\n" , ** pptr );
return0;
16}



Value of var = 1234
Value at * ptr = 1234
Value at ** pptr = 1234


The memory bytes used by the variables declared in above examples are shown in the
following figure.
0×20 0×21 0×22 0×23 0×24 0×25
var
00000000 00000000 00000100 11010010
var=1234
0×40 0×41 0×42 0×43 0×44 0×45
*ptr
00000000 00000000 00000000 00100001
ptr=&var = 0×21
0×60 0×61 0×62 0×63 0×64 0×65
**pptr
00000000 00000000 00000000 010000001
pptr=&ptr=0×41
Example of pointer to pointer of an array is given below.

1# include< stdio .h >
3intmain () {
char* ptr =" Arun ";/* Pointer ptr . */
5 char** pptr ;
pptr = & ptr ;
7 while(*(* pptr ) !=’\0 ’) {
printf (" Value = %c\n", *(* pptr ));
9 (* pptr ) ++;
}
11 return0;
}



Value = A
Value = r
Value = u
Value = n

338 Array & Pointer
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58 0×59
A r u n
0×81 0×82 0×83 0×84
0×53
ptr
0×91 0×92 0×93 0×94
0×81
pptr
From the above example code, the code line

char* ptr =" Arun ";/* Pointer ptr . */


tells that, in memory, string “Arun ” is stored. The memory location at which first
character ‘A’ is stored is assigned to the pointer variable ‘ptr’. Thus‘ptr’ points to
that memory cell which stores address of ‘A’. From the figure, its value is 0×53. Note
that asterisk used during variable declaration, it makes that variable a pointer. Once
the variable is declared as pointer and if asterisk is prefixed to it, it returns the value
stored at address contains by pointer’s memory cell. After pointer’s declaration, they are
identified by their names without using asterisk prefixed.

1char** pptr ;
pptr = & ptr ;


These lines tell that second pointer variable ‘pptr’ is declared and address of ‘ptr’ pointer
variable is assigned to it. Thus the memory cell of pointer variable ‘pptr’ holds value 0×81
(let). The memory address of pointer variable ‘pptr’ itself is 0×91.

printf (" Value = %c\n", *(* pptr ));


In above code line ‘*(*pptr))’ has special meaning. Parenthesis are used to define priority.
First we dereference to pointer variable ‘pptr’ as ‘*pptr’. It returns the value stored at
address pointed by pointer variable ‘pptr’. From above figure, the address pointed by
‘pptr’ is 0×81. So, the value at memory address 0×81 is value 0×53. Though this
address is pointer itself, hence the value at this memory address is address of another
memory location. When we dereference this address as ‘*(*pptr)’(say double dereference
of pointer ‘pptr’) we get the value ‘A’ that is stored at the memory address 0×53. The
code line

1(* pptr ) ++;


adds one in the dereference value of ‘pptr’, actually it is value storedat the memory
address 0×81. This value is address of other location, hence when (*pptr) in incremented
by one, it increases the value 0×53 by one and it becomes 0×54 that is address of string
character ‘r’. Usingwhileloop, we retrieve all the string characters one by one.

1# include< stdio .h >
3intmain () {

2.2. POINTER 339
intnum = 48;
5 int* ptr ;
int** pptr ;
7 int*** ppptr ;
// *** ppptr = ** pptr = * ptr = num ; //
9 ptr = & num ;
pptr = & ptr ;
11 ppptr = & pptr ;
inti = 1;
13 while(i < 5) {
printf (" Value = %d\n", *** ppptr + i);
15 i ++;
}
17 return0;
}



Value = 49
Value = 50
Value = 51
Value = 52



# include< stdio .h >
2
intmain () {
4 intnum = 48;
int* ptr ;
6 int** pptr ;
int*** ppptr ;
8 int**** pppptr ;
ptr = & num ;
10 pptr = & ptr ;
ppptr = & pptr ;
12 pppptr = & ppptr ;
inti = 1;
14 while(i < 5) {
printf (" Value = %d\n", **** pppptr + i);
16 i ++;
}
18 return0;
}



Value = 49
Value = 50
Value = 51
Value = 52



# include< stdio .h >
2
int* sum (inta ,intb) {

340 Array & Pointer
4 static intk [1];
k [0] = a + b;
6 returnk;
}
8
intmain (void) {
10 int* s;
s = sum (1 , 2) ;
12 printf (" Sum is : %d \n", *s);
return0;
14}



Sum is : 3


The example for the array of pointers to an integer is given below:

1# include< stdio .h >
3intmain (void) {
inti ;
5 intArr1 [ ] = {1 , 2};
intArr2 [ ] = {10 , 20};
7 int* ptr [2];
9 ptr [0] = & Arr1 [0];
ptr [1] = & Arr2 [0];
11
for( i = 0; i < 2; i ++) {
13 printf ("%d \t % d\n", *( ptr [0] + i) , *( ptr [1] + i));
}
15 return0;
}



1 10
2 20


The memory arrangement figure of this example is given below. Integer data type stores
values in group of four bytes. In each group of four bytes, the decimal values of ‘Arr1’
and ‘Arr2’ are shown in the following figure.
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58
1 2Arr1
0×81 0×82 0×83 0×84 0×85 0×86 0×87 0×88
10 20Arr2
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×51 0×81ptr

2.2. POINTER 341
The stored integer values are small, hence only one byte of group offour bytes has
values and rest has zeros. From the above example code, the codeline

intArr1 [ ] = {1 , 2};
2intArr2 [ ] = {10 , 20};


declares two arrays, each has two elements. The code line

int* ptr [2];
2
ptr [0] = & Arr1 [0];
4ptr [1] = & Arr2 [0];


declare an array pointer ‘ptr’ of pointer to integers. The array size of the pointer variable
is two. Its first element stored is address of first element of the array ‘Arr1’ and second
element stored is address of first element of the array ‘Arr2’. The code line

printf ("% d \t %d\n", *( ptr [0] + i) , *( ptr [1] + i));


returns the elements of by incrementing pointers fori
th
array indices. Be cautious about
the addition of one with value of normal variable and value of pointer variable. For
example, if an integer type variable ‘a’ assigned a value 10 and it is added by one as ‘i+1’
then its result will be 11. This is addition of the two integers. But if there is pointer
variable, say ‘*a’ pointing to address of integers, the datasize of pointer variable is always
four bytes, i.e. size of addresses is always four bytes. Let this pointer variable points to
address 0×10. Then addition of one as ‘a+1’ will be equal to the sum of address and size
of address. In this case result be 0×14. Remember that datasize of pointers is four bytes.
The data type precedented to a pointer variable tells about the type of data stored at
the address pointed by it and how the data is read during dereferencing of the pointer.
In the below example, two different pointers has same datasize.

1# include< stdio .h >
3intmain (void) {
char* c;
5 int* i;
printf ("%d \t %d \n ",sizeof(c) ,sizeof(i));
7 return0;
}



4 4


int *p[ ];
This declaration is array ‘p’ of pointers to an integer. It means, there are multiple arrays
which stores integer type values. The address of first byte of these arrays are stored at
another places in array form which are pointed by ‘p’.

342 Array & Pointer
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58
1 2Arr1
0×81 0×82 0×83 0×84 0×85 0×86 0×87 0×88
10 20Arr2
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×51 0×81int *p[ ];
p
In the above figure, there are two arrays, ‘Arr1’ and ‘Arr2’. The addresses of first
bytes of these two arrays are 0×51 and 0×81 respectively. These addresses are further
arranged in array form whose first byte address (say 0×91) is pointed by pointer ‘p’. A
pointer is always four bytes long in 32 bit system. So, whatever is thesize of address of
first bytes, byte address is stored in four bytes long memory space.
int **p[ ];
This declaration stands for array of pointers ‘p’ that point to pointers to integer values.
Let we have two integer variables ‘i’ and ‘j’. These numbers are arranged in memory as
shown in following figure.
0×10 0×11 0×12 0×13 0×14 0×15 0×16 0×17 0×18 0×19
1 2
int i; int j;
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37 0×38 0×39
0×10 0×16
int *A; int *B;
The addresses of the integer variables are pointed by pointers ‘A’ and ‘B’ respectively.
The addresses of these two pointers (not pointee) are arrangedas array of another pointer
‘p’ as shown in the following figure.
0×70 0×71 0×72 0×73 0×74 0×75 0×76 0×77
0×30 0×36int **p[ ];
p
Now, the pointer ‘p’ can be dereferences using this pointer ‘p’. The equivalent C codes
are given below:

1# include< stdio .h >

2.2. POINTER 343
3intmain () {
inti =1;
5 intj =2;
int* A =& i;
7 int* B =& j;
int** p [2];
9 p [0]=& A;
p [1]=& B;
11 printf ("%d \n",*(*( p [0]) ));
printf ("%d \n",*(*( p [1]) ));
13 return0;
}



1
2


int (*p)[ ];
This is explained as pointer ‘p’ to an array of integers. Parenthesesenclosing ‘*p’ has
higher priority, hence pointer definition goes with ‘p’ while array definition (by []) goes
to values stored at pointee address. Let we have an array ‘Arr’.
0×10 0×11 0×12 0×13 0×14 0×15 0×16 0×17
12345 12346Arr
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
0×10int (*p)[ ];
p
The pointer ‘p’ points to the first element of the array ‘Arr’ as shown in above figure.
The C equivalent codes are given below:

# include< stdio .h >
2
intmain () {
4 intArr [2]={12345 ,12346};
int(* p) [2];
6 p =& Arr ;
printf ("%d \n",(* p) [0]) ;
8 printf ("%d \n",(* p) [1]) ;
return0;
10}



12345
12346

344 Array & Pointer
int (**p)[ ];
It constructs a pointer ‘p’ which points to the address of anotherpointer to an array of
integers. The memory arrangement and its relation is shown in the following figure.
0×10 0×11 0×12 0×13 0×14 0×15 0×16 0×17
1 2Arr1
0×20 0×21 0×22 0×23 0×24 0×25 0×26 0×27
0×10int (*A)[ ];
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
0×20int (**p)[ ];
p
C codes for above declaration are given below:

# include< stdio .h >
2
intmain (void) {
4 intArr [2]={1 ,2};
int* A;
6 A =& Arr [0];
int** p;
8 p =& A;
printf ("%d\n", ** p);
10 return0;
}



1


int *(*p)[ ];
It constructs a pointer ‘p’ which points to the array of pointers those are pointing to
integers. The memory arrangement and its relation is shown in the following figure.

2.2. POINTER 345
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58
1i
0×61 0×62 0×63 0×64 0×65 0×66 0×67 0×68
10j
0×71 0×72 0×73 0×74 0×75 0×76 0×77 0×78
0×51 0×61int *P[ ];
0×81 0×82 0×83 0×84 0×85 0×86 0×87 0×88
0×71int *(*p)[ ];
p
The C example is

1# include< stdio .h >
3intmain (void) {
inti = 105 , j = 201;
5 int* A [2] = {& i , &j };
int*(* p) [];
7 p =& A;
printf ("%d \t %d\n", *(* p) [0] , *(* p) [1]) ;
9 return0;
}



105 201


int (*p[ ])[ ];
It constructs array of pointer ‘p’ which points to the array of integers. The memory
arrangement and its relation is shown in the following figure.
0×51 0×52 0×53 0×54 0×55 0×56 0×57 0×58
1 2Arr1
0×81 0×82 0×83 0×84 0×85 0×86 0×87 0×88
10 20Arr2
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×51 0×81int (*p[ ])[ ];
p
The C example is given below:

346 Array & Pointer

1# include< stdio .h >
3intmain (void) {
intArr1 [2] = {1 , 2};
5 intArr2 [2] = {4 , 5};
int(* p [2]) [2];
7 p [0] = & Arr1 ;
p [1] = & Arr2 ;
9 printf ("%d \t %d\n", (* p [0]) [1] , (* p [1]) [0]) ;
return0;
11}



2 4


int *p();
It constructs a function which returns a pointer pointing to an integer value. The memory
arrangement of this declaration is shown below:
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
int v;
0x14AEFC
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×32int *p();
p
C code for above declaration are given below. In this example, the returned pointer
pointed to an integer value.

1# include< stdio .h >
3int*p(int*j) {
*j = 10 * (* j);
5 returnj;
}
7
intmain (void) {
9 intv = 10;
printf ("%d\n", *p (& v));
11 return0;
}



100


We can also return a pointer which points to a real value, like double orfloat type values.
See the example given below:

2.2. POINTER 347

1# include< stdio .h >
3double*p (double*j) {
*j = 10 * (* j);
5 returnj;
}
7
intmain (void) {
9 doublev = 10;
printf ("% lf \n", *p (& v));
11 return0;
}



100.000000


int (*p)();
It constructs a pointer ‘p’ which points to a function which returnsan integer value. The
C codes are

1intmyf (intr){
return2* r;
3}
(* p) () =& myf ;


The memory arrangement and its relation is shown in the following figure.
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
myf 3.14
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×32int (*p)();
p
int (**p)();
It constructs a pointer ‘p’ which points to another pointer to a function. The function
being pointed here returns an integer value.

348 Array & Pointer
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
myf 100
0×81 0×82 0×83 0×84 0×85 0×86 0×87 0×88
0×32int (*f)();
f
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×81int (**p)();
p
In the above figure, the function ‘myf’ returns the pointer address of computed value
‘100’ via a pointer variable ‘j’. Pointer variable ‘j’ points to the address of 0×22 (for
example). The C equivalent codes are given below:

# include< stdio .h >
2
intmyf (intj) {
4 j = 10 * j;
returnj;
6}
8intmain (void) {
intv = 10;
10 int(* f) () ;
int(** p) () ;
12 f = & myf ;
p = & f;
14 printf ("%d\n", (** p )(v));
return0;
16}



100


int *(*p)();
It constructs a pointer ‘p’ which points to a function. The functionbeing pointed here
returns pointer to an integer value.

2.2. POINTER 349
0×20 0×21 0×22 0×23 0×24 0×25 0×26 0×27
100
j=0×22
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
myf 0×22
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×32int *(*p)();
p
The C equivalent codes are given below:

1# include< stdio .h >
3int* myf (int*j) {
*j = 10 * (* j);
5 returnj;
}
7
intmain (void) {
9 intv = 10;
int*(* p) () ;
11 p =& myf ;
printf ("%d\n", *(* p ) (& v));
13 return0;
}



100


int (*p())();
It constructs a function ‘p’, which returns value of a pointer to function (say ‘myf’), where
function ‘myf’ returns an integer value.
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
myf 100
0×40 0×41 0×42 0×43 0×44 0×45 0×46 0×47
p 0×32
The equivalent C codes are given below:

350 Array & Pointer

1# include< stdio .h >
3intmyf (intj) {
j = 10 * j;
5 returnj;
}
7
int*p(int*j) {
9 j = myf (* j);
returnj;
11}
13intmain (void) {
intv = 11;
15 int*(* p () ) () ;
printf ("%d\n", *p (& v));
17 return0;
}



110


int (*p[ ])();
It constructs an array of pointers ‘p’ which points to the addressof functions. Functions
returns integer type value.
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
myf1 12
0×40 0×41 0×42 0×43 0×44 0×45 0×46 0×47
myf2 13
0×91 0×92 0×93 0×94 0×95 0×96 0×97 0×98
0×32 0×42int (*p[])();
p
The C codes are

1# include< stdio .h >
3intmyf1 (intj) {
return10 * j;
5}
7intmyf2 (intj) {
return5 * j;

2.2. POINTER 351
9}
11intmain (void) {
intv = 11;
13 int(* p [2]) () ;
p [0]=& myf1 ;
15 p [1]=& myf2 ;
printf ("%d \t %d\n", (* p [0]) (v) ,(* p [1]) (v));
17 return0;
}



110 55


int (*p())[ ];
It constructs a function ‘p’ which returns a pointer value. The return pointer points to
an array of integers.
0×20 0×21 0×22 0×23 0×24 0×25 0×26 0×27
100 200j[]
0×30 0×31 0×32 0×33 0×34 0×35 0×36 0×37
myf 0×20
The C codes are

1# include< stdio .h >
intj [2]={100 ,200};
3
int* myf () {
5 returnj;
}
7
intmain (void) {
9 int(* myf () ) [];
printf ("%d \t %d\n", (* myf () ) [0] , (* myf () ) [1]) ;
11 return0;
}



100 200

352 Array & Pointer
2.2.11 Pointer Casting
Suppose a pointer is declared as

1int*i;


It declares a variable that points to the address of other variable.This declaration also
tells about the data type of pointed address. In above declaration, the address, which
‘i’ will point, shall be integer type. In other words, the data started from the pointed
address shall be grouped in four successive bytes. See the code snippets

1unsigned int i =1818004170;
int*j =& i ;// let address of i is 0 x21
3printf ("% d",*j);// call value started at address 0 x21


0×20 0×21 0×22 0×23 0×24 0×25
00110110 00101110 10001010 11001010
i= 1818004170
Data typeintfor the pointer ‘j’ tells us that when we retrieve data from the address of
‘i’, data must be read fromfour successive memory bytesstarted at the address of
‘i’ and onward. If address data type is different from the data typeof the pointer itself,
then pointers are typecast suitably to tell the compiler about the number of bytes being
read or write at once started from the address. Normally, in pointer casting, data size of
the pointer and address pointed by the pointer are made equal. Seethe following code
snippets.

1# include< stdio .h >
3intmain () {
/* A double floating type value . */
5 doubled =1000000.22255;
/* A pointer of long int type . */
7 long int* iptr ;
/* Cast address of the double floating *
9 * type number into the long int type . */
iptr =(long int*) &d ;
11 /* Retrieve value from the address pointed *
* by iptr and convert it into double type . */
13 printf ("% lf ", *(double*) iptr );
return0;
15}



1000000.222550

2.2. POINTER 353
2.2.12 Pointer as Structure
A structure object can be assigned to a pointer to object by assigning it the address of
the structure object.

1# include< stdio .h >
3structStruc {
inti ;
5 charch ;
};
7
intmain (void) {
9 /* Structure object obj */
structStruc obj ;
11 /* Pointer structure object strucObj *
* assigned the address of obj */
13 structStruc * strucObj = & obj ;
15 /* Assign values to elements of structure */
strucObj ->i = 5;
17 strucObj -> ch =’A ’;
19 /* Access value of elements of structure */
printf (" [% d] [% c ]\ n ", strucObj ->i , strucObj -> ch );
21 return0;
}



[5] [A]


In the above example, code line

1structStruc obj ;


creastes a structure object ‘obj’. The code line

1structStruc * strucObj = & obj ;


creates pointer struct object ‘strucObj’ and the address of ‘obj’ is assigned to it. Now
the structure elements can be accessed by using pointer object and using operator ‘−>’
as shown in above example.

354 File & Data Structure

3.1. INPUT OUTPUT 355
3
File & Data Structure
Standard Input-Output and access of files is a main part of computer programming.
In this chapter we shall discuss the importance and methodology ofaccessing system and
user define files.
3.1 Input Output
A C program under execution opens automatically three standard streams namedstdin,
stdout, andstderr. These are attached to every C program. The first standard stream
is used for input buffering and the other two are used for outputs.These streams are
sequences of bytes.

1intmain () {
intvar ;
3 /* Use stdin for scanning an *
* integer from keyboard . */
5 scanf ("%d", & var );
/* Use stdout for printing a character . */
7 printf ("%d", var );
return0;
9}


By defaultstdinpoints to the keyboard andstdoutandstderrpoint to the screen. It is
possible under Unix and may be possible under other operating systems to redirect input
from or output to a file or both.
3.1.1 Handling File Directory
Sometimes user needs to read, create, delete or change a directory. Directories are sep-
arated by symbol ‘/’. To represent current working directory or parent directory of the
current working directory, dots are used as ‘./’ and ‘../’ respectively. ‘/..’ has same
meaning as ‘/’.
3.1.2 Change Directory
Current working directory of a program is the location where all thetemporary or per-
manent files are stored and retrieved by default. Location of current working directory of
a program may be changed to other directory by usingchdir() function. Syntax of this
function is

1chdir (< directory path >)


On successful change of location of old working directory to new location of working
directory, it returns ‘0’ otherwise ‘-1’. An example of the function isgiven below.

356 File & Data Structure

1# include< stdio .h >
# include< string .h >
3# include< stdlib .h >
5intmain (void) {
chardr [10];
7 intret ;
printf (" Enter the directory name :" );
9 scanf ("%s", & dr );
ret = chdir ( dr );
11 printf ("%d\n", ret );
returnEXIT_SUCCESS ;
13}


3.1.3 FILE pointers
The<stdio.h>header contains a definition for a typeFILE(usually via a data type)
which is capable of processing all the information needed to exercisecontrol over a stream,
including its file position indicator, a pointer to the associated buffer (if any), an error
indicator that records whether a read/write error has occurredand an end-of-file indicator
that records whether the end of the file has been reached. Theremay be multiple FILE
descriptors for a single file.

1# include< stdio .h >
3intmain (void) {
FILE * f1 , * f2 ;
5 /* First discriptor for file a. txt */
f1 = fopen ("a. txt ","r");
7 if(! f1 ) {
printf (" Unable to open file a. txt \n" );
9 return1;
}
11 /* Second discriptor for file a. txt */
f2 = fopen ("a. txt ","r");
13 if(! f2 ) {
printf (" Unable to open file a. txt \n" );
15 return1;
}
17
/* Change f1 location */
19 fseek (f1 , 7, SEEK_SET );
21 /* Change f2 location */
fseek (f2 , 14 , SEEK_SET );
23 /* Print results */
printf (" Position of f1 is %d\n" , ftell ( f1 ));
25 printf (" Position of f2 is %d\n" , ftell ( f2 ));
/* close streams */

3.1. INPUT OUTPUT 357
27 fclose ( f1 );
fclose ( f2 );
29 return0;
}



Position of f1 is 7
Position of f2 is 14


But this way of accessing file is not safe as both file descriptors access file simultaneously.
To avoid any problems arise due to mixing of streams and descriptors, a file locking facility
should be used to avoid simultaneous access.
Locking & Unlocking a File
Theflockfile() function acquires the internal locking to the file stream. It ensures that no
other stream may access the file while the file is locked and accessed by current stream. If
there is no further required to access the file, then file is unlocked byfunlockfile() function.
funlockfile() function is called if locking function is able to lock the file.

# include< stdio .h >
2# include< stdlib .h >
4intmain (void) {
FILE * f1 , * f2 ;
6 /* first discriptor for file a. txt */
f1 = fopen ("a. txt ","r");
8 /* lock the file */
flockfile ( f1 );
10 if(! f1 ) {
printf (" Unable to open file a. txt \n" );
12 return1;
}
14 /* change f1 location */
fseek (f1 , 7, SEEK_SET );
16 printf (" Position of f1 is %d\n" , ftell ( f1 ));
/* unlock the file */
18 funlockfile ( f1 );
/* close streams */
20 fclose ( f1 );
22 return0;
}



Position of f1 is 7


But direct locking of the file byflockfile() function may return error if the file is already
locked. So, it is safe to useftrylockfile() function to avoid multiple locking of the same
file simultaneously.

358 File & Data Structure

1# include< stdio .h >
# include< stdlib .h >
3
intmain (void) {
5 FILE * f1 , * f2 ;
/* first discriptor for file a. txt */
7 f1 = fopen ("a. txt ","r");
/* lock the file */
9 ftrylockfile ( f1 );
if(! f1 ) {
11 printf (" Unable to open file a. txt \n" );
return1;
13 }
/* change f1 location */
15 fseek (f1 , 7, SEEK_SET );
printf (" Position of f1 is %d\n" , ftell ( f1 ));
17 /* unlock the file */
funlockfile ( f1 );
19 /* close streams */
fclose ( f1 );
21
return0;
23}



Position of f1 is 7


In the above example, we are trying to lock a file by using functionftrylockfile() and
seeking file stream location in the file. If the file is already locked by other program,
thenftrylockfile() function will fail to lock the file and stream will try to access the file
without locking it (simultaneous access). This is why, before accessing to the file, its
locking status must be checked.

1# include< stdio .h >
# include< stdlib .h >
3
intmain (void) {
5 FILE * f1 , * f2 ;
/* first discriptor for file a. txt */
7 f1 = fopen ("a. txt ","r");
/* try to lock the file and check lock status */
9 if( ftrylockfile ( f1 ) == 0) {
if(! f1 ) {
11 printf (" Unable to open file a. txt \n" );
return1;
13 }
/* change f1 location */
15 fseek (f1 , 7, SEEK_SET );
printf (" Position of f1 is %d \n" , ftell ( f1 )) ;
17 }
/* unlock the file */

3.1. INPUT OUTPUT 359
19 funlockfile ( f1 );
/* close streams */
21 fclose ( f1 );
return0;
23}



Position of f1 is 7


Reading/Scanning Directory
In C, there is no dedicated function to read or scan a directory butusingreaddiror
scandirfunction, a directory can be read or scanned respectively.

1# include< stdio .h >
# include< dirent .h >
3
intmain () {
5 DIR * dir ;
structdirent * dp ;
7 char* file_name ;
dir = opendir (".");
9 while(( dp = readdir ( dir )) != NULL ) {
printf (" debug : %s\n", dp -> d_name );
11 if(! strcmp (dp -> d_name ,".") || ! strcmp (dp -> d_name ," .. ")) {
/* your code here . */
13 }else{
file_name = dp -> d_name ; // use it
15 printf (" file_name : \"% s \"\ n", file_name );
}
17 }
closedir ( dir );
19 return0;
}



debug : .
debug : ..
debug : nbproject
file _ name : " nbproject "
debug : main .c
file _ name : " main .c"


Similarly

# include< dirent .h >
2
intmain (void) {
4 structdirent ** namelist ;
intn ;
6

360 File & Data Structure
n = scandir (".", & namelist , NULL , alphasort );
8 if(n < 0)
perror (" scandir ");
10 else{
while(n - -) {
12 printf ("%s\ n", namelist [ n]-> d_name );
free ( namelist [n ]) ;
14 }
free ( namelist );
16 }
}



nbproject
main .c
image . bmp
dist
..
.


Open a File
To open or close a file, the<stdio.h>library has three functions:fopen,freopen, and
fclose. We can open a file to read or write as

# include< stdio .h >
2FILE * fopen (const char* filename ,const char* mode );
FILE * freopen (const char* filename ,const char* mode , FILE * stream );


fopenandfreopenopens the file whose name is in the string pointed-by a file name and
associates a stream with it. Both return a pointer to the object controlling the stream.
If the open operation fails, a null pointer is returned and error is set. On successfully
opening of a file, the error and end-of-file indicators are cleared.freopendiffers from
fopenby a bit and the file pointed-by ‘stream’ is firstly closed if it already open and
errors related to close operation are ignored. File operation mode for both file opening
functions points-to a string consisting of one of the following sequences:

3.1. INPUT OUTPUT 361
Mode Explanation
r Open a text file for reading
w Truncate to zero length or create a text file for writing
a Append or open or create text file for writing at end-of-file
rb Open binary file for reading
wb Truncate to zero length or create a binary file for writing
ab Append or open or create binary file for writing at end-of-file
r+ Open text file for update (reading and writing)
w+ Truncate to zero length or create a text file for update
a+ Append or open or create text file for update
r+b or rb+ Open binary file for update (reading and writing)
w+b or wb+ Truncate to zero length or create a binary file for update
a+b or ab+ Append or open or create binary file for update
Table 3.1: File read and write mode.
Opening a file with read mode (‘r’ as the first character in the mode argument) fails
if the file does not exist or can not be read. Opening a file with append mode (‘a’ as
the first character in the mode argument) causes all subsequentwrites to the file to be
forced to the then-current end-of-file. Opening a binary file with append mode (‘b’ as
the second or third character in the above list of mode arguments)may initially position
the file position indicator for the stream beyond the last data written, because of null
character padding. When a file is opened with update mode (‘+’), bothinput and output
may be performed on the associated stream.

1# include< stdio .h >
# include< stdlib .h >
3
intmain (void) {
5 /* File pointer that is defined in stdlib .h header *
* file and used for file handling by data type FILE */
7 FILE * fo ;
charf_name [10]=" fname . txt ";
9 /* Open file fname . txt in write mode */
fo = fopen ( f_name ,"w");
11 /* Show warning if file can not be open . */
if( fo == NULL ) {
13 printf (" Could not open fname file .\ n" );
exit (0) ;
15 }else{
printf ("%s file is created .\ n" , f_name );
17 }
inti = 0, n;

362 File & Data Structure
19 /* Get the rows up to which data *
* is to be write in the file */
21 printf (" Enter the data rows No . : " );
scanf ("%d", &n);
23 /* Do what you want . */
while(i < n) {
25 fprintf (fo ,"%d %d %d\n", i , i*i , i * i * i);
i ++;
27 }
printf (" Details are written in file %s .\ n" , f_name );
29 /* Close the open file . */
fclose ( fo );
31 /* If every thing gone ok , return success . */
return0;
33}



fname . txt file is opened .
Enter the data rows No . : 10
Details are written in file fname . txt


Close a File
We can close a file pointer by using close function as shown in the following syntax.

1# include< stdio .h >
intfclose ( FILE * stream );


Thefclose() function causes the stream pointed-by ‘stream’ to be flushed and the as-
sociated file is closed. Any unwritten buffered data for the stream are delivered to the
host environment to be written to the file. Any unread buffered data are discarded. The
function returns zero if the stream was successfully closed or stream is encounters with
EOF.

# include< stdio .h >
2# include< stdlib .h >
4intmain (void) {
/* File pointer that is defined in stdlib .h header *
6 * file and used for file handling by data type FILE */
FILE * fo ;
8 charf_name [10]=" fname . txt ";
/* Open file fname . txt in write mode */
10 fo = fopen ( f_name ,"w");
/* Show warning if file can not be open . */
12 if( fo == NULL ) {
printf (" Could not open fname file .\ n" );
14 exit (0) ;
}else{
16 printf ("%s file is created .\ n" , f_name );

3.1. INPUT OUTPUT 363
}
18 inti = 0, n;
/* Get the rows up to which data *
20 * is to be write in the file */
printf (" Enter the data rows No . : " );
22 scanf ("%d", &n);
/* Do what you want . */
24 while(i < n) {
fprintf (fo ,"%d %d %d\n", i , i*i , i * i * i);
26 i ++;
}
28 printf (" Details are written in file %s .\ n" , f_name );
/* Close the open file . */
30 fclose ( fo );
printf ("%s file is closed .\ n", f_name );
32 /* If every thing gone ok , return success . */
return0;
34}



fname . txt file is opened .
Enter the data rows No . : 10
Details are written in file fname . txt
fname . txt file is closed .


fflushfunctionThe synopsis of this function is

# include< stdio .h >
2intfflush ( FILE * stream );


If stream points to output or update stream in which the most recent operation was not
input, thefflushfunction causes any unwritten data for that stream to be deferred to the
host environment to be written to the file. A simple example is

# include< stdio .h >
2/* For prototype for sleep () */
# include< unistd .h >
4
intmain (void) {
6 intcount ;
for( count = 10; count >= 0; count - -) {
8 /* Lead with a CR */
printf ("\ rSeconds until launch : " );
10 if( count > 0)
printf (" %2 d ", count );
12 else
printf (" blastoff !\ n");
14 /* Force output now !! */
fflush ( stdout );
16 /* The sleep () delayed system by number of seconds : */
sleep (1) ;

364 File & Data Structure
18 }
return0;
20}



Seconds until launch : 10
Seconds until launch : blastoff !


The effect of usingfflush() on an input stream is undefined. Sometime a program needed
huge RAM and disk memory to perform a programming job. In between the process
of job, if there is requirement of log data (say) to be stored in disk (outstream), then
OS waits till termination of the resource consuming program and then it writes log data
into the disk file. If the program abrupptly terminated or terminated with error, whole
unwritten log data is vanished. To overcome this problem,fflushfunction is used to force
OS to write log data immediated into the disk file. It is good programminghabbit that
each time when data file being written by program (like using functionfprintfetc), it
should be followed byfflushfunction.
setbuffunctionThe syntax of this function is

# include< stdio .h >
2voidsetbuf ( FILE * stream ,char* buf );


It returns no value. Thesetbuffunction is equivalent to thesetvbuffunction.setvbuf
function uses two more parameters ‘mode’ and ‘size’. A simple exampleis

# include< stdio .h >
2
intmain () {
4 FILE * fp ;
charlineBuf [1024];
6 /* b. txt must be in executable ’s dir */
fp = fopen ("b. txt "," rb ");
8 setbuf (fp , NULL );// set to unbuffered
fclose ( fp );
10 return0;
}


setvbuffunctionThe function syntax is

1# include< stdio .h >
intsetvbuf ( FILE * stream ,char* buf ,intmode , size_t size );


Thesetvbuffunction may be used only after the stream pointed-by ‘stream’ has been
associated with an open file and before any other operation is performed on the stream.
The argument size specifies the ‘size’ of the array. The contents of the array at any time
are indeterminate. Thesetvbuffunction returns zero on success, or nonzero if an invalid
value is given for ‘mode’ or if the request cannot be honored. A simpleexample is

# include< stdio .h >

3.1. INPUT OUTPUT 365
2
intmain () {
4 FILE * fp ;
charlineBuf [1024];
6 /* b. txt must be in executable ’s dir */
fp = fopen ("b. txt ","r");
8 /* set to line buffering */
setvbuf (fp , lineBuf , _IOLBF , 1024) ;
10 fclose ( fp );
return0;
12}


setvbufis invoked with ‘mode’ has valueIOFBF and ‘size’ when ‘buf’ is not a null
pointer. Again, if ‘buf’ is a null pointer then ‘mode’ has valueIONBF.
fgetpos&fsetposfunctionsThe function syntax is

# include< stdio .h >
2intfgetpos ( FILE * stream , fpos_t * pos );
intfsetpos ( FILE * stream ,constfpos_t * pos );


Thefgetposfunction stores the current value of the file position indicator for the stream
pointed-by ‘stream’ in the object pointed-by ‘pos’. A simple example is

1# include< stdio .h >
3intmain () {
FILE * fName ;
5 intc ;
intn ;
7 fpos_t pos ;
9 fName = fopen (" fname . txt ","r");
if( fName == NULL )
11 perror (" Can not open a file . ");
else{
13 c = fgetc ( fName );
printf (" First char is %c\n" , c);
15 fgetpos ( fName , & pos );
for(n = 0; n < 3; n ++) {
17 fsetpos ( fName , & pos );
c = fgetc ( fName );
19 printf (" Char in position %d is %c\n" , n , c);
}
21 fclose ( fName );
}
23 return0;
}



First char is 0
Char in position 0 is

366 File & Data Structure
Char in position 1 is
Char in position 2 is


fseek&ftellfunctionsThe function syntax is

# include< stdio .h >
2intfseek ( FILE * stream ,long intoffset ,intwhence );
longftell ( FILE * stream );


Thefseekfunction sets the file position indicator for the stream pointed-to the ‘stream’.
For a binary stream, the new position, measured in characters from the beginning of the
file, is obtained by adding ‘offset’ to the position specified by ‘whence’.Three macros
instdio.hcalledSEEKSET,SEEKCUR, andSEEKENDexpand to unique values. If
the position specified by ‘whence’ isSEEKSET, the specified position is the beginning
of the file; if ‘whence’ isSEEKEND, the specified position is the end of the file; and
if ‘whence’ isSEEKCUR, the specified position is the current file position. A binary
stream need not meaningfully supportfseekcalls with a ‘whence’ value ofSEEKEND.
In case ofSEEKEND, ‘offset’ may be a negative count (i.e. within the current extent of
file) or may be a positive count (i.e. position past the current end of file). In the later
case file is extended up to that position and filled with zeros.
0 1 2 3 4 5 6 7 8 9
10111213141516171819
20212223242526272829
(1)
fp
(2)
fseek(fp, 10, SEEKCUR)
(3)
fp
(4)
Figure 3.1: Change in location of file pointer from current file pointer location.

3.1. INPUT OUTPUT 367
0 1 2 3 4 5 6 7 8 9
10111213141516171819
20212223242526272829
(1)
fp
(2)
fseek(fp, -8, SEEKEND)
(3)
fp
(4)
Figure 3.2: Change in location of file pointer from the end of file location.
0 1 2 3 4 5 6 7 8 9
10111213141516171819
20212223242526272829
(1)
fp
(2)
fseek(fp, 10, SEEKSET)
(3)
fp
(4)
Figure 3.3: Change in location of file pointer from the beginning of file location.
A simple example is

1# include< stdio .h >
3intmain () {
FILE * fp ;
5
fp = fopen (" file . txt ","w+");
7 fputs (" This is my file name .", fp );
9 fseek (fp , 7, SEEK_SET );
fputs ("C Programming Langauge " , fp );
11 fclose ( fp );
13 return(0) ;
}

368 File & Data Structure
For output see the file “file.txt”.ftellreturns the current position of file pointer from the
start of the file. Its largest return value is signedlongtype value. Whenftellis used for
obtaining of size of huge files, it fails due to its return size, therefore be cautious when
using for this purpose. Example forftellis given below:

# include< stdio .h >
2
intmain () {
4 FILE * fp ;
intlen ;
6
fp = fopen (" file . txt ","r");
8 if( fp == NULL ) {
perror (" Error opening file ");
10 return( -1) ;
}
12 fseek (fp , 0, SEEK_END );
14 len = ftell ( fp );
fclose ( fp );
16
printf (" Total size of file . txt = %d bytes \n" , len );
18
return(0) ;
20}



Total size of file . txt = 32 bytes


Using the pointer in a function, we can also get the file size as shown in the example given
below.

1# include< stdlib .h >
# include< stdio .h >
3
longgetFileSize (const char* filename ) {
5 longresult ;
FILE * fh = fopen ( filename ," rb ");
7 fseek (fh , 0, SEEK_END );
result = ftell ( fh );
9 fclose ( fh );
returnresult ;
11}
13intmain (void) {
printf ("% ld \n", getFileSize (" file . txt "));
15 return0;
}



Total size of file . txt = 32 bytes

3.1. INPUT OUTPUT 369
fseekandfputccan be used to write a file of specific size. See the example given below.

1# include< stdio .h >
3intmain () {
FILE * fp = fopen (" myfile . txt "," w");
5 fseek (fp , 1024 * 1024 , SEEK_SET );
fputc (’\n ’, fp );
7 fclose ( fp );
return0;
9}


rewindfunctionThe synopsis of the function is

1# include< stdio .h >
voidrewind ( FILE * stream );


Therewindfunction sets the file position indicator for the stream pointed-by ‘stream’ to
the beginning of the file. It is equivalent to

(void) fseek ( stream , 0L , SEEK_SET )


except that the error indicator for the stream is also cleared. A simple example is

1# include< stdio .h >
3intmain () {
FILE * fp ;
5 intch ;
7 fp = fopen (" file . txt ","r");
9 if( fp != NULL ) {
while(! feof ( fp )) {
11 ch = fgetc ( fp );
printf ("%c", ch );
13 }
rewind ( fp );
15
while(! feof ( fp )) {
17 ch = fgetc ( fp );
printf ("%c", ch );
19 }
fclose ( fp );
21 }
23 return(0) ;
}


The output from the file “file.txt” is

370 File & Data Structure

This is C Programming Langauge
This is C Programming Langauge


feoffunctionThe synopsis of the function is

# include< stdio .h >
2intfeof ( FILE * stream );


Thefeoffunction tests the end-of-file indicator for the stream pointed-by ‘stream’ and
returns nonzero if and only if the end-of-file indicator is set for stream, otherwise it returns
zero. A simple example is

# include< stdio .h >
2
intmain (void) {
4 inta ;
FILE * fp ;
6 fp = fopen (" file . txt "," rb ");
/* Read single ints at a time , stopping on EOF or error : */
8 while( fread (& a ,sizeof(int) , 1, fp ) , ! feof ( fp ) &&
! ferror ( fp )){
printf ("I read %d\n", a);
10 }
if( feof ( fp ))
12 printf (" End of file was reached .\ n" );
if( ferror ( fp ))
14 printf (" An error occurred .\ n ");
fclose ( fp );
16 return0;
}



I read 543649385
I read 1735287116
I read 1701279073
End of file was reached .


Reading File
There are two ways to read the stuff in C. In first method data is accepted from terminal.
In second method data is read from a file. Following functions are used in reading data
from a file.
fgetcfunctionThe syntax of the function is

# include< stdio .h >
2intfgetc ( FILE * stream );

3.1. INPUT OUTPUT 371
Thefgetcfunction obtains the next character (if present) as an unsigned
1
char converted
into its equivalent character code, from the input stream pointed-by ‘stream’.fgetcmod-
ified to the file pointer after reading each character. If the stream is at end-of-file, the
end-of-file indicator for the stream is set andfgetcreturnsEOF. If a read error occurs,
the error indicator for the stream is set andfgetcreturnsEOF.
A B C D E F G H
fgetc(fp)
A
fp→
A B C D E F G H
fgetc(fp)
B
fp→

# include< stdio .h >
2# include< stdlib .h >
4intmain (void) {
/* File pointer */
6 FILE * fr ;
/* Open file fread . txt in read mode */
8 fr = fopen (" fname . txt ","r");
/* If file is not opened , show warning *
10 * and exit without doing nothing . */
if( fr == NULL ) {
12 printf (" Couldn ’t open fname . txt file for reading .\ n" );
}
14 /* Read whole data of file by using fgetc */
intc ;
16 while(( c = fgetc ( fr )) != EOF ) {
putchar (c);
18 }
/* Close the file */
20 fclose ( fr );
/* If every thing is ok return successfully */
22 return0;
}


1
Position of char is determined by integer number started from zero to continue...

372 File & Data Structure

This is C Programming Langauge


fgetc() is more faster than thefread() function.fread() takes 0.1143 seconds to read
1.8MB MP3 file whilefgetctakes 0.000142 seconds to read the same file.

1# include< stdio .h >
# include< time .h >
3
intmain () {
5 clock_t startTime = clock () ;
FILE * fp ;
7 fp = fopen ("a. mp3 ","r");
ints ;
9 s = fgetc ( fp );
while(s > 0) {
11 s = fgetc ( fp );
}
13 fclose ( fp );
clock_t endTime = clock () ;
15 doubletd = ( endTime - startTime ) / ( double) CLOCKS_PER_SEC ;
printf (" Program has run for %5.8 f seconds \n" , td );
17 return0;
}


fgetsfunctionThe synopsis of the function is

char* fgets (char*s ,intn , FILE * stream );


Thefgetsfunction reads at most one less than the number of characters specified by
‘n’ from the stream pointed-by ‘stream’ into the array pointed-by‘s’. No additional
characters are read after a new-line character (which is retained) or after end-of-file. A
null character is written immediately after the last character readinto the array. The
fgetsfunction returns ‘s’ if successful. If end-of-file is encountered and no characters have
been read into the array, the contents of the array remain unchanged and a null pointer is
returned. If a read error occurs during the operation, the array contents are indeterminate
and a null pointer is returned.
A B C D E F G H
fgets(s,5,fp)
s=ABCDE
fp→
In following example,fgets() function reads specific number of bytes from a file via
file pointer and prints it in output console.

1# include< stdio .h >

3.1. INPUT OUTPUT 373
# defineBUFFER_SIZE 100
3
intmain (void) {
5 /* A read buffer */
charbuffer [ BUFFER_SIZE ];
7 while( fgets ( buffer , BUFFER_SIZE , stdin ) != NULL ) {
printf ("%s", buffer );
9 }
return0;
11}



This is
This is
my Car
my Car


Note that each line ends with end of line marker, i.e. ‘\r\n’, therefore,fgetsalways returns
a string of size two bytes even if a blank line is read from flat text file.

# include< stdio .h >
2# include< string .h >
4intmain () {
FILE * f;
6 inti = 0;
char* line = malloc (1024) ;
8 f = fopen (" txt . txt ","r");
if(f ) {
10 while( fgets ( line , 1024 , f) != NULL ) {
i = 0;
12 while( line [i] !=’\0 ’) {
printf ("%d %d %d\t", line [i],’\r ’,’\n ’);
14 i ++;
}
16 printf ("\n");
}
18 free ( line );
}
20 fclose (f);
return0;
22}



13 13 10 10 13 10
97 13 10 98 13 10 99 13 10
13 13 10 10 13 10


Another example, with additional functionality is given below. The texts from ‘fname.txt’
file are read and prints it in output console.

1# include< stdio .h >

374 File & Data Structure
# include< stdlib .h >
3# defineBUFFER_SIZE 1000
5intmain (void) {
/* File pointer */
7 FILE * fr ;
/* A read buffer */
9 charbuffer [1000];
/* Open file fname . txt in read mode */
11 fr = fopen (" fname . txt ","r");
/* If file is not opened , show warning *
13 * and exit without doing nothing . */
if( fr == NULL ) {
15 printf (" Couldn ’t open fname . txt file for reading .\ n" );
return0;
17 }
/* Read whole data of file by using fgets */
19 while( fgets ( buffer , BUFFER_SIZE , fr ) != NULL ) {
printf ("%s", buffer );
21 }
/* Close the file . */
23 fclose ( fr );
/* If every thing is ok return successfully */
25 return0;
}



This is C Programming Langauge


fgetscan also used in place ofscanffor receiving string from standard input.

1# include< stdio .h >
# defineSTRSIZE 100
3
intmain () {
5 intres ;
char* str1 , * str2 ;
7
str1 = malloc (sizeof(char) * STRSIZE + 1) ;
9 printf (" First string : ");
fgets ( str1 , STRSIZE , stdin );
11 printf (" You entered : %s", str1 );
13 str2 = malloc (sizeof(char) * STRSIZE + 1) ;
printf (" Second string : ");
15 fgets ( str2 , STRSIZE , stdin );
printf (" You entered : %s", str2 );
17
free ( str1 );
19 free ( str2 );
21 return0;

3.1. INPUT OUTPUT 375
}



First string : aryb
You entered : aryb
Second string : rakv
You entered : rakv


getcfunctionThis function reads data from input stream character by character,
unlike togetswhich reads string at once. Though this function has time consuming
process, yet it is helpful in bytewise operations. This function reads data from file and
updates its address by one. This function stops reading data whenit encounters EOF
symbol or any process error. The synopsis of the functiongetcis

# include< stdio .h >
2intgetc ( FILE * stream );


Thegetcfunction is equivalent tofgetc, except that it may be implemented as a macro.

# include< stdio .h >
2# include< stdlib .h >
# defineBUFFER_SIZE 1000
4
intmain (void) {
6 /* File pointer */
FILE * fr ;
8 /* A read buffer */
charbuffer [1000];
10 /* Open file fname . txt in read mode */
fr = fopen (" fname . txt ","r");
12 /* If file is not opened , show warning *
* and exit without doing nothing . */
14 if( fr == NULL ) {
printf (" Couldn ’t open fname . txt file for reading .\ n" );
16 return0;
}
18 /* Read whole data of file by using getc */
intc ;
20 while(( c = getc ( fr )) != EOF ) {
putchar (c);
22 }
/* Close the file . */
24 fclose ( fr );
/* If every thing is ok return successfully */
26 return0;
}


getcharfunctionThe syntax of this function is

1/* Header file for getchar () . */

376 File & Data Structure
# include< stdio .h >
3intgetchar (void);


Thegetcharfunction is equivalent togetcwith the argumentstdin. Thegetcharfunction
returns the next character from the input stream pointed-bystdin. The return value is
character code (integer) of the character. For example it returns ‘97’ for character ‘a’,
‘98’ for character ‘b’ and so on. It is similar to the following statement.

1scanf ("%c ", & ch );


Example of this function is given below.

1# include< stdio .h >
/* Copy input to output */
3
voidmain (void) {
5 intc ;
/* Get the position of first character *
7 * of stuff supplied to console window . */
c = getchar () ;
9 /* Recurse while loop until the character *
* representing end of file is not encountered */
11 while(c != EOF ) {
/* Put the first character and reach to next *
13 * character if next character is no EOF */
putchar (c);
15 /* After putting previous character *
* read the position of next character */
17 c = getchar () ;
}
19}


We can also count the lines by usinggetcharfunction

1# include< stdio .h >
3/* Count lines in input */
main (void) {
5 /* Define required variables . */
intc , nl ;
7 /* Initiate start of line number */
nl = 0;
9 /* Until end of file is not *
* encountered recurse while loop . */
11 while(( c = getchar () ) != EOF )
/* If new line parameter \n is encountered increase *
13 * the line counter and print the line number . */
if(c ==’\n ’)
15 ++ nl ;
printf ("%d\n", nl );
17}

3.1. INPUT OUTPUT 377
The third one is

1# include< stdio .h >
/* As the word is count , enter into the *
3* word to count characters in a word */
# defineINSIDEWORD 1
5/* If all characters are counted *
* exit and start word count mode . */
7# defineOUTWORD 0
9main (void) {
/* Define parameters */
11 intc , Noline , Noword , Nocharacter , state ;
/* Initial state is in word mode */
13 state = OUTWORD ;
/* Initiate counters as zero */
15 Noline = Noword = Nocharacter = 0;
/* Until not encountered end of file do *
17 * recursion for while loop for each character . */
while(( c = getchar () ) != EOF ) {
19 /* Count the character until \n or *
*’ ’ or \t is not encountered */
21 ++ Nocharacter ;
/* If encountered end of line \n */
23 if(c ==’\n ’)
/* Count the line */
25 ++ Noline ;
/* If encountered to space or end of line or *
27 * tab , enter into word mode to count the words . */
if(c ==’ ’|| c ==’\n ’|| c ==’\t ’)
29 /* Change the state to word mode when *
* encountered with ’ ’ or \n or \t controls . */
31 state = OUTWORD ;
/* If word mode count the words */
33 else if( state == OUTWORD ) {
/* Toggle the state to character mode until *
35 * encountered with ’ ’ or \n or \t controls . */
state = INSIDEWORD ;
37 /* Count the words . */
++ Noword ;
39 }
}
41 printf (" Number of lines & words are %d & %d .\ n " , Noline ,
Noword );
printf (" Number of characters are %d\n" , Nocharacter );
43}


Following is an example of finding longest line.

1# include< stdio .h >
/* Maximum input line length */
3# defineMAXLINE 1000

378 File & Data Structure
intreadline (charline [ ],intmaxline );
5voidcopyoutput (charto [ ],charfrom [ ]) ;
7main (void) {
/* Current line length */
9 intlen ;
/* Maximum length seen so far */
11 intmax ;
/* Current input line */
13 charline [ MAXLINE ];
/* Longest line saved here */
15 charlongest [ MAXLINE ];
max = 0;
17 while(( len = readline ( line , MAXLINE )) > 0) {
if( len > max ) {
19 max = len ;
copyoutput ( longest , line );
21 }
}
23 /* There was a line */
if( max > 0)
25 printf ("%s", longest );
return0;
27}
29/* readline : read a line into s , return length */
intreadline (chars[ ],intlim ) {
31 intc , i;
for( i = 0; i < lim - 1 && \
33 (c = getchar () ) != EOF && \
c !=’\n ’; ++ i)
35 s [i] = c;
if(c ==’\n ’) {
37 s [i] = c;
++ i;
39 }
s[i] =’\0 ’;
41 returni;
}
43
/* copyoutput : copyoutput ’ from ’ into *
45*’ to ’; assumed that it is big enough */
voidcopyoutput (charto [ ],charfrom [ ]) {
47 inti ;
i = 0;
49 while(( to [i] = from [i ]) !=’\0 ’)
++ i;
51}


getsfunctionThe syntax of the function is

3.1. INPUT OUTPUT 379
1# include< stdio .h >
char* gets (char*s);


Thegetsfunction reads characters from the input stream pointed-bystdininto the array
pointed-by ‘s’ until an end-of-file is encountered or a new-line character is read. Any
new-line character is discarded, and a null character is written immediately after the last
character read into the array. This function is deprecated as it’s dangerous, it may cause
buffer overflow.

# include< stdio .h >
2# defineSTRSIZE 100
4intmain () {
intres ;
6 char* str1 , * str2 ;
8 str1 = malloc (sizeof(char) * STRSIZE + 1) ;
printf (" First string : ");
10 gets ( str1 );
printf (" You entered : %s\n" , str1 );
12
str2 = malloc (sizeof(char) * STRSIZE + 1) ;
14 printf (" Second string : ");
gets ( str2 );
16 printf (" You entered : %s\n" , str2 );
18 free ( str1 );
free ( str2 );
20
return0;
22}



First string : aryb
You entered : aryb
Second string : rakv
You entered : rakv


EOFpitfallEOFis a negative value defined in<stdio.h>, usually -1. The reason
is that, the keyboard input ranges from 0 to 255 in extended character support. So any
other value except than -1 will interpret as a character rather than termination of a file.
A mistake when usingfgetc,getc, orgetcharis to assign the result to a variable of type
char before comparing it to ‘EOF’. The following code fragments exhibit this mistake,
and next code fragments exhibits the correct approach (using type int)

/* c as character . */
2charc;
while(( c = getchar () ) != EOF )
4 putchar (c);

380 File & Data Structure
The mistake in above example is corrected in the following example.

/* c as integer */
2intc;
while(( c = getchar () ) != EOF )
4 putchar (c);


scanffunctionThe synopsis of the function is

# include< stdio .h >
2intfscanf ( FILE * stream ,const char* format , variable_name );
intscanf (const char* format , variable_name );
4intsscanf (const char* src ,const char* format , dest );


Thefscanffunction reads input from the stream pointed-by ‘stream’, under control of
the string pointed-by ‘format’ that specifies the admissible sequences and how they are
to be converted for assignment, using subsequent arguments aspointers to the objects to
receive converted input. If there are insufficient arguments for the format, the behavior
is undefined. If the format is exhausted while arguments remain, the excess arguments
are evaluated (as always) but are otherwise ignored. The format shall be a multi-byte
character sequence, beginning and ending in its initial shift state. Asimple example is

# include< stdio .h >
2
intmain (intargc ,char* argv [ ]) {
4 charkey [10];
intHex , i;
6 strcpy ( key ," zaz ");
sscanf ( key ,"%x", & Hex );
8 printf (" The Hex value of ’%s ’ is ’%x ’.\ n" , key , Hex );
return0;
10}



The Hex value of ’zaz ’ is ’22 d 000 ’.


fscanfexample is given as

1# include< stdio .h >
# include< stdlib .h >
3
intmain () {
5 intnum ;
FILE * fp ;
7 /* file . txt must be in the executable ’s dir */
fp = fopen (" file . txt ","r");
9 /* Read file in integer form . */
fscanf (fp ,"%d", & num );
11 printf (" Integer %d .\ n", num );
/* Read file in hex form . */
13 fscanf (fp ,"%x", & num );

3.1. INPUT OUTPUT 381
printf (" Hex is %x .\ n", num );
15 /* Read file in string form . */
fscanf (fp ,"%s", & num );
17 printf (" String is % c .\ n", num );
fclose ( fp );
19
return(0) ;
21}


Output from my file “file.txt” is

Integer 0.
Hex is 0.
String is T.


Following is afscanfexample.

1# include< stdio .h >
3intmain (intargc ,char* argv [ ]) {
FILE * fin ;// In file name
5 FILE * fout ;// Out file name
/* Must provide infile name and outfile name from command lin e */
7 if( argc < 3) {
printf (" Use : % s < file in > < file out >\ n", argv [0]) ;
9 exit (1) ;
}
11 fin = fopen ( argv [1] ,"r");// open infile for read
if( fin == NULL ){// if any error
13 fprintf ( stderr ," Can ’t open in file in . list !\ n");
exit (1) ;
15 }
/* Open outfile for read */
17 fout = fopen ( argv [2] ,"w");
if( fout == NULL ){// if any error
19 fprintf ( stderr ," Can ’t open out file in . list !\ n");
exit (1) ;
21 }
/* Read name array from first column of infile */
23 charName [9];
/* Read roll no from second column of infile */
25 intRolNo ;
/* ---------------------------------**
27 Infile structure is like
Arun 100
29 Raj 200
Ram 300
31 and saved in . txt file
Scan file line by two columns
33 at once until file is not ended .
**-------------------------------- - */
35 while( fscanf ( fin ,"%s %d", Name , & RolNo ) != EOF ) {

382 File & Data Structure
/* Write every thing in out file if first column is *
37 * text column and second column is integer column . */
fprintf ( fout ," %s %d\n", Name , RolNo );
39 }
/* Close infile and outfile . */
41 fclose ( fin );
fclose ( fout );
43 return0;
}


freadfunctionThe syntax of the function is

# include< stdio .h >
2size_t fread (void* ptr , size_t size , size_t nmemb , FILE * stream );


Thefreadfunction reads from the stream pointed-by ‘stream’ and writes data into the
array pointed-by ‘ptr’, up to ‘nmemb’ elements whose size is specifiedby ‘size’. A simple
example is

# include< stdio .h >
2
intmain (void) {
4 inti ;
intn [10];
6 FILE * fp ;
fp = fopen ("a. txt "," rb ");
8 fread (n ,sizeof(int) , 10 , fp );// read 10 integers
fclose ( fp );
10 // print them out :
for( i = 0; i < 10; i ++)
12 printf ("n [% d] == %d\n", i , n [i ]) ;
return0;
14}


Output for my file “a.txt” is

n [0] == 1936287828
n [1] == 544434464
n [2] == 539444064
n [3] == 1735357008
n [4] == 1835884914


A second example is

1# include< stdio .h >
# definebufsize 10
3
intmain (intargc ,char* argv [ ]) {
5 ints ;
intHexValue ;
7 charbuf [ bufsize ];

3.1. INPUT OUTPUT 383
/* ’f ’ prefixed with ’ read ’ and ’ write ’ functions *
9 * represents to the file to be read and write . */
s = fread ( buf , 1, bufsize , stdin );
11 while(s > 0) {
fwrite ( buf , 1, s , stdout );
13 s = fread ( buf , 1, bufsize , stdin );
}
15 return0;
}


There are no differences between reading one byte long data from afile by ‘n’ times or
‘n’ bytes long data by one time, using functionfread(). In both cases,fread() stores ‘n’
bytes data from file pointer into buffer pointer. Only execution time isaffected on the
implementation type offread(). In following example, a 5.48MB file is read one byte at
once. The execution time is about 1.188 seconds.

# include< stdio .h >
2# include< time .h >
# defineDATA_SIZE 1
4# defineBLOCK_SIZE 1
6intmain () {
clock_t startTime = clock () ;
8 FILE * fp ;
/* bmp . bmp must be in the executable ’s dir */
10 fp = fopen (" bmp . bmp ","r");
charbuff [1024];
12 ints ;
s = fread ( buff , DATA_SIZE , BLOCK_SIZE , fp );
14 while(s > 0) {
s = fread ( buff , DATA_SIZE , BLOCK_SIZE , fp );
16 }
fclose ( fp );
18 clock_t endTime = clock () ;
doubletd = ( endTime - startTime ) / ( double) CLOCKS_PER_SEC ;
20 printf (" Program has run for %5.8 f seconds \n" , td );
return0;
22}


Data size is increased from 1 to 10, the execution time reduced to 0.125 seconds.

# include< stdio .h >
2# include< time .h >
# defineDATA_SIZE 10
4# defineBLOCK_SIZE 1
6intmain () {
clock_t startTime = clock () ;
8 FILE * fp ;
/* bmp . bmp must be in the executable ’s dir */
10 fp = fopen (" bmp . bmp ","r");

384 File & Data Structure
charbuff [1024];
12 ints ;
s = fread ( buff , DATA_SIZE , BLOCK_SIZE , fp );
14 while(s > 0) {
s = fread ( buff , DATA_SIZE , BLOCK_SIZE , fp );
16 }
fclose ( fp );
18 clock_t endTime = clock () ;
doubletd = ( endTime - startTime ) / ( double) CLOCKS_PER_SEC ;
20 printf (" Program has run for %5.8 f seconds \n" , td );
return0;
22}


Again, data size is 1 and block size read byfread() function is increased to 10 from 1.
Again the execution time is 0.125 seconds.

# include< stdio .h >
2# include< time .h >
# defineDATA_SIZE 1
4# defineBLOCK_SIZE 10
6intmain () {
clock_t startTime = clock () ;
8 FILE * fp ;
/* bmp . bmp must be in the executable ’s dir */
10 fp = fopen (" bmp . bmp ","r");
charbuff [1024];
12 ints ;
s = fread ( buff , DATA_SIZE , BLOCK_SIZE , fp );
14 while(s > 0) {
s = fread ( buff , DATA_SIZE , BLOCK_SIZE , fp );
16 }
fclose ( fp );
18 clock_t endTime = clock () ;
doubletd = ( endTime - startTime ) / ( double) CLOCKS_PER_SEC ;
20 printf (" Program has run for %5.8 f seconds \n" , td );
return0;
22}


Hence, it is clear that when block size read byfread() function increases, the corresponding
execution time decreases.
Writing File
We can write a binary or text file by using following methods.
fputcfunctionThe synopsis of the function is

# include< stdio .h >
2intfputc (intc , FILE * stream );

3.1. INPUT OUTPUT 385
Thefputcfunction writes the character specified by ‘c’ (converted to an unsigned char)
to the stream pointed-by ‘stream’ at the position indicated by the associated file position
indicator (if defined), and advances the indicator appropriately. If the file cannot sup-
port positioning requests, or if the stream is opened with append mode, the character
is appended to the output stream. The function returns the character written, unless a
write error occurs, in which case the error indicator for the stream is set andfputcreturns
EOF.

# include< stdio .h >
2# include< stdlib .h >
4intmain (intargc ,char** argv ) {
inti = 0;
6 FILE * fp ;
fp = fopen ("a. txt "," wa ");
8 while(i < 100) {
fputc (i , fp );
10 i ++;
}
12 close ( fp );
return( EXIT_SUCCESS );
14}


fputsfunctionThe synopsis of the function is

# include< stdio .h >
2intfputs (const char*s , FILE * stream );


Thefputsfunction writes the string pointed-by ‘s’ to the stream pointed-to‘stream’. The
terminating null character is not written. The function returnsEOFif a write error
occurs, otherwise it returns a non-negative value. A simple exampleis

# include< stdio .h >
2# include< stdlib .h >
4intmain (intargc ,char** argv ) {
chars [10] =" hello ";
6 FILE * fp ;
fp = fopen ("a. txt "," wa ");
8 fputs (s , fp );
close ( fp );
10 return( EXIT_SUCCESS );
}


putcfunctionThis function has syntax like

1# include< stdio .h >
intputc (intc , FILE * stream );

386 File & Data Structure
Theputcfunction is equivalent tofputc, except that if it is implemented as a macro, it
may evaluate stream more than once, so the argument should never be an expression with
side effects. The function returns the character written, unlessa write error occurs, in
which case the error indicator for the stream is set and the function returnsEOF.

# include< stdio .h >
2# include< stdlib .h >
4intmain (intargc ,char** argv ) {
inti = 0;
6 FILE * fp ;
fp = fopen ("a. txt "," wa ");
8 while(i < 100) {
putc (i , fp );
10 i ++;
}
12 close ( fp );
return( EXIT_SUCCESS );
14}


putcharfunctionThe syntax of this function is

/* Header file for putchar () . */
2# include< stdio .h >
intputchar (intc);


Theputcharfunction is equivalent toputcwith the second argumentstdout. It returns
the character equivalent to its character code. If a write error occurs, theerrorindicator
forstdoutis set and the function returnsEOF. This is similar to the statement

1printf ("% c", ch );


A simple example is

1# include< stdio .h >
# include< stdlib .h >
3
intmain (intargc ,char** argv ) {
5 inti =0;
while(i <100) {
7 putchar (i);
i ++;
9 }
return( EXIT_SUCCESS );
11}


putsfunctionThe synopsis of the function is

1# include< stdio .h >
intputs (const char*s);

3.1. INPUT OUTPUT 387
Theputsfunction writes the string pointed-by ‘s’ to the stream pointed-tostdout, and
appends a new-line character to the output. The terminating null character is not written.
The function returnsEOFif a write error occurs; otherwise, it returns a non-negative
value.

# include< stdio .h >
2# include< stdlib .h >
4intmain (intargc ,char** argv ) {
chars [10] =" hello ";
6 puts ( s);
return( EXIT_SUCCESS );
8}


Eachputsputs a value at the beginning of new line. See the example as given bellow:

# include< stdio .h >
2# include< stdlib .h >
4intmain (intargc ,char** argv ) {
puts (" This is new line ");
6 puts (" This is new line ");
puts (" This is new line ");
8 return( EXIT_SUCCESS );
}



This is new line
This is new line
This is new line


fwritefunctionThe synopsis of the function is

1# include< stdio .h >
size_t fwrite (const void* ptr , size_t size , size_t nmemb , FILE
* stream );


Thefwritefunction writes, from the array pointed-by ‘ptr’, up to ‘nmemb’ elements whose
size is specified by ‘size’ to the stream pointed-to ‘stream’. The file position indicator for
the stream (if defined) is advanced by the number of characters successfully written. A
simple example is

# include< stdio .h >
2
intmain (void) {
4 inti ;
intr [10];
6 FILE * fp ;
/* Populate the array with random numbers : */
8 for( i = 0; i < 10; i ++) {
r [i] = rand () ;

388 File & Data Structure
10 }
/* Save the random numbers (10 ints ) to the file */
12 fp = fopen ("a. txt "," wb ");
14 /* Write 10 ints */
fwrite (r ,sizeof(int) , 10 , fp );
16 fclose ( fp );
return0;
18}


fwritefunction writes bytes into the file stream rather than string data.This is why
integer values can not be written into text file by using this function.
fprintffunctionIntegers can be written into a text file by usingfprintffunction rather
thanfwritefunction.fprintf, first converts an integer into its equivalent character code
and then puts it into the file stream. An example for thefprintffunction is given below:

# include< stdio .h >
2
intmain () {
4 FILE * f;
inti = 0;
6 f = fopen (" TreeNode . txt ","w");
while(i < 5) {
8 fprintf (f ,"%d\ n", 10 + i);
i ++;
10 }
fclose (f);
12 return0;
}


In output file, output appears as

10
11
12
13
14


Supplying File Names from Command LineThere is another way by which file names
can be directly supplied to the program and the files are read and write asstdinand
stdout. For explanation see following example.

1# include< stdio .h >
# definebuf_size 1024
3
intmain (intargc ,char* argv [ ]) {
5 charbuf [ buf_size ];
intrd ;
7 if( argc < 2) {
/* In command line a infile name can be assigned by *

3.1. INPUT OUTPUT 389
9 * prefixing ’<’ character and outfile name can be *
* assigned by prefixing ’>’ character before input *
11 * and output file names . If system can able to read *
* the file it shown not error and put all the data *
13 * of infile into outfile . If file does not exist *
* then system return that ’ The system can not find *
15 * the file specified .’ Other string which is not *
* prefixed by ’<’ or ’>’ is considered as argument . */
17 fprintf ( stderr ,"%s key < infile > outfile \n" , argv [0]) ;
exit (1) ;
19 }
/* Infile is read as ’ stdin ’*/
21 rd = fread ( buf , 1, buf_size , stdin );
while( rd > 0) {
23 /* Outfile is open as ’ stdout ’. If *
* outfile is not specified , output *
25 * is printed in the console window . */
fwrite ( buf , 1, rd , stdout );
27 rd = fread ( buf , 1, buf_size , stdin );
}
29 /* File open for read and write once would be *
* closed automatically when program is terminated . */
31}


Remove & Rename a File
removefunctionThis function removes the specified file whose name is supplied as
argument from the disk storage. The syntax of this function is

1# include< stdio .h >
intremove (const char* filename );


It returns zero if file is successfully removed otherwise non zero if removal of file is unsuc-
cessful. Theremovefunction causes the file whose name is the string pointed-by ‘filename’
to be no longer accessible by that name.

# include< stdio .h >
2
intmain () {
4 if( remove (" fname . txt ") != 0)
perror (" Error deleting file ");
6 else
puts (" File successfully deleted " );
8 return0;
}



File successfully deleted

390 File & Data Structure
unlinkfunctionIt deletes a file identify by file name. If file name is supplied to
the function file itself is also deleted. Actually, if any process has thefile open when
this happens, deletion is postponed until all processes have closedthe file. The function
unlink() is declared in the header file ‘unistd.h’. It returns 0 on successfulcompletion,
and -1 on error.

1# include< stdio .h >
# include< unistd .h >
3
intmain (void) {
5 unlink ("a. txt ");
return0;
7}


rmdirfunctionIt deletes a directory identify by directory name. It is similar to
unlink() except that the error handling is improved inrmdir() function. It returns 0 on
successful completion, and -1 on error.

1# include< stdio .h >
# include< unistd .h >
3
intmain (void) {
5 rmdir (" ../ ");
return0;
7}


renamefunctionThe synopsis of the function is

1# include< stdio .h >
intrename (const char* old_name ,const char* new_name );


Therenamefunction causes the file whose name is the string pointed-by ‘oldname’ to
be henceforth known by new name, pointed-by ‘newname’. A simple example is

# include< stdio .h >
2
intmain () {
4 if( rename ("a. txt ","b. txt ") != 0)
perror (" Error renaming file ");
6 else
puts (" File successfully renamed ." );
8 return0;
}



Error renaming file : No such file or directory


tmpfilefunctionThe synopsis of the function is

3.1. INPUT OUTPUT 391

1# include< stdio .h >
FILE * tmpfile (void);


Thetmpfilefunction creates a temporary binary file. This file is automatically removed
when either it is closed or the program, which created it, is terminated. A simple example
is

# include< stdio .h >
2FILE * fp ;
4intmain () {
/* Initiate a temporary file . */
6 fp = tmpfile () ;
if(! fp ) {
8 printf (" Couldn ’t initiate temp file ...\ n" );
exit (0) ;
10 }else{
printf (" temp file is initiated ... " );
12 }
return0;
14}



temp file is initiated ...


tmpnamfunctionThe synopsis of the function is

1# include< stdio .h >
char* tmpnam (char*s);


Thetmpnamfunction generates a string that is a valid file name and that is not thename
of an existing file. A simple example is

# include< stdio .h >
2
/* Temporary file name pointer . */
4chartmp_name [10];
6intmain () {
8 /* Assigne the name to name pointer . */
tmpnam ( tmp_name );
10 if( strlen ( tmp_name ) == 0) {
printf (" Couldn ’t get a work file name ...\ n " );
12 exit (0) ;
}else{
14 printf (" work file name is \"% s \". ", tmp_name );
}
16 return0;
}

392 File & Data Structure

work file name is "/ tmp /t 76 c .0".


Resize a File
truncate() function changes the size of the file. If the file has data of sizenand the maker
offset is shorter than it, then everything after the marker position is made unavailable to
access. It returns 0 on success and -1 on error. The errorEACCESreturns if the file is a
directory or not writable.EINVAL, if length is negative.EFBIG, of the operation would
extend the file beyond the limits of the operating system.EIO, if a hardware I/O error
occurred.EPERM, if the file is in “append-only” or “immutable” mode andEINTR, if
the operation was interrupted by a signal.
File Pointer as Function Argument
In C, file pointers can be passed to a function as its argument. The syntax for file pointer
as function argument is given below:

1voidfile_function ( FILE *< ptr_name >)


In the following example, a file is opened in read mode in main function andthe same
file pointer is passed to user defined function ‘printfile’ as its argument. Inside the user
define function, contents of the file are read and print in output console.

1# include< stdio .h >
# include< stdlib .h >
3
voidprint_file ( FILE *) ;
5
intmain (void) {
7
FILE * fp = fopen ("a . txt ","r");
9 if(! fp ){
perror (" Unable to open file ");
11 exit ( EXIT_FAILURE );
}
13 print_file ( fp );
15 return0;
}
17
voidprint_file ( FILE * in ) {
19 charch = 0;
while(! feof ( in )) {
21 ch = (char) getc ( in );
23 if( ferror ( in )) {
fputs (" File error - Reading Operation " , stderr );
25 exit ( EXIT_FAILURE );
}

3.1. INPUT OUTPUT 393
27 if(! feof ( in )) {
putchar ( ch );
29 }
}
31 return;
}


Low Level Input/Output
In this section, functions for performing low-level input/output operations on a file de-
scriptors are explained. Here, low level I/O functions uses file descriptor while high level
I/O functions uses streams. The low level descriptors are used in reading large binary
chunk from binary files or reading of whole file at once as done inmmapfunction. It is
used to perform operations rather than data transfer. The useful low level functions are
open(),fileno,close,read,write,lseeketc. These functions are declared in the header file
‘fcntl.h’.
open()This function is used to open a file descriptor for a file that is already existing
in the system. Its syntax is

int< file descriptor > = open (< filename >, <mode >)


This function creates a new file descriptor (an integer value) and returns it. Initially,
position of file descriptor is at the beginning of file. The mode tells how the file is open?
The mode values are ORDONLY, OWRONLY, ORDWR, OAPPEND, OCREAT and
OTRUNC. Multiple modes can also be used by using binary ‘|’ operator. This function
returns the file descriptor value when it creates & opens a file descriptor successfully,
otherwise it returns ‘-1’ as error value.

1# include< stdio .h >
# include< fcntl .h >
3
intmain (intargc ,char* argv []) {
5 intfd ;
/* Read and write mode of file . */
7 if(( fd = open ("a. pdf ", O_RDWR )) == -1) {
printf (" Unable to open file .\ n");
9 return1;
}
11 printf (" File descriptor is :% d\n ", fd );
close ( fd );
13 return0;
}



File descriptor is :3


Modes OWRONLY, OCREAT and OTRUNC are used to create a new file and opening
of file descriptor.

394 File & Data Structure
close()This function is used to close a file descriptor. Its syntax is

1int< state > = close (< file descriptor >)


When this function is called, the file descriptor is deallocated, any locked record is un-
locked and any unread data, if there, is discarded. It returns 0 onsuccessful closing of
file descriptor and ‘-1’ in case of failure.

1# include< stdio .h >
# include< fcntl .h >
3
intmain (intargc ,char* argv []) {
5 intfd ;
/* Read and write mode of file . */
7 if(( fd = open ("a. pdf ", O_RDWR )) == -1) {
printf (" Unable to open file .\ n");
9 return1;
}
11 printf (" File descriptor is :% d\n ", fd );
/* Close the file descriptor . */
13 close ( fd );
return0;
15}



File descriptor is :3


read()This function is used to read data from a file through a file descriptor. Its
syntax is

1int< size of data read >
= read (< file descriptor >, < buffer >, < size (n) >)


This function reads data, equivalent to size ‘n’, from a file using file descriptor and copied
it to buffer. On successful read of data, it returns a number equivalent to bytes read
successfully through file descriptor. On failure it returns ‘-1’

# include< stdio .h >
2# include< fcntl .h >
4intmain (intargc ,char* argv []) {
intfd ;
6 char* buff ;
if(( fd = open ("a. pdf ", O_RDWR )) == -1) {
8 printf (" Unable to open file .\ n");
return1;
10 }
/* Read data */
12 ints = read (fd , buff , 10) ;
printf (" Read data is :% s\n", buff );
14 close ( fd );

3.1. INPUT OUTPUT 395
return0;
16}



Read data is : aaaaaaaaaa


writeThis function is used to write buffer data into a file through a file descriptor.
Its syntax is

1int< size of data written >
= read (< file descriptor >, < buffer >, < size (n) >)


This function writes data of buffer, equivalent to size ‘n’, into a file using file descriptor.
The buffer data beyond the size ‘n’ is discarded, i.e. does not writteninto the file. On
successful wrote data into the file, it returns a number equivalentto number of data bytes
written successfully through file descriptor. On failure it returns ‘-1’.

# include< stdio .h >
2# include< fcntl .h >
4intmain (intargc ,char* argv []) {
intfd ;
6 char* buff =" This is my file .";
if(( fd = open ("a. pdf ", O_RDWR )) == -1) {
8 printf (" Unable to open file .\ n");
return1;
10 }
/* Write data */
12 ints = write (fd , buff , 10) ;
printf (" Size of written data is :% d\n" , s);
14 close ( fd );
return0;
16}



Size of written data is :10


lseek()This function is used to change the position of file descriptor in a file for next
readorwrite. Its syntax is

1off_t lseek (< file descriptor >, < offset >, < from where >)


The ‘offset’ is the position value that may be changed for file descriptor either from the
beginning of the file, or from the current position of the file or from the end of file. The
values for third argument are SEEKSET, SEEKCUR or SEEKEND. The return value
oflseekfunction is eitherofftoroff64tas the case may be. On failure it returns ‘-1’.

1# include< stdio .h >
# include< fcntl .h >
3

396 File & Data Structure
intmain (intargc ,char* argv []) {
5 intfd ;
if(( fd = open ("a. pdf ", O_RDONLY )) == -1) {
7 printf (" Unable to open file .\ n");
return1;
9 }
char* buff ;
11 read ( fd , buff , 10) ;
printf (" Read data is :% s\n", buff );
13 /* Set file descriptor to new position */
lseek (fd , 10 , SEEK_CUR );
15 read ( fd , buff , 10) ;
printf (" Read data is :% s\n", buff );
17 close ( fd );
return0;
19}



Read data is : This is my
Read data is : aaaaaaaaaa


fdopen()This function is used to open a stream for a file descriptor. Its syntax is

FILE *< new stream >
2 = fdopen (< file descriptor >, <mode >)


The mode values are any one of the values ‘w’, ‘w+’, ‘r’, ‘r+’ and others associated with
fopenfunction. On successful it returns stream pointer and on failure itreturns null
pointer. Mixing of I/O functions exclusively used with streams and I/O functions exclu-
sively defined for file descriptor is dangerous. Therefore, it shouldbe checked whether a
file descriptor is associated with stream pointer or not by usingfilenofunction as given
in following syntax.

int< file descriptor > = fileno (< stream >) ;


filenoreturns the file descriptor associated with the stream. If an error is detected or if
stream does not have a file descriptor,filenoreturns ‘-1’.

1# include< stdio .h >
# include< fcntl .h >
3
intmain (intargc ,char* argv []) {
5 intfd ;
FILE * f;
7 char* buff ;
if(( fd = open ("a. pdf ", O_RDONLY )) == -1) {
9 printf (" Unable to open file .\ n");
return1;
11 }
/* Link file descriptor to stream */
13 f = fdopen (fd ,"r");

3.2. SYMBOL TABLE 397
/* Get file descriptor linked to stream */
15 intfdn = fileno (f);
printf (" Associated file descriptor is :% d\n" , fdn );
17 fread ( buff ,sizeof(char) , 10 , f );
printf (" Read data is :% s\n", buff );
19 close ( fd );
return0;
21}



Associated file descriptor is :3
Read data is : This is my


3.2 Symbol Table
Symbol Table is a data structure that is created and maintained by the compiler in order
to keep track about scope and binding names of a variable, its instances, function names,
classes, objects, etc. A new table is created to store entries, liketokens, attribute type of
variable, scope of variable, dimension of variable, line of reference,use, etc. This available
information is used to verify expression, code optimization and target code generation by
compilers. Entry stored in symbol table are variable name, functionname, literals, labels,
addresses etc.
3.3 Data Structures
A data structure (struct) contains multiple pieces of data. Each piece of data (called a
“member”) can be accessed by using a group of instance of structure, followed by a ‘.’ (ie
dot), then the name of the member (another way to access a member is using the member
operator ‘−>’ for pointers.). The member variables of data structure can be ofany data
type or can be an array or a pointer.
3.3.1 Structures
A data structure contains multiple pieces of data. To collect data, variables (structure
elements) of appropriate data type are used. A function can not be an element of the
structure. Structure in C is declared withstructkeyword. Skeletal of thestructkeyword
is shown below:

struct< structure_name >{
2 int< int_member >;
double< double_member >;
4 char< string_member [25] >;
} < structure_alias_name >;


‘structurealiasname’ is instance of ‘structurename’. We can omit it from the end of the
structdeclaration and it may be declared later as shown below:

398 File & Data Structure

1struct< structure_name > < structure_alias_name >;


It is common practice to make a type synonym so we don’t have to type

1struct< structure_name >


all the time when this structure is required. Thestructitself has no name (by the absence
of a name on the first line), but it is aliased as ‘structurename’. We can use

1< structure_name > < structure_alias_name >;


to create structure instances as and when required. We can add data into structure or
read data from structure by using ‘dot’ symbol (direct member access).

1structstudent {
intid ;
3 char* name ;
floatperc ;
5} st ;
st . id =1;/* Use dot symbol between instance *
7 * name and structure element . */


After creating an instance of structure, instance reserves thememory bytes equal to the
sum of size of all members. In a C structure, a string element declared aschar *sdoes
not contains the string itself. It contains the address where string is stored. This is why,
the size ofchar *selement of the structure is 4 bytes only.

1# include< stdio .h >
3structmyStruct {
char* s;
5};
intmain () {
7 structmyStruct st ;
printf (" Size of st is %d bytes ." , (int)sizeof( st ));
9 return0;
}



Size of st is 4 bytes .


If a structure contains a pointer member then it stores the memory address of those
values/variables to whom it is pointing. For example, in the following structure:

1structst {
inti ;
3 char* s;
} myS ;

3.3. DATA STRUCTURES 399
In above structure, there are two members. First in ‘i’ which is integer type. This variable
holds value itself. For illustration purpose, let it holds value 1224527 indecimal form.
The second member is a pointer of string contains alphabets from A to I. The pointer
variable does not holds value itself but it holds the address of first string character as
shown in the following figure.
0×50 0×51 0×52 0×53
0×12AF4F
0×50 0×51 0×52 0×53
0×80
int i char *s
myS
A
0×80
B
0×81
C
0×82
D
0×83
E
0×84
F
0×85
G
0×86
H
0×87
I
0×88
\0
0×89
Though total data size is 14 bytes long (4 bytes of integer and 10 bytes of string) yet
the size of ‘myS’ is 8 bytes. This is because, four bytes is used byintdata type variable
and four bytes are used by pointer variable. If string element, declared aschar s[¡n¿],
contains the string of suitable size ‘n’ itself. Example for fixed stringelements within the
structure.

# include< stdio .h >
2
structmyStruct {
4 chars [10];
};
6intmain () {
structmyStruct st ;
8 printf (" Size of st is %d bytes ." , (int)sizeof( st ));
return0;
10}



Size of st is 10 bytes .


See the figure given below:
st
id name perc
After creating an instance of structure, instance reserves thememory space (N) in
bytes equal to or greater than the sum of bytes reserved by thestructure members, where
Nis perfect multiple of size of all member data types. The size calculation is done as
given in following examples.

400 File & Data Structure

1structs {
intid1 ;// 4 bytes for data
3 intid2 ;// 4 bytes for data
};// total size will be equal to sum of all
5 // bytes , upward rounded off to , multiple
// to size of largest structure member .



# include< stdio .h >
2
structs {
4 intid1 ;
intid2 ;
6};// Total 8 bytes rounded up to
// 4*2=8 bytes is size of s
8
intmain () {
10 printf (" Size of Structure s in bytes is " );
printf ("%d .\ n",sizeof(structs)) ;
12 return0;
}



Size of Structure s in bytes is 8


Here, sum of memory bytes calculated from structure members, isrounded off upward
so that it is perfect multiple of the largest data type member of thatstructure. This is
because, number of elements (n) in an array is given by
n=
Sum of Bytes
sizeof(data type)
Wherenis an integer. If there are multiple datatypes as in the case of a structure, if bytes
are not multiple of all member datatypes’ size, thennbecomes fraction. This rounding
off is done to make structure operation easy. Take another case:

1structs {
intid1 ; // 4 bytes for data
3 doubleid2 ;// 8 bytes for data
};// total size will be equal to sum of all
5 // bytes , upward rounded off to , multiple
// to size of largest structure member .



# include< stdio .h >
2
structs {
4 intid1 ;
doubleid2 ;
6};// Total 12 bytes rounded up to
// 8*2=16 bytes is size of s