UNIT 4 c Programming
UNIT 4 c Programming
Functions: Function Prototype, definition and calling. Return statement. Nesting of functions. Categories of
functions. Recursion, Parameter Passing by address & by value. Local and Global variables, Storage classes:
automatic, external, static and register.
Pointers: Pointer data type, Pointer declaration, initialization, accessing values using pointers. Pointer
arithmetic. Pointers and arrays, pointers and functions.
Introduction of Functions
Definition: A function is a block of code that performs a specific task.
Types of Functions:
There are two types of functions in C programming:
1. Standard Library Functions
2. User-Defined Functions
1. Standard Library Functions:
The Standard Library functions are built-in functions in C programming to handle tasks such as I/O
processing, mathematical calculations, and string handling, etc.
Example:
printf() is a standard library function used to send formatted output, and it is defined in the stdio.h header
file.
Common Header Files & Functions:
#include<stdio.h> → printf(), scanf(), puts(), gets(), etc.
#include<conio.h> → clrscr(), getch(), etc.
#include<string.h> → strlen(), strupr(), strlwr(), etc.
#include<math.h> → sqrt(), ceil(), floor(), etc.
2. User-Defined Functions:
C language allows programmers to define their own functions. Such functions created by users are called
User-Defined Functions.
Depending on the complexity and requirements of the program, you can create as many user-defined
functions as needed.
data_type function_name(parameter_list);
Function Definition
A function definition is also known as function implementation.
1. Function Header
2. Function Body
1. Function Header:
2. Function Body:
Example:
Function Call
A function is called by simply using the function name followed by actual arguments.
Syntax:
variable_name = function_name(arguments);
Example:
c = sum(a, b);
Example:
c = sum(10, 20);
#include <stdio.h>
#include <conio.h>
// Function Prototype
int sum(int a, int b);
void main()
{
int n1, n2, total;
clrscr();
// Function Call
total = sum(n1, n2);
getch();
}
// Function Definition
int sum(int a, int b)
{
int result;
result = a + b;
return result;
}
Sample Output:
Enter n1: 10
Enter n2: 20
Total = 30
TERMINOLIGY IN FUNCTIONS:
1. Calling Function
2. Called Function
3. Actual Parameters
The values/variables passed during the function call.
These values are copied (in pass by value) or referenced (in pass by reference).
4. Formal Parameters
The variables declared in the function definition that receive actual parameters.
These act as local variables inside the function.
Return Statement:
The return statement terminates the execution of a function and returns a value to the calling function.
The program control is transferred back to the calling function after the return statement.
In the example above, the value of the variable result is returned to the variable total in the main()
function.
Syntax:
return variable_name;
Example:
return total;
return a + b; // Value will be returned
Nesting Functions :
Nesting of functions refers to calling a function inside another function.
Example:
#include <stdio.h>
#include <conio.h>
// Function declarations
void functionA();
void functionB();
void main()
{
clrscr();
printf("Calling functionA() from main()\n");
functionA(); // Calling functionA from main
getch();
}
// FunctionA calls functionB
void functionA()
{
printf("Inside functionA\n");
functionB(); // Calling functionB from functionA
printf("Back to functionA\n");
}
// FunctionB
void functionB()
{
printf("Inside functionB\n");
}
Sample Output:
CATEGOTIES OF FUNCTIONS:
A user-defined function is one that is defined by the user when writing any program, as we do not have
library functions that have predefined definitions.
#include <stdio.h>
#include <conio.h>
// Function definition
void greet()
{
printf("Hello! Welcome to C programming.");
}
Sample Output:
#include <stdio.h>
#include <conio.h>
void main()
{
int num;
clrscr();
num = generateNumber(); // Function call and storing return value
printf("Generated number: %d", num);
getch();
}
// Function definition
int generateNumber()
{
return 10; // Returning a value
}
Sample Output:
Generated number: 10
3. Function with Arguments and No Return Value
#include <stdio.h>
#include <conio.h>
void main()
{
int a = 5, b = 10;
clrscr();
addNumbers(a, b); // Function call with arguments
getch();
}
// Function definition
void addNumbers(int x, int y)
{
printf("Sum = %d", x + y); // Prints result but does not return
}
Sample Output:
Sum = 15
#include <stdio.h>
#include <conio.h>
void main()
{
int a = 4, b = 5, result;
clrscr();
result = multiply(a, b); // Function call with arguments and storing return value
printf("Multiplication = %d", result);
getch();
}
// Function definition
int multiply(int x, int y)
{
return x * y; // Returning the result
}
Sample Output:
Multiplication = 20
Recursive functions are useful for repetitive computations, where each action depends on the result of the
previous step. Many iterative problems can be solved using recursion.
Examples of recursion in C:
Factorial Calculation
Fibonacci Series
Tower of Hanoi
Advantages of Recursion
Disadvantages of Recursion
void fun1()
{
fun1(); // Function calls itself
}
#include <stdio.h>
#include <conio.h>
void main()
{
int n;
long int result;
clrscr();
printf("Enter n: ");
scanf("%d", &n);
result = fact(n);
printf("Factorial of %d is %ld", n, result);
getch();
}
Sample Output:
Enter n: 5
Factorial of 5 is 120
5 * 24 = 120 (fact(5))
4 * 6 = 24 (fact(4))
3 * 2 = 6 (fact(3))
2 * 1 = 2 (fact(2))
1 = 1 (fact(1))
Finally, 120 is returned to main() and stored in result, and the output is Factorial of 5 is 120.
The technique used to pass data from one function to another function is known as passing parameters.
1. Pass by Value:
#include <stdio.h>
#include <conio.h>
// Function Prototype
int sum(int a, int b);
void main()
{
int n1, n2, total;
clrscr();
// Function Call
total = sum(n1, n2);
getch();
}
// Function Definition
int sum(int a, int b)
{
int result;
result = a + b;
return result;
}
Sample Output:
Enter n1: 10
Enter n2: 20
Total = 30
In the above example, the function call sum(n1, n2), where n1 and n2 are actual parameters, and the
variables in the function definition a and b are formal parameters.
If any changes are made to the variables a and b, it does not affect the variables n1 and n2 in the main()
function.
2. Pass by Reference:
Example:
#include<stdio.h>
#include<conio.h>
void main()
{
int n1, n2, total;
clrscr();
printf("Enter n1: ");
scanf("%d", &n1);
getch();
}
Sample Output:
Enter n1: 10
Enter n2: 20
Total = 30
Explanation:
In the above example, we are passing the address of n1, n2, and total to the function definition.
In the function definition, formal parameters are created as pointer variables to hold the addresses.
Finally, *c = *a + *b;, meaning the variable c gets updated, and this change reflects in the variable
total in the main() function.
differences between the Call by Value and Call by Reference:
Feature Call by Value Call by Reference
How can we pass the Whole Array to Functions? Explain with example
program.
When you want to pass an entire array to a function, you simply use the array name as the actual
parameter. The formal parameter in the function definition does not need the array size to be specified,
except for multi-dimensional arrays.
One-Dimensional Array:
To pass the whole array, you simply use the array name as the actual parameter. In the called function, we
declare that the corresponding formal parameter is an array. We do not need to specify the number of
elements.
Program:
void main() {
int a[5] = {1, 2, 3, 4, 5};
fun1(a);
}
Explanation:
In this program, the fun1 function takes an array a[] as an argument. It calculates the sum of the
array elements.
The array is passed by its name a, and the formal parameter in the function fun1 is declared as int
a[].
No need to specify the number of elements in the array when passing it. The array can be accessed
inside the function by iterating through its elements.
Two-Dimensional Array:
When passing a 2-D array to a function, the process is similar to passing a 1-D array. However, in the
function definition, the formal parameter must indicate that the array has two dimensions. We need to
specify the size of the second dimension.
Rules:
Program:
void main() {
int a[2][2] = {{1, 2}, {3, 4}};
fun1(a);
}
Explanation:
In this program, fun1 accepts a 2-D array a[][2] as the formal parameter. The second dimension is
specified as 2, but the first dimension is not. This tells the function that it is dealing with a 2-D array
with 2 rows and 2 columns.
Inside the function, we use nested loops to access each element of the 2-D array and print it.
The array is passed by its name a, and the array size is inferred from the function definition.
Scope of Variables:
The scope of a variable defines its visibility within a program. The scope of a variable depends on where it
is declared.
1. Local Variables
2. Global Variables
1. Local Variables:
2. Global Variables:
Example:
#include <stdio.h>
#include <conio.h>
// Global Variable
int total;
void main()
{
// Local Variables
int a, b;
clrscr();
printf("Enter a and b value: ");
scanf("%d %d", &a, &b);
getch();
}
Sample Output:
Explanation:
#include <stdio.h>
#include <conio.h>
void main()
{
auto int a = 20; // Automatic variable
clrscr();
getch();
}
void fun1()
{
int a = 10; // Local variable in fun1()
printf("\na = %d", a); // Printing value of 'a' inside fun1()
}
Sample Output:
a = 10
a = 20
2. External:
#include <stdio.h>
#include <conio.h>
extern int a; // External variable declaration
void main()
{
clrscr();
printf("%d", a); // Print value of external variable
getch();
}
Sample Output:
100
#include <stdio.h>
#include <conio.h>
void main()
{
register int a = 10; // Register variable
clrscr();
printf("Value of register variable a: %d", a);
getch();
}
Sample Output:
#include <stdio.h>
#include <conio.h>
void counter()
{
static int count = 0; // Static variable
count++;
printf("Count = %d\n", count);
}
void main()
{
clrscr();
counter(); // Function call 1
counter(); // Function call 2
counter(); // Function call 3
getch();
}
Sample Output:
Count = 1
Count = 2
Count = 3
static RAM Zero Local Till the end of the main program,
Retains value between multiple
functions call
void fun() {
printf("Hello, World!");
}
The compiled code of fun() is stored in the text segment.
2. Data Segment
This segment stores global and static variables. It has two parts:
Example:
3. Heap Segment
Stores dynamically allocated memory using functions like malloc(), calloc(), and realloc().
The heap grows towards higher memory addresses.
Example:
4. Stack Segment
void function() {
Introduction to Pointer
The pointer in C language is a variable that stores the address of another variable.
This variable can be of type int, char, array, function, or any other pointer.
The size of the pointer depends on the architecture.
However, in a 32-bit architecture, the size of a pointer is 2 bytes.
int n = 10;
int *p = &n; // Variable 'p' of type pointer is pointing to the address of variable 'n' of type integer.
Declaring a Pointer
The pointer in C language can be declared using the * (asterisk) symbol.
It is also known as an indirection pointer, used to dereference a pointer.
As you can see in the above figure, the pointer variable stores the address of the number variable,
i.e., fff4.
The value of the number variable is 50, but the address of the pointer variable p is aaa3.
With the help of the * (indirection operator), we can print the value of the pointer variable p.
#include <stdio.h>
int main() {
int *p;
return 0;
Output
Value of p variable is 50
Pointer to Array
A pointer can be used to point to an array, allowing easy traversal and manipulation of its elements.
Example:
int arr[10];
int *p = arr; // Pointer 'p' is pointing to the address of the first element of the integer array 'arr'.
Pointer to a Function
A function pointer stores the address of a function and can be used to call the function dynamically.
Example:
void show(int);
void (*p)(int) = &show; // Pointer 'p' is pointing to the address of the function 'show'.
Advantages of Pointers
1. Pointers reduce code complexity and improve performance. They are used in handling strings,
trees, arrays, structures, and functions.
2. We can return multiple values from a function using pointers.
3. Pointers allow us to access any memory location in the computer.
Usage of Pointers
In C, we can dynamically allocate memory using malloc() and calloc() functions, where pointers are
used.
Pointers are widely used in arrays, functions, and structures, reducing code size and improving
efficiency.
Understanding Pointers in C
Pointer Definition
A pointer is a special type of variable used to store the memory location (address) of another
variable.
In C programming, we can create pointer variables of any data type.
Every pointer stores the address of the variable with the same data type only.
That means an integer pointer is used to store the address of an integer variable only.
In the above example, %u is used to display the address of the marks variable. The address of any
memory location is an unsigned integer value.
datatype *pointerName;
Example:
int *ptr;
In the above example, the variable ptr is a pointer variable that can be used to store the address of
any integer variable.
int a, *ptr;
In the above declaration, the variable a is a normal integer variable, and ptr is an integer pointer
variable.
If we want to assign the address of variable a to pointer variable ptr, we use the following
statement:
ptr = &a;
In the above statement, the address of variable a is assigned to pointer variable ptr. We say that
pointer variable ptr is pointing to variable a.
*pointerVariableName
Example Code
#include <stdio.h>
#include <conio.h>
void main() {
int a = 10, *ptr;
clrscr();
int a = 10;
int *ptr; // Pointer declaration
ptr = &a; // Pointer initialization
Example:
float a;
int *ptr = &a; // ERROR: type mismatch
While declaring a pointer variable, if it is not assigned to anything, it contains a garbage value.
Therefore, it is recommended to assign a NULL value to it.
NULL Pointer
A pointer that is assigned a NULL value is called a NULL pointer in C.
Example:
#include <stdio.h>
#include <conio.h>
void main() {
int a = 10, *ptr;
clrscr();
#include <stdio.h>
int main() {
int a;
a = 10;
int *p = &a; // Declaring and initializing the pointer
return 0;
}
Output:
10
10
3795480300
3795480300
3795480304
int s = 56;
int *ptr1, *ptr2;
ptr1 = &s;
ptr2 = ptr1;
ptr1 = &s;
ptr2 = ptr1;
return 0;
}
Output
Pointer Arithmetic
We can perform addition and subtraction of an integer constant from a pointer variable.
Addition
ptr1 = ptr1 + 2;
Subtraction
ptr1 = ptr1 - 2;
Invalid Operations
We cannot perform the following operations on two pointer variables:
We can use the increment (++) and decrement (--) operators with pointers to modify the address contained
in the pointer variable.
Example
z = 5 * -*ptr2 / *ptr1;
This is because the symbol /* is considered as the beginning of a comment, which causes a syntax error.
If Ptr1 and Ptr2 are properly declared and initialized pointers, then C allows adding integers to a pointer
variable.
Example:
int a = 5, b = 10;
int *Ptr1, *Ptr2;
Ptr1 = &a;
Ptr2 = &b;
If Ptr1 & Ptr2 are properly declared and initialized pointers, C allows subtracting integers from pointers.
If Ptr1 & Ptr2 are properly declared and initialized pointers, and both point to the elements of the
same type, then subtraction of one pointer from another pointer is also possible.
Note:
This operation is done when both pointer variables point to the elements of the same array.
Example:
We can use the increment operator to increment the address of the pointer variable so that it
points to the next memory location.
The value by which the address of the pointer variable will increment is not fixed.
It depends on the data type of the pointer variable.
Example:
int *ptr;
ptr++;
Thus, the value by which the address of the pointer variable increments is known as the scale factor.
The scale factor is different for different data types, as shown below:
C Program to Compute the Sum of All Elements Stored in an Array Using Pointers
int main()
{
int a[10], i, sum = 0, *p;
printf("Enter 10 elements:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
return 0;
}
Output:
Enter 10 elements:
1
2
3
4
5
6
7
8
9
10
The sum is 55
#include <stdio.h>
int main() {
int x[4];
int i;
Output:
&x[0] = 1450734448
&x[1] = 1450734452
&x[2] = 1450734456
&x[3] = 1450734460
Address of array x: 1450734448
There is a difference of 4 bytes between two consecutive elements of array x. This is because the
size of int is 4 bytes (on our compiler).
Notice that the address of &x[0] and x is the same. This is because the variable name x points to the
first element of the array.
#include <stdio.h>
int main() {
int i, x[6], sum = 0;
printf("Enter 6 numbers: ");
Enter 6 numbers:
2
3
4
4
12
4
Sum = 29
Pointer to Pointer (Double Pointer)
#include <stdio.h>
void main() {
int a = 10;
int *p;
int **pp;
Output
less
CopyEdit
Address of a: d26a8734
Address of p: d26a8738
Value stored at p: 10
Value stored at pp: 10
Dangling Pointers in C
A dangling pointer is a pointer that points to an invalid memory location because the target variable has
been deallocated or is no longer accessible.
1. Memory Deallocation – When a pointer still holds the address of a freed memory block.
2. Out-of-Bounds Access – Trying to access memory outside the valid range of an array.
3. Variable Going Out of Scope – When a local variable goes out of scope, but the pointer still refers
to it.
Void Pointers
Till now, we have studied that the address assigned to a pointer should be of the same type as
specified in the pointer declaration.
For example, if we declare an int pointer, then this pointer cannot point to a float variable or any
other type of variable. It can only point to an int type variable.
To overcome this problem, we use a pointer to void.
A pointer to void means a generic pointer that can point to any data type.
We can assign the address of any data type to the void pointer, and a void pointer can be assigned
to any type of pointer without performing explicit typecasting.
void *pointer_name;
void *ptr;
In the above declaration, void is the type of the pointer, and ptr is the name of the pointer.
The size of the void pointer in C is the same as the size of the pointer of character type.
According to C perception, the representation of a pointer to void is the same as the pointer of
character type.
The size of the pointer will vary depending on the platform that you are using.
#include <stdio.h>
int main() {
void *ptr = NULL; // Void pointer
printf("Size of void pointer = %d\n\n", sizeof(ptr));
return 0;
}
Advantages of Void Pointer
The malloc() and calloc() functions return the void pointer, so these functions can be used to
allocate the memory of any data type.
The void pointer in C can also be used to implement generic functions in C.
#include <stdio.h>
int main() {
int a = 56; // Initialization of an integer variable 'a'.
float b = 4.5; // Initialization of a float variable 'b'.
char c = 'k'; // Initialization of a char variable 'c'.
ptr = &a;
printf("Value of 'a' is: %d", *((int *)ptr));
ptr = &b;
printf("\nValue of 'b' is: %f", *((float *)ptr));
ptr = &c;
printf("\nValue of 'c' is: %c", *((char *)ptr));
return 0;
}
Generic Pointers
When a variable is declared as being a pointer to type void, it is known as a generic pointer.
Since you cannot have a variable of type void, the pointer will not point to any data and therefore cannot
be dereferenced. It is still a pointer, though, and to use it, you just have to cast it to another kind of
pointer first. Hence the term generic pointer.
This is very useful when you want a pointer to point to data of different types at different times.
A void pointer is a specific pointer type – void * – a pointer that points to some data location in storage,
which doesn’t have any specific type.
void refers to the type. Basically, the type of data that it points to can be anything.
If we assign the address of a char data type to a void pointer, it will become a char pointer.
If we assign the address of an int data type to a void pointer, it will become an int pointer, and so
on.
Any pointer type is convertible to a void pointer, hence it can point to any value.
A function has a physical location in memory that can be assigned to a pointer. This address is the entry
point of the function and is the address used when the function is called.
Once a pointer points to a function, the function can be called through that pointer. Function pointers also
allow functions to be passed as arguments to other functions.
A pointer in a function parameter list holds the address of an argument passed during the function call.
This is also known as Call by Reference.
When a function is called by reference, any change made to the reference variable will affect the original
variable.
#include <stdio.h>
int main() {
int p = 10, q = 20;
printf("Before Swapping:\n");
printf("p = %d\n", p);
printf("q = %d\n\n", q);
printf("After Swapping:\n");
printf("p = %d\n", p);
printf("q = %d\n", q);
return 0;
}
Output:
Before Swapping:
p = 10
q = 20
After Swapping:
p = 20
q = 10
Explanation:
The addresses of memory locations p and q are passed to the function swap.
The pointers *a and *b accept those values.
Now, the pointer a and b point to the address of p and q respectively.
When the values of pointers are changed, the values in the pointed memory location also change
correspondingly.
Hence, changes made to *a and *b are reflected in p and q in the main function.
This technique is known as Call by Reference in C programming.
#include <stdio.h>
int main() {
int (*functionPtr)(int, int); // Function pointer declaration
int s;
return 0;
}
Output:
Sum is 65
Explanation:
It is possible to declare a pointer pointing to a function that can then be used as an argument in
another function.
A function pointer is declared as follows:
type (*pointer-name)(parameter);
Example:
A function pointer can point to a specific function when it is assigned the name of the function.
s(10, 20);
Note: Be careful, because local variables of a function do not live outside the function.
If you return a pointer connected to a local variable, that pointer will be pointing to nothing when the
function ends.
#include <stdio.h>
int main() {
int num1, num2;
int *ptr;
return 0;
}
Output: