Unit-III Notes
Unit-III Notes
Functions- Basics, user defined functions, inter function communication, Storage classes-auto, register,
static, extern, scope rules, type qualifiers, recursion- recursive functions, memory allocation functions,
pointers to functions, structures and functions, command –line arguments, Preprocessor commands.
Files- Concept of a file, standard input / output functions, formatted input / output functions, text files and
binary files, file input / output operations, Random access functions, file status functions (error handling), C
program examples.
Basics
In c, we can divide a large program into the basic building blocks known as function. The function contains
the set of programming statements enclosed by {}. A function can be called multiple times to provide
reusability and modularity to the C program. In other words, we can say that the collection of functions
creates a program. The function is also known as procedure or subroutine in other programming languages.
Advantage of functions in C
There are the following advantages of C functions.
o By using functions, we can avoid rewriting same logic/code again and again in a program.
o We can call C functions any number of times in a program and from any place in a program.
o We can track a large C program easily when it is divided into multiple functions.
o Reusability is the main achievement of C functions.
o However, Function calling is always a overhead in a C program.
Function Aspects
There are three aspects of a C function.
o Function declaration A function must be declared globally in a c program to tell the compiler about
the function name, function parameters, and return type.
o Function call Function can be called from anywhere in the program. The parameter list must not
differ in function calling and function declaration. We must pass the same number of functions as it
is declared in the function declaration.
o Function definition It contains the actual statements which are to be executed. It is the most
important aspect to which the control comes when the function is called. Here, we must notice that
only one value can be returned from the function.
Types of Functions
There are two types of functions in C programming:
1. Library Functions: are the functions which are declared in the C header files such as scanf(), printf(),
gets(), puts(), ceil(), floor() etc.
2. User-defined functions: are the functions which are created by the C programmer, so that he/she
can use it many times. It reduces the complexity of a big program and optimizes the code.
ACTUAL ARGUMENTS AND FORMAL ARGUMENTS
Actual Arguments:
1. Arguments which are mentioned in the function in the function call are known as calling
function.
2. These are the values which are actual arguments called to the function.
It can be written as constant , function expression on any function call which return a value .
Formal Arguments:
1. Arguments which are mentioned in function definition are called dummy or formal
argument.
2. These arguments are used to just hold the value that is sent by calling function.
3. Formal arguments are like other local variables of the function which are created when
function call starts and destroyed when end function.
a) Formal arguments are declared within the ( ) where as local variables are
declared at beginning.
b) Formal arguments are automatically initialized when a value of actual argument
is passed.
c) Where other local variables are assigned variable through the statement inside
the function body.
Note: Order, number and type of actual argument in the function call should be matched with
the order , number and type of formal arguments in the function definition .
Here value of actual arguments is passed to the formal arguments and operation is done in the
formal argument.
Since formal arguments are photo copy of actual argument, any change of the formal arguments
does not affect the actual arguments
Changes made to the formal argument t are local to block of called function, so when control
back to calling function changes made vanish.
Example:
{
int t;
t = a;
a=b;
b = t;
main( )
Output:
50, 25
Explanation:
After that control enters into the function a temporary memory space ‘t’ is created when int t is
executed.
50;
after this control again enters into the main function and execute the print function print (k,m).
it returns the value 50 , 25.
NOTE:
Whatever change made in called function not affects the values in calling function.
Call by reference:
Here instead of passing value address or reference are passed. Function operators or address
rather than values .Here formal arguments are the pointers to the actual arguments.
Example
#include<stdio.h>
void add(int *n);
int main()
{
int num=2;
printf(“\n The value of num before calling the function=%d”, num);
add(&num);
printf(“\n The value of num after calling the function = %d”, num);
return 0;
}
void add(int *n)
{
*n=*n+10;
printf(“\n The value of num in the called function = %d”, n);
}
Output:
NOTE:
In call by address mechanism whatever change made in called function affect the values in
calling function.
Call By Value Call By Reference
In this method, the value of each variable in In this method, the address of actual variables in the
calling function is copied into corresponding calling function are copied into the dummy variables
dummy variables of the called function. of the called function.
Call By Value Call By Reference
Thus actual values of a and b remain unchanged Thus, actual values of a and b get changed after
even after exchanging the values of x and y. exchanging values of x and y.
In call-by-values, we cannot alter the values of In call by reference, we can alter the values of
actual variables through function calls. variables through function calls.
Values of variables are passed by the Simple Pointer variables are necessary to define to store the
technique. address values of variables.
Scope Rules
A scope in any programming is a region of the program where a defined variable can have its existence and
beyond that variable it cannot be accessed. There are three places where variables can be declared in C
programming language −
● Inside a function or a block which is called local variables.
● Outside of all functions which is called global variables.
● In the definition of function parameters which are called formal parameters.
Let us understand what are local and global variables, and formal parameters.
Local Variables
Variables that are declared inside a function or block are called local variables. They can be used only by
statements that are inside that function or block of code. Local variables are not known to functions
outside their own. The following example shows how local variables are used. Here all the variables a, b,
and c are local to main() function.
Live Demo
#include <stdio.h>
int main () {
/* actual initialization */
a = 10;
b = 20;
c = a + b;
printf ("value of a = %d, b = %d and c = %d\n", a, b, c);
return 0;
}
Global Variables
Global variables are defined outside a function, usually on top of the program. Global variables hold their
values throughout the lifetime of your program and they can be accessed inside any of the functions
defined for the program.
A global variable can be accessed by any function. That is, a global variable is available for use throughout
your entire program after its declaration. The following program show how global variables are used in a
program.
Live Demo
#include <stdio.h>
int main () {
/* actual initialization */
a = 10;
b = 20;
g = a + b;
return 0;
}
A program can have same name for local and global variables but the value of local variable inside a
function will take preference. Here is an example −
Live Demo
#include <stdio.h>
int main () {
return 0;
}
When the above code is compiled and executed, it produces the following result −
value of g = 10
Type Qualifiers
Type qualifiers in C: In the C programming language, type qualifiers are the keywords that prepend to the
variables to change their accessibility, i.e., we can tell that the type qualifiers are used to change the
properties of variables. In other words, the qualifiers are the keywords that are applied to the data types or
the type modifiers in C.
Types of type qualifiers
There are three types of type qualifier variables in the C programming language.
● const
● volatile
● restrict
Type qualifiers are basically the keywords that are used to modify the properties of the existing variables.
1. Const qualifier
● The const qualifier is used to declare a variable to be read only (constant), the value may not be
changed, and it can be declared using the keyword const.
● This qualifier will help to prevent accidental changes in the values.
● In order to declare a const qualifier, include the keyword const before or after any data type.
Syntax
The syntax for declaring a const qualifier is:
const data-type constant-name = value;
Or
data-type const constant-name = value;
Use the const type qualifier to qualify an object whose value cannot be changed at any given time.
The objects qualified by the ‘const’ keyword cannot be modified, i.e., an object declared as a ‘const’ cannot
serve as an operand in an operation that changes its value in further operations.
int const *p_ci; /* Pointer to constant int*/
int const (*p_ci); /* Pointer to constant int*/
int *const cp_i; /* Constant pointer to int*/
int (*const cp_i); /*Constant pointer to int*/
int volatile vint; /* Volatile integer*/
E.g.:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
const float pi = 3.14;
printf (“The value of pi is = %f \n”, pi);
return 0;
}
Output
● The const qualifier can be used to qualify any data type, including the single member of a structure
or a union.
● If const is specified when declaring an aggregate type, all the aggregate type members are treated
as objects qualified with const. When the keyword const is used to qualify a member of any
aggregate type, only that member will be qualified.
2. Volatile qualifier
● A volatile qualifier is used to declare a variable that can be changed at any point of time and
explicitly, i.e., it always tells the compiler that the variable’s value may change at any time.
o It will be useful for embedding programming in order to keep the updated value that can be
changed from various interrupts.
o To declare a volatile variable, the keyword ‘volatile’ is used.
o In order to declare a volatile variable, include the keyword volatile before or after the data
type.
Syntax
The syntax to declare ta volatile variable is as follows:
volatile data-type variable-name;
Or
data-type volatile variable-name;
An object without the volatile specifier will not tell the compiler to perform the optimizations. It indicates
that the compiler can apply any optimizations depending on the program context and compiler
optimization levels.
E.g.:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int x = 0;
volatile int y = 0;
int main()
{
y = 0; /* the compiler optimizes the code and else will be optimized
because the variable(x) will never be other than 0*/
if (x == 0)
{
printf (“The value of the variable x is zero \n”);
}
else
{
printf (“The value of the variable x is not zero \n”);
}
if (x == 0)
{
printf (“The value of the variable y is zero \n”);
}
else
{
printf (“The value of the variable y is not zero \n”);
}
return 0;
}
Output
Optimizations that are defeated by using the volatile qualifier and can be categorized as follows:
● Optimizations alter an object's duration, such as cases where referencing to an object is shifted or
moved to another part of the program.
● Optimizations alter an object's locality, such as cases where a variable serving as a loop counter
can be stored in a register to save the cost of doing any memory reference.
● Optimizations alter an object's existence, such as loop induction to eliminate the variable
reference.
3. Restrict qualifier
● The new type of qualifier introduced to C99 can be applied to pointer declarations.
● It qualifies the pointer, not what it points at.
● It is an optimization hint that no other pointer in the present scope refers to the exact location.
● It acts as a contract between a developer and a compiler. If you do alias a pointer marked with
restrict, then the result is undefined.
E.g.:
#include <stdio.h>
void my_function(int* x, int* y, int* restrict z) {
*x += *z;
*y += *z;
}
main(void) {
int x = 10, y = 20, z = 30;
my_function(&x, &y, &z);
printf("%d %d %d", x, y, z);
}
Output
Marking union members as restrict will tell the compiler that only some of the options can be accessed in
scope, allowing the compiler to optimize the access to members.
RECURSION
Recursion is a process in which a problem is defined in terms of itself. In ‘C’ it is possible to call a
function from itself. Functions that call themselves are known as recursive functions, i.e. a
statement within the body of a function calls the same function. Recursion is often termed as
‘Circular Definition’. Thus recursion is the process of defining something in terms of itself. To
implement recursion technique in programming, a function should be capable of calling itself.
Example:
Here the function fun1() is calling itself inside its own function body, so fun1() is a recursive
function. When main() calls fun1(), the code of fun1() will be executed and since there is a call to
fun1() insidefun1(), again fun1() will be executed. It looks like the above program will run up to
infinite times but generally a terminating condition is written inside the recursive functions
which end this recursion. The following program (which is used to print all the numbers starting
from the given number to 1 with successive decrement by 1) illustrates this:
How to write a Recursive Function?
Before writing a recursive function for a problem its necessary to define the solution of the
problem in terms of a similar type of a smaller problem.
(i). Identify the Non-Recursive part(base case) of the problem and its solution(Part of
the problem whose solution can be achieved without recursion).
(ii). Identify the Recursive part(general case) of the problem(Part of the problem
where recursive call will be made).
Identification of Non-Recursive part of the problem is mandatory because without it the function
will keep on calling itself resulting in infinite recursion.
How control flows in successive recursive calls?
Consider the following program which uses recursive function to compute the factorial of a
number.
In the above program if the value entered by the user is 1 i.e.n=1, then the value of n is copied
into m. Since the value of m is 1 the condition ‘if(m==1)’ is satisfied and hence 1 is returned
through return statement i.e. factorial of 1 is 1.
When the number entered is 2 i.e. n=2, the value of n is copied into m. Then in function fact(),
the condition ‘if(m==1)’ fails so we encounter the statement a=m*fact(m-1); and here we meet
recursion. Since the value of m is 2 the expression (m*fact(m-1)) is evaluated to (2*fact(1)) and
the result is stored in a(factorial of a). Since value returned by fact(1) is 1 so the above
expression reduced to (2*1) or simply 2. Thus the expression m*fact(m-1) is evaluated to 2 and
stored in a and returned to main(). Where it will print ‘Factorial of 2 is 2’.
In the above program if n=4 then main() will call fact(4) and fact(4) will send back the computed
value i.e. f to main(). But before sending back to main() fact(4) will call fact(4-1) i.e. fact(3) and
wait for a value to be returned by fact(3). Similarly fact(3) will call fact(2) and so on. This series of
calls continues until m becomes 1 and fact(1) is called, which returns a value which is so called as
termination condition. So we can now say what happened for n=4 is as follows
All recursive functions work in two phases- winding phase and unwinding phase.
Winding phase starts when the recursive function is called for the first time, and ends when the
termination condition becomes true in a call i.e. no more recursive call is required. In this phase
a function calls itself and no return statements are executed.
After winding phase unwinding phase starts and all the recursive function calls start returning in
reverse order till the first instance of function returns. In this phase the control returns through
each instance of the function.
Implementation of Recursion
We came to know that recursive calls execute like normal function calls, so there is no extra
technique to implement recursion. All function calls(Whether Recursive or Non-Recursive) are
implemented through run time stack. Stack is a Last In First Out(LIFO) data structure. This means
that the last item to be stored on the stack(PUSH Operation) is the first one which will be
deleted(POP Operation) from the stack. Stack stores Activation Record(AR) of function during
run time. Here we will take the example of function fact() in the previous recursive program to
find factorial of a number.
Now will see how the run time stack changes during the evaluation of factorial of 3.
The following steps will reveal how the above stack contents were expressed:
First main() is called, so PUSH AR of main() into the stack. Then main() calls fact(3) so PUSH AR of
fact(3). Now fact(3) calls fact(2) so PUSH AR of fact(2) into the stack. Likewise PUSH AR of fact(1).
After the above when fact(1) is completed, POP AR of fact(1), Similarly after completion of a
specific function POP its corresponding AR. So when main() is completed POP AR of main(). Now
stack is empty.
In the winding phase the stack content increases as new Activation Records(AR) are created and
pushed into the stack for each invocation of the function. In the unwinding phase the Activation
Records are popped from the stack in LIFO order till the original call returns.
Examples of Recursion
Q1. Write a program using recursion to find the summation of numbers from 1 to n.
Ans: We can say ‘sum of numbers from 1 to n can be represented as sum of numbers from 1 to
n- 1 plus n’ i.e.
= n+ n-1 + n-2 + +1
#include<stdio.h>
void main()
int n,s;
printf(“Enter a number”);
scanf(“%d”,&n); s=sum(n);
}
int sum(int m) int r;
if(m==1)
return (1);
else
r=m+sum(m-1);/*Recursive Call*/
return r;
Output:
Enter a number
5 15
Q2. Write a program using recursion to find power of a number i.e. nm.
Ans: We can write,
nm = n*nm-1
=n*n*nm-2
#include<stdio.h>
int power(int,int);
void main()
int n,m,k;
scanf(“%d%d”,&n,&m);
k=power(n,m);
if(y==0)
return 1;
else
{
return(x*power(x,y-1));
}
Output:
Enter the value of n and
m3
5
The value of nm for n=3 and m=5 is 243
Ans: The GCD or HCF (Highest Common Factor) of two integers is the greatest integer that
divides both the integers with remainder equals to zero. This can be illustrated by Euclid’s
remainder Algorithm which states that GCD of two numbers say x and y i.e.
GCD(x, y) = x if y is 0
#include<stdio.h>
int GCD(int,int);
void main()
{
int a,b,gcd;
printf(“Enter two numbers”);
scanf(“%d%d”,&a,&b);
gcd=GCD(a,b);
printf(“GCD of %d and %d is %d”,a,b,gcd);
}
int GCD(int x, int y)
{
if(y==0)
return x;
else
return GCD(y,x%y);
}
Output:
Enter two numbers 21
35
GCD of 21 and 35 is 7
Ans: Fibonacci series is a sequence of integers in which the first two integers are 1 and from
third integer onwards each integer is the sum of previous two integers of the sequence i.e.
Output:
Enter the number of terms of Fibonacci Series which is going to be printed
6 1 1 2 3 5 8 13
STORAGE CLASSES
To completely define a variable one needs to mention its type along with its storage class. In
other words we can say not only variables have a data type but also they have ‘storage classes.
Till now the storage class of any variable is not mentioned because storage classes have defaults.
If someone doesn’t specify the storage class of a variable during its declaration, the compiler
assumes a storage class depending upon the situation in which the variable is going to be used.
Therefore we can now say every variable have certain default storage class.
Compiler identifies the physical location within the computer where the string of bits which
represents the variable’s values are stored from the variable name itself.
Generally there are two kinds of locations in a computer where such a value can be present,
these are Memory and CPU registers. The storage class of a particular variable determines in
which of the above two locations the variable’s value is stored.
There are four properties by which storage class of a variable can be recognized.These are scope,
default initial value, scope and life.
There are four storage classes in C, these are Automatic, Static, Register and External. The
keywords auto, static, registers and exter are used for the above storage classes respectively.
general syntax is
Storag
e Class
Automatic Memory Garbage Value Local to the block Till the control
in which the remains within the
variable is defined block in which the
variable is defined
Register CPU Garbage Value Local to the block Till the control
Registers in which the remains within the
variable is defined block in which the
variable is defined
Example:
auto int i;
Storage: Memory
Default Initial Value: Garbage Value
Scope: Local to the block in which the variable is defined
Life: Till the control remains within the block in which the variable is defined
All the variables which are declared inside a block or function without any storage class specifier
are automatic variables. So by default every variable is automatic variable. We can use auto
keyword to declare automatic variables but generally it is not done. Since automatic variables
are known inside a function or block only, we may have variables of same name in different
functions or blocks without any doubt. Look at the following two functions:
{ {
} }
In the above two functions declaration statements are equivalent as both declare variables x and
y as automatic variables.
void test();
void main()
{
test();
test();
test();
}
void test()
{
auto int k=10;
printf(“%d\n”,k);
k++;
}
Output:
10
10
10
In the above program when the function test() is called for the first time ,variable k is created
and initialized to 10. When the control returns to main(), k is destroyed. When function test() is
called for the second time again k is created , initialized and destroyed after execution of the
function. Hence automatic variables came into existence each time the function is executed and
destroyed when execution of the function completes.
Life: Till the control remains within the block in which the variable is defined
Register storage class can be applied only to automatic variables. Its scope, life and default initial
value are same as that of automatic variables. The only difference between register and
automatic variables is the place where they are stored. Automatic variables are stored in
memory but register variables are stored in CPU registers. Registers are small storage units
present in the processor. The variables stored in registers can be accessed much faster than the
variables stored in registers. Hence the variables which are frequently used in a program can be
assigned register storage class for faster execution. For example loop counters are declared as
register variables, which are defined as follows:
int main()
{
register int a;
for(a=0;i<50000;i++)
printf(“%d\t”,a);
return 0;
}
In the above program, variable a was used frequently as a loop counter so the variable a is
defined as a register variable. Register is a not a command but just a request to the compiler to
allocate the memory for the variable into the register. If free registers are available than memory
will be allocated in to the registers. And if there are no free registers then memory will be
allocated in the RAM only (Storage is in memory i.e. it will act as automatic variable).
Every type of variables can be stored in CPU registers. Suppose the microprocessor has 16 bit
registers then they can’t hold a float or a double value which requires 4 and 8 bytes respectively.
But if you use register storage class for a float or double variable then you will not get any error
message rather the compiler will treat the float and double variable as be of automatic storage
class(i.e. Will treat them like automatic variables).
Example:
static int i;
Storage: Memory
Life: Value of the variable continues to exist between different function calls
Now look at the previous program with k is declared as static instead of automatic.
void test();
void main()
{
test();
test();
test();
}
void test()
{
static int k=10;
printf(“%d\n”,k);
k++;
}
Output:
10
11
12
Here in the above program the output is 10, 11, 12, because if a variable is declared as static
then it is initialized only once and that variable will never be initialized again. Here variable k is
declared as static, so when test() is called for the first time k value is initialized to 10 and its value
is incremented by 1 and becomes 11. Because k is static its value persists. When test() is called
for the second time k is not reinitialized to 10 instead its old value 11 is available. So now 11 is
get printed and it value is incremented by 1 to become 12. Similarly for the third time when
test() is called 12(Old value) is printed and its value becomes 13 when executes the statement
‘k++;’
So the main difference between automatic and static variables is that static variables are
initialized to zero if not initialized but automatic variables contain an unpredictable
value(Garbage Value) if not initialized and static variables does not disappear when the function
is no longer active , their value persists, i.e. if the control comes back to the same function again
the static variables have the same values they had last time.
General advice is avoid using static variables in a program unless you need them, because their
values are kept in memory when the variables are not activc which means they occupies space in
memory that could otherwise be used by other variables.
Example:
extern int i;
Storage: Memory
Default Initial Value: Zero
Scope: Global
External variables differ from automatic, register and static variables in the context of scope,
external variables are global on the contrary automatic, register and static variables are local.
External variables are declared outside all functions, therefore are available to all functions that
want to use them.
If the program size is very big then code may be distributed into several files and these files are
compiled and object codes are generated. These object codes linked together with the help of
linker and generate “.exe” file. In the compilation process if one file is using global variable but it
is declared in some other file then it generate error called undefined symbol error. To overcome
this we need to specify global variables and global functions with the keyword extern before
using them into any file. If the global variable is declared in the middle of the program then we
will get undefined symbol error, so in that case we have to specify its prototype using the
keyword extern.
So if a variable is to be used by many functions and in different files can be declared as external
variables. The value of an uninitialized external variable is zero. The declaration of an external
variable declares the type and name of the variable, while the definition reserves storage for the
variable as well as behaves as a declaration. The keyword extern is specified in declaration but
not in definition. Now look at the following four statements
1. auto int a;
2. register int b;
3. static int c;
4. extern int d;
Out of the above statements first three are definitions where as the last one is a declaration.
Suppose there are two files and their names are File1.c and File2.c respectively. Their contents
are as follows:
File1.c
int n=10;
void hello()
printf(“Hello”);
}
File2.c
extern int n;
extern void hello();
void main()
{
printf(“%d”, n);
hello();
}
In the above program File1.obj+ File2.obj=File2.exe and in File2.c value of n will be 10.
The rules that define which storage class is to be executed when are as follows:
(a) Use static storage class if you want the value of a variable to persist between
different function calls.
(b) Use register storage class for those variables that are being used very often in a
program, for faster execution. A typical application of register storage class is loop
counters.
(c) Use extern storage class for only those variables that are being used by almost all
the functions in a program, this avoids unnecessary passing of these variables as
arguments when making a function call.
(d) If someone do not have any need mentioned above, then use auto storage class.
MEMORY ALLOCATION
The concept of dynamic memory allocation in c language enables the C programmer to allocate
memory at runtime. Dynamic memory allocation in c language is possible by 4 functions of stdlib.h
header file.
1. malloc()
2. calloc()
3. realloc()
4. free()
Before learning above functions, let's understand the difference between static memory allocation
and dynamic memory allocation.
memory can't be increased while executing program. memory can be increased while executing program.
malloc() function in C
The malloc() function allocates single block of requested memory.
It doesn't initialize memory at execution time, so it has garbage value initially.
It returns NULL if memory is not sufficient.
The syntax of malloc() function is given below:
1. ptr=(cast-type*)malloc(byte-size)
Let's see the example of malloc() function.
1. #include<stdio.h>
2. #include<stdlib.h>
3. int main(){
4. int n,i,*ptr,sum=0;
5. printf("Enter number of elements: ");
6. scanf("%d",&n);
7. ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc
8. if(ptr==NULL)
9. {
10. printf("Sorry! unable to allocate memory");
11. exit(0);
12. }
13. printf("Enter elements of array: ");
14. for(i=0;i<n;++i)
15. {
16. scanf("%d",ptr+i);
17. sum+=*(ptr+i);
18. }
19. printf("Sum=%d",sum);
20. free(ptr);
21. return 0;
22. }
Output
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
calloc() function in C
The calloc() function allocates multiple block of requested memory.
It initially initialize all bytes to zero.
It returns NULL if memory is not sufficient.
The syntax of calloc() function is given below:
1. ptr=(cast-type*)calloc(number, byte-size)
Let's see the example of calloc() function.
1. #include<stdio.h>
2. #include<stdlib.h>
3. int main(){
4. int n,i,*ptr,sum=0;
5. printf("Enter number of elements: ");
6. scanf("%d",&n);
7. ptr=(int*)calloc(n,sizeof(int)); //memory allocated using calloc
8. if(ptr==NULL)
9. {
10. printf("Sorry! unable to allocate memory");
11. exit(0);
12. }
13. printf("Enter elements of array: ");
14. for(i=0;i<n;++i)
15. {
16. scanf("%d",ptr+i);
17. sum+=*(ptr+i);
18. }
19. printf("Sum=%d",sum);
20. free(ptr);
21. return 0;
22. }
Output
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
realloc() function in C
If memory is not sufficient for malloc() or calloc(), you can reallocate the memory by realloc()
function. In short, it changes the memory size.
Let's see the syntax of realloc() function.
1. ptr=realloc(ptr, new-size)
free() function in C
The memory occupied by malloc() or calloc() functions must be released by calling free() function.
Otherwise, it will consume memory until program exit.
Let's see the syntax of free() function.
1. free(ptr)
Pointer to Function
As we know that we can create a pointer of any data type such as int, char, float, we can also create a
pointer pointing to a function. The code of a function always resides in memory, which means that the
function has some address. We can get the address of memory by using the function pointer.
Let's see a simple example.
1. #include <stdio.h>
2. int main()
3. {
4. printf("Address of main() function is %p",main);
5. return 0;
6. }
The above code prints the address of main() function.
Output
In the above output, we observe that the main() function has some address. Therefore, we conclude
that every function has some address.
Declaration of a function pointer
Till now, we have seen that the functions have addresses, so we can create pointers that can contain
these addresses, and hence can point them.
Syntax of function pointer
1. return type (*ptr_name)(type1, type2…);
For example:
1. int (*ip) (int);
In the above declaration, *ip is a pointer that points to a function which returns an int value and
accepts an integer value as an argument.
1. float (*fp) (float);
In the above declaration, *fp is a pointer that points to a function that returns a float value and
accepts a float value as an argument.
We can observe that the declaration of a function is similar to the declaration of a function pointer
except that the pointer is preceded by a '*'. So, in the above declaration, fp is declared as a function
rather than a pointer.
Till now, we have learnt how to declare the function pointer. Our next step is to assign the address of
a function to the function pointer.
1. float (*fp) (int , int); // Declaration of a function pointer.
2. float func( int , int ); // Declaration of function.
3. fp = func; // Assigning address of func to the fp pointer.
In the above declaration, 'fp' pointer contains the address of the 'func' function.
Note: Declaration of a function is necessary before assigning the address of a function to the
function pointer.
Calling a function through a function pointer
We already know how to call a function in the usual way. Now, we will see how to call a function using
a function pointer.
Suppose we declare a function as given below:
1. float func(int , int); // Declaration of a function.
Calling an above function using a usual way is given below:
1. result = func(a , b); // Calling a function using usual ways.
Calling a function using a function pointer is given below:
1. result = (*fp)( a , b); // Calling a function using function pointer.
Or
1. result = fp(a , b); // Calling a function using function pointer, and indirection operator can b
e removed.
The effect of calling a function by its name or function pointer is the same. If we are using the
function pointer, we can omit the indirection operator as we did in the second case. Still, we use the
indirection operator as it makes it clear to the user that we are using a function pointer.
Let's understand the function pointer through an example.
1. #include <stdio.h>
2. int add(int,int);
3. int main()
4. {
5. int a,b;
6. int (*ip)(int,int);
7. int result;
8. printf("Enter the values of a and b : ");
9. scanf("%d %d",&a,&b);
10. ip=add;
11. result=(*ip)(a,b);
12. printf("Value after addition is : %d",result);
13. return 0;
14. }
15. int add(int a,int b)
16. {
17. int c=a+b;
18. return c;
19. }
Output
1. Passing each item of the structure as a function argument. It is similar to passing normal
values as arguments. Although it is easy to implement, we don’t use this approach because if
the size of a structure is a bit larger, then our life becomes miserable.
2. Pass the whole structure as a value.
3. We can also Pass the address of the structure (pass by reference).
The following examples will explain to you, How to Pass Structures to functions in C by value and
By referencePass Structure to a Function By Value in C
If the structure is passed to the function by the value, then Changes made to the structure variable
members within the function will not reflect the original structure members.
This program for Structures and Functions in C, User is asked to enter, Student Name, First Year Marks,
and Second Year Marks. By using these values, this program will check whether the student is eligible
for a scholarship or not.
Please refer to Call By Value and Call By Reference to the Functions post to know the difference
between pass by value and pass by reference. Here, we are going to discuss the second and third
approaches
#include <stdio.h>
struct Student
char Student_Name[50];
float First_Year_Marks;
float Second_Year_Marks;
};
int main()
{
scanf("%s",&Student1.Student_Name);
scanf("%f",&Student1.First_Year_Marks);
scanf("%f",&Student1.Second_Year_Marks);
PassBy_Value(Student1);
return 0;
Average = Sum/2;
else
In these Structures and Functions in C example, Declared the Student structure with Student Name,
First Year Marks, Second Year Marks members with appropriate Data Types.
Within the C Programming main(), we created the Student structure variable Student1
Printf and scanf statements in the next lines used to ask the users to enter the Student Name, First
Year Marks, Second Year Marks.
PassBy_Value(Student1);
When the compiler reaches this, then it will traverse to the top. And check for the function definition
or else declaration of the PassBy_Value (struct). If the func fails to identify the function with
PassBy_Value name, then it will throw an error.
We declared 2 float local variables Sum and Average to calculate the Sum and average of every
student’s first-year marks and second-year marks. Depending upon the result, this program will find
whether the student is eligible for Scholarship or Not.
Average = Sum/2;
In the next line, We used If statement to check whether the calculated average is greater than 900 or
not
● If the calculated Average is Greater than 900 then, He is Eligible for Scholarship
● If the calculated Average is Less than or Equal to 900 then, He is Not Eligible for Scholarship
NOTE: Dot operator (.) is used to Assign or Access the values of Structure Variable
Passing Structure to a Function By Reference
In this Structure and Functions in C program, User asked to enter Lecturer Name, Total years of
experience, and Total years of experience in this particular college.
#include <stdio.h>
#include <string.h>
struct Lecturer
char Lecturer_Name[50];
int Total_Experience;
int Experience_In_This_College;
};
int main()
scanf("%s",&Lecturer1.Lecturer_Name);
printf("Please Enter Lecturers Total Years of Experience\n");
scanf("%d",&Lecturer1.Total_Experience);
scanf("%d",&Lecturer1.Experience_In_This_College);
PassBy_Reference(&Lecturer1);
return 0;
Lecturers->Total_Experience = 5;
Lecturers->Experience_In_This_College = 3;
Suresh
10
Within this Structure and Functions in C example, Declared the Lecturer structure with Lecturer
Name, Lecturers Total Years of Experience, and Lecturers Total Years of Experience in this College
member with appropriate Data Types.
Printf and scanf statements in the next lines used to ask the users to enter the Lecturer Name,
Lecturers Total Years of Experience, and Lecturers Total Years of Experience in this College. As per our
example, the values for Lecturer1 are as follows
PassBy_Reference(&Lecturer1);
Here, We passed the address of the Lecturer1 structure to the function instead of its Clone. It means
any changes made to the structural members within the func will reflect the original values.
Within the function Definition, We haven’t done anything special, Just assigned new values to the
Lecturer structure.
Lecturers->Total_Experience = 5;
Lecturers->Experience_In_This_College = 3;
It means
Since we passed the address of the Lecturer1 to the PassBy_Reference(), these new values will replace
the user entered values. The -> operator is used to Assign or Access the values of Pointer Variable
Command Line Arguments
It is possible to pass some values from the command line to your C programs when they are executed.
These values are called command line arguments and many times they are important for your
program especially when you want to control your program from outside instead of hard coding those
values inside the code.
The command line arguments are handled using main() function arguments where argc refers to the
number of arguments passed, and argv[] is a pointer array which points to each argument passed to
the program. Following is a simple example which checks if there is any argument supplied from the
command line and take action accordingly −
#include <stdio.h>
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
When the above code is compiled and executed with single argument, it produces the following
result.
$./a.out testing
The argument supplied is testing
When the above code is compiled and executed with a two arguments, it produces the following
result.
$./a.out
One argument expected
It should be noted that argv[0] holds the name of the program itself and argv[1] is a pointer to the
first command line argument supplied, and *argv[n] is the last argument. If no arguments are
supplied, argc will be one, and if you pass one argument then argc is set at 2.
You pass all the command line arguments separated by a space, but if argument itself has a space
then you can pass such arguments by putting them inside double quotes "" or single quotes ''. Let us
re-write above example once again where we will print program name and we also pass a command
line argument by putting inside double quotes −
#include <stdio.h>
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
When the above code is compiled and executed with a single argument separated by space but inside
double quotes, it produces the following result.
$./a.out "testing1 testing2"
Preprocessor Commands
The C preprocessor is a micro processor that is used by compiler to transform your code before
compilation. It is called micro preprocessor because it allows us to add macros.
Note: Proprocessor direcives are executed before compilation.
All preprocessor directives starts with hash # symbol.
Let's see a list of preprocessor directives.
o #include
o #define
o #undef
o #ifdef
o #ifndef
o #if
o #else
o #elif
o #endif
o #error
o #pragma
The C preprocessor is a micro processor that is used by compiler to transform your code before
compilation. It is called micro preprocessor because it allows us to add macros.
Note: Proprocessor direcives are executed before compilation.
1. File Inclusion: A file inclusion directive is an external file containing function macro definitions,
that can be included using #include directive. The name suggests you need to include any file
at the start of the program. The syntax of this directive is as follows:
#define Age 18
int main()
{
#ifdef Age // conditional compilation directives
printf("This person is over %d years old.\n", Age);
#endif // also a conditional compilation directive
printf("So, he is eligible.\n");
return 0;
}
Output:
This person is over 18 years old.
So, he is eligible.
Explanation: In the above example, conditional directive #ifdef is used to apply the condition in the
code, and #endif is used to terminate the code if the condition is satisfied.
3. Line Control: This preprocessor directive in C provided information about the error or mistakes
in a program. It gives the line number where there is an error in syntax, indentation, etc.
Syntax as follows:
Syntax 1
# line-number “file_name”
Syntax 2
# line line-number “file_name”
Let us see an example.
#include <stdio.h>
void function_1();
void function_2();
void function_1()
{
printf("Inside the function_1()\n");
}
void function_2()
{
printf("Inside the function_2()\n");
}
int main()
{
void function_1();
void function_2();
printf("Inside the main()\n");
return 0;
}
Output:
Inside the main()
Explanation: In the above example, line control preprocessor directives #pragma is used to switch the
control of line execution of code.
● #include : This directive is used to include a header file. It searched the entire directory and
finds that particular header file as specified by the user.
● #include "file": This directive searched for the header file in the current directory. The
directory of the current input file is called the current directory.
● #include anything else: If any of the above two cases failed, then this directive is used.
2. #define:
This preprocessor directive in C comes under Macros. A macro is one when some particular section of
code is substituted by the value of the macro. There are two types of Macros:
1. Object-like Macros: When the macro is replaced by a value, generally for numerical value.
Example:- Here, "PI" is used with the preprocessor dictie. So the value of 'PI' = 3.1415 will be
assigned in the code.
#define PI 3.1415
● Preprocessor directives in C are the simple text processing tool that starts with a hash #.
● All the codes before compilation, goes to the preprocessor for preprocessing.
● There are four types of derivatives in C that is Macros, File Inclusion, Conditional Compilation,
and Line Control derivatives.
● Some part of the code is replaced by a name, known as Macros.
FILE
A File is a collection of data stored on a secondary storage device like hard disk. File
operation is to combine all the input data into a file and then to operate through the C
program. Various operations like insertion, deletion, opening closing etc can be done upon
a file. When the program is terminated, the entire data is lost in C programming. If you
want to keep large volume of data, it is time consuming to enter the entire data. But, if file
is created these information can be accessed using few commands.
There are large numbers of functions to handle file I/O in C language. In this tutorial, you
will learn to handle standard I/O(High level file I/O functions) in C. High level file I/O
functions can be categorized as:
1. Text file
2. Binary file
A file can be open in several modes for these operations. The various modes are:
fopen and freopen opens the file whose name is in the string pointed to by filename and
associates a stream with it. Both return a pointer to the object controlling the stream, or if
the open operation fails a null pointer. The error and end-of-file(EOF) indicators are cleared,
and if the open operation fails error is set. freopen differs from fopen in that the file
pointed to by stream is closed first when already open and any close errors are ignored.
fo
pe
n()
fil
e
*f
p;
fp=fopen(“student.DAT”,
“r”); if(fp==NULL)
Q2. Write a C program to read name and marks of n number of students from user and
store them in a file. If the file previously exits, add the information of n students.
Ans:
#include
<stdio.h> int
main()
char
name[50];
int marks,
i,n;
printf(“Enter number of
students”);
scanf(“%d”, &n);
FILE *fptr;
fptr=(fopen(“C:\\student.txt”,”a”));
if (fptr==NULL){
printf("Error!"); exit(1);
for(i=0;i<n;++i)
printf(“Enter
marks”);
scanf(“%d”,
&marks);
fclose(f
ptr);
Return
0;
The fclose function causes the stream pointed to be flushed and the associated file to be
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 stream is
disassociated from the file. If the associated buffer was automatically allocated, it is
deallocated. The function returns zero if the stream was successfully closed or EOF if any
errors were detected.
Q.3. Write a program to read data from file and close using fclose
function. Ans:
#include
<stdio.h> int
main()
int n
FILE *fptr;
if
((fptr=fopen("C:\\program.txt","r"))==NULL
fscanf(fptr,"%d",&n);
printf("Value of
n=%d",n);
fclose(fptr);
return 0;
Q4. Write a C program to write all the members of an array of strcures to a file using
fwrite(). Read the array from the file and display on the screen.
Ans:
#include<std
io.h> Struct
s
{
Char
name[50];
Int height;
};
Int main()
{
Struct s a[5],
b[5]; FILE
*fptr;
Int I;
Fptr=fopen(“file.txt”,
“wb”); For(i=0; i<5; ++i)
{
fflush(stdin);
fwrite(a,sizeof(a),1,fptr);
fclose(fptr);
fptr=fopen("file.txt","rb");
fread(b,sizeof(b),1,fptr);
for(i=0;i<5;++i)
{
printf("Name: %s\nHeight: %d",b[i].name,b[i].height);
} fclose(fptr);
}
In the above table we have discussed about various file I/O functions to perform reading and writing
on file. getc() and putc() are the simplest functions which can be used to read and write individual
characters to a file.
#include<stdio.h>
int main()
FILE *fp;
char ch;
fp = fopen("one.txt", "w");
printf("Enter data...");
putc(ch, fp);
fclose(fp);
fp = fopen("one.txt", "r");
printf("%c",ch);
// closing the file pointer
fclose(fp);
return 0;
Copy
#include<stdio.h>
struct emp
char name[10];
int age;
};
void main()
{
struct emp e;
FILE *p,*q;
p = fopen("one.txt", "a");
q = fopen("one.txt", "r");
fclose(p);
do
while(!feof(q));
Copy
In this program, we have created two FILE pointers and both are refering to the same file but in
different modes.
fprintf() function directly writes into the file, while fscanf() reads from the file, which can then be
printed on the console using standard printf() function.
Difference between Append and Write Mode
Write (w) mode and Append (a) mode, while opening a file are almost the same. Both are used to
write in a file. In both the modes, new file is created if it doesn't exists already.
The only difference they have is, when you open a file in the write mode, the file is reset, resulting in
deletion of any data already present in the file. While in append mode this will not happen. Append
mode is used to append or add data to the existing data of file(if any). Hence, when you open a file in
Append(a) mode, the cursor is positioned at the end of the present data in the file.
ftell ( )
It returns the current position of the file ptr.
The syntax is as follows −
int n = ftell (file pointer)
For example,
FILE *fp;
int n;
_____
_____
_____
n = ftell (fp);
Note − ftell ( ) is used for counting the number of characters which are entered into a file.
rewind ( )
It makes file ptr move to beginning of the file.
The syntax is as follows −
rewind (file pointer);
For example,
FILE *fp;
-----
-----
rewind (fp);
n = ftell (fp);
printf ("%d”, n);
Output
The output is as follows −
0 (always).
fseek ( )
It is to make the file pntr point to a particular location in a file.
The syntax is as follows −
fseek(file pointer, offset, position);
Offset
● The no of positions to be moved while reading or writing.
● If can be either negative (or) positive.
o Positive - forward direction.
o Negative – backward direction.
Position
It can have three values, which are as follows −
● 0 – Beginning of the file.
● 1 – Current position.
● 2 – End of the file.
Example
● fseek (fp,0,2) - fp moved 0 bytes forward from the end of the file.
● fseek (fp, 0, 0) – fp moved 0 bytes forward from beginning of the file
● fseek (fp, m, 0) – fp moved m bytes forward from the beginning of the file.
● fseek (fp, -m, 2) – fp moved m bytes backward from the end of the file.
Errors
The errors related to fseek () function are as follows −
● fseek (fp, -m, 0);
● fseek(fp, +m, 2);
The function int ferror(FILE *stream); checks the status of error indicator associated with the given
stream. To get the exact nature of the error, we should use perror function. A call to clearerr, freopen
or rewind clears the error indicator.
int main(){
FILE *file;
char ch;
/* Opening an empty text file in read only mode*/
file = fopen("textFile.txt", "r");
/* It will causes an I/O error trying to write on it */
fputc('A', file);
if(ferror(file))
{
printf("Error: writing in a read only file\n");
/*Clearing error indicators */
clearerr (file);
}
fclose(file);
return(0);
}
Output
Error: writing in a read only file