0% found this document useful (0 votes)
8 views

UNIT 4 c Programming

This document covers the concepts of functions and pointers in C programming, including function prototypes, definitions, calling conventions, recursion, and parameter passing methods. It details the types of functions, their declarations, definitions, and the differences between passing parameters by value and by reference. Additionally, it explains the advantages and disadvantages of recursion and provides examples to illustrate these concepts.

Uploaded by

Arun
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

UNIT 4 c Programming

This document covers the concepts of functions and pointers in C programming, including function prototypes, definitions, calling conventions, recursion, and parameter passing methods. It details the types of functions, their declarations, definitions, and the differences between passing parameters by value and by reference. Additionally, it explains the advantages and disadvantages of recursion and provides examples to illustrate these concepts.

Uploaded by

Arun
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

UNIT-IV: FUNCTIONS, POINTERS

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.

Why Do We Need Functions? (or) Uses of Functions


There are many benefits of using functions, such as:

1. Reduces program size.


2. Divides complex programs into simple sub-tasks.
3. Subprograms are easier to write, understand, and debug.
4. Each subprogram is compiled separately and can be loaded together.
5. Reduces workload and development time.
6. Functions enable code reusability by allowing repeated use without redevelopment.
Function Declarations/Prototypes
The general format for declaring a function is:

data_type function_name(parameter_list);

Example: int sum(int a, int b);

Rules for Function Declarations:

1. The parameter list must be separated by commas.


2. The parameter names do not need to be the same in the prototype and function definition.
3. The data types must match in both the function prototype and definition.
4. The function name should be meaningful, as it is used to call the function in the program.
5. Parameter names are optional in the declaration.
6. Every function declaration must end with a semicolon (;).
7. A function cannot be declared inside another function.
8. A function with void as the return type does not return any value.

Example: void printf(void);

int sum(int a, int b);

Function Definition
A function definition is also known as function implementation.

It is divided into two parts:

1. Function Header
2. Function Body

1. Function Header:

 The function header consists of three parts:


o Function type
o Function name
o Formal parameter list
 It does not have a semicolon at the end.

2. Function Body:

The function body consists of:

 Local variable declarations


 Function statements
 Return statement (to return the value)
Syntax:

return_type function_name(type parameter1, type parameter2, …)


{
// Function body
}

 Variables in the function definition are called parameters.

Example:

int sum(int a, int b)


{
int c;
c = a + b;
return c;
}

Function Call
A function is called by simply using the function name followed by actual arguments.

 Variables passed in the function call are called actual arguments.

Syntax:

variable_name = function_name(arguments);

Example:

c = sum(a, b);

Passing Constant Values to Functions

You can also pass constant values as arguments in a function call.

Example:

c = sum(10, 20);

Complete C Program Example

#include <stdio.h>
#include <conio.h>

// Function Prototype
int sum(int a, int b);

void main()
{
int n1, n2, total;

clrscr();

printf("Enter n1: ");


scanf("%d", &n1);

printf("Enter n2: ");


scanf("%d", &n2);

// Function Call
total = sum(n1, n2);

printf("Total = %d", total);

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

 The function that invokes (calls) another function.


 It passes values (arguments) to the called function.
 Execution control is transferred to the called function.

2. Called Function

 The function that is invoked (executed) by the calling function.


 It processes the received values and returns the result (if applicable).
 Execution control returns to the calling function after execution.

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.

 One function calls another function inside its body.


 The called function must be declared before it is used.
 The execution starts from the main() function and follows the function call hierarchy.

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:

Calling functionA() from main()


Inside functionA
Inside functionB
Back to functionA

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.

Different Types of User-defined Functions in C


There are four types of user-defined functions divided on the basis of arguments they accept and the
value they return:
1. Function with no arguments and no return value
2. Function with no arguments and a return value
3. Function with arguments and no return value
4. Function with arguments and with return value

1. Function with No Arguments and No Return Value

 The function does not take any arguments.


 It does not return a value (void return type).
 It performs an action but does not return any result to the caller.

Example: Printing a Message

#include <stdio.h>
#include <conio.h>

void greet(); // Function declaration


void main()
{
clrscr();
greet(); // Function call
getch();
}

// Function definition
void greet()
{
printf("Hello! Welcome to C programming.");
}

Sample Output:

Hello! Welcome to C programming.

2. Function with No Arguments and a Return Value

 The function does not take arguments.


 It returns a value using the return statement.

Example: Generating a Random Number

#include <stdio.h>
#include <conio.h>

int generateNumber(); // Function declaration

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

 The function takes arguments (inputs).


 It does not return a value (void return type).
 It performs an operation using the provided arguments.

Example: Adding Two Numbers and Displaying Result

#include <stdio.h>
#include <conio.h>

void addNumbers(int, int); // Function declaration

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

4. Function with Arguments and with Return Value

 The function takes arguments (inputs).


 It returns a value to the caller.
 This type of function is most commonly used in real-world applications.

Example: Multiplication of Two Numbers

#include <stdio.h>
#include <conio.h>

int multiply(int, int); // Function declaration

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 (Recursion)


A function that calls itself repeatedly until a condition is met is called a recursive function. This technique
is known as recursion.

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

1) Simpler and shorter method


2) Clear and easy to use
3) Easy to implement
4) Easy to debug (identify and fix errors)
5) An effective technique for certain problems

Disadvantages of Recursion

1) Requires more memory and time


2) Difficult to use with global variables
3) Harder to trace the logic of the function
4) Programmers and readers may find it difficult to understand

Syntax of a Recursive Function

void fun1()
{
fun1(); // Function calls itself
}

Example: Factorial Calculation using Recursion

#include <stdio.h>
#include <conio.h>

long int fact(int x); // Function prototype

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();
}

// Recursive function to calculate factorial


long int fact(int x)
{
if (x > 1)
{
return x * fact(x - 1); // Recursion
}
else
{
return 1; // Base condition
}
}

Sample Output:

Enter n: 5
Factorial of 5 is 120

Explanation of Recursion for Factorial (n = 5)

1. fact(5) → 5 * fact(4) → Recursion (1st time)


2. fact(4) → 4 * fact(3) → Recursion (2nd time)
3. fact(3) → 3 * fact(2) → Recursion (3rd time)
4. fact(2) → 2 * fact(1) → Recursion (4th time)
5. fact(1) = 1 (Base case reached, function stops recursion)

Now, it returns values back to the main function:

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.

Passing Parameters to the Function (or Passing Arguments):

The technique used to pass data from one function to another function is known as passing parameters.

There are two ways to pass parameters in C:

1. Pass by Value – also known as Call by Value


2. Pass by Reference – also known as Call by Address

1. Pass by Value:

✔The value of the actual parameter is passed to the formal parameter.


✔The storage locations of actual and formal parameters are different.
✔The value of the actual parameter is copied into another location, and the formal parameter refers to
this new location.
✔Any changes in the formal parameter do not affect the actual parameter.

Example: Pass by Value

#include <stdio.h>
#include <conio.h>

// Function Prototype
int sum(int a, int b);

void main()
{
int n1, n2, total;

clrscr();

printf("Enter n1: ");


scanf("%d", &n1);

printf("Enter n2: ");


scanf("%d", &n2);

// Function Call
total = sum(n1, n2);

printf("Total = %d", total);

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:

 The address of the actual parameter is passed to the formal parameter.


 The storage locations of actual and formal parameters are different, but the formal parameter
contains the address of the actual parameters.
 If any changes are made to the formal parameters, it affects the actual parameters.
 Address is represented using &, and a pointer variable is represented using *.

Example:

#include<stdio.h>
#include<conio.h>

void sum(int *a, int *b, int *c);

void main()
{
int n1, n2, total;
clrscr();
printf("Enter n1: ");
scanf("%d", &n1);

printf("Enter n2: ");


scanf("%d", &n2);

sum(&n1, &n2, &total);

printf("Total = %d", total);

getch();
}

void sum(int *a, int *b, int *c)


{
*c = *a + *b;
}

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

In this method, the value of In call by reference,


Value Passed the variable is passed to the reference to the variable is
function. passed.

The original value remains


The changes made are
Scope of unchanged even when we
reflected in the original
Changes make changes in the
variable.
function.

It requires extra memory It is more memory and time


Performance and time to copy so less efficient as it does not
efficient. create a copy.
Feature Call by Value Call by Reference

The memory addresses of The actual and the formal


Memory
the actual and formal parameters point at the
Location
parameters are different. same memory address.

Mainly used to pass values


It is used when we want to
for small data or when we
Applications modify the original value or
do not want to change
save resources.
original values.

How can we pass the Whole Array to Functions? Explain with example
program.

Passing an Entire Array to Functions:

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 fun1(int a[]) {


int i, sum = 0;
for(i = 0; i < 5; i++) {
sum = sum + a[i];
}
printf("%d", sum);
}

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:

 The function must be called by passing only the array name.


 In the function definition, the formal parameter is a 2-D array with the size of the second dimension
specified.

Program:

void fun1(int a[][2]) {


int i, j;
for(i = 0; i < 2; i++) {
for(j = 0; j < 2; j++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
}

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.

In C programming, the scope of a variable is classified into two types:

1. Local Variables
2. Global Variables
1. Local Variables:

 Local variables are declared inside a function or block.


 They are accessible only within that function or block.
 Once the function exits, the local variables are destroyed and cannot be accessed outside the
function.

2. Global Variables:

 Global variables are declared outside all functions.


 They are accessible from any function within the same program.
 Since global variables persist throughout the program execution, they retain their values across
function calls.
 The scope of a global variable is also called file scope.

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);

total = a + b; // Using global variable


printf("Total = %d", total);

getch();
}

Sample Output:

Enter a and b value: 5 10


Total = 15

Explanation:

1. total is a global variable, declared outside the main() function.


2. a and b are local variables, declared inside main(), so they are accessible only within main().
3. The sum of a and b is stored in total, which is a global variable.
4. Since total is global, it can be accessed from any function in the program.
Storage Classes:
Storage classes in C are used to determine the lifetime, visibility, memory location, and initial value of a
variable.

There are four types of storage classes in C:

1. Automatic - Keyword used: auto


2. External - Keyword used: extern
3. Register - Keyword used: register
4. Static - Keyword used: static

1. Automatic Storage Class:

 The keyword used for defining automatic variables is auto.


 The visibility and scope of automatic variables is limited to the block in which they are defined.
 The automatic variables are initialized to garbage by default.
 The memory assigned to automatic variables is freed upon exiting from the block.
 Every local variable in C is automatic by default.

#include <stdio.h>
#include <conio.h>

void fun1(); // Function prototype

void main()
{
auto int a = 20; // Automatic variable
clrscr();

fun1(); // Calling function fun1()

printf("\na = %d", a); // Printing value of 'a' in main()

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:

 The keyword used for defining external variables is extern.


 The external storage class is used to tell the compiler that the variable defined as extern is declared
with an external linkage elsewhere in the program.
 The default initial value of an external integral type is 0, otherwise null.
 We can only initialize the extern variable globally; i.e., we cannot initialize the external variable
within any block or method.
 An external variable can be declared multiple times but can be initialized only once.
 If a variable is declared as external, then the compiler searches for that variable to be initialized
somewhere in the program (either as extern or static).
o If it is not found, the compiler will show an error.

#include <stdio.h>
#include <conio.h>
extern int a; // External variable declaration
void main()
{
clrscr();
printf("%d", a); // Print value of external variable
getch();
}

int a = 100; // External variable definition

Sample Output:

100

3. Register Storage Class

 The keyword used for defining register variables is register.


 The variables defined as register are allocated memory in the CPU registers. If no space is available,
they are allocated in primary memory (RAM).
 The access time of register variables is faster than automatic variables.
 The initial default value of register local variables is garbage (random value).
 We can store pointers in register variables, meaning a register can store the address of a variable.

Example: Register Storage Class in C

#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:

Value of register variable a: 10

Static Storage Class

 The keyword used to define a static variable is static.


 The variables defined with the static specifier retain their values between multiple function calls.
 Static local variables are only visible to the function or block in which they are defined.
 A static variable can be declared multiple times, but it can be initialized only once.
 The default initial value of a static integral variable is 0, otherwise null for pointers.
 The visibility of a static global variable is limited to the file in which it has been declared.

Example: Static Storage Class in C

#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

Storage Storage Place Default Scope Lifetime


Classes Value
(Visibility)

auto RAM Garbage Local With in function


Value
extern RAM Zero Global Till the end of the main program
May be declared anywhere in the
program
register CPU Register Garbage Local Within the function
Value

static RAM Zero Local Till the end of the main program,
Retains value between multiple
functions call

Memory Layout of C Programs


The memory layout of a C program refers to how the program’s data is stored in memory during execution.
Understanding this helps in efficient memory management and avoiding issues like segmentation faults
and memory leaks.

1. Text Segment (Code Segment)

 Stores the compiled machine code of the program.


 It contains the program’s instructions and functions.
 This segment is read-only to prevent accidental modification.

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:

A. Initialized Data Segment

 Stores global and static variables that are initialized.


 Example:

int a = 10; // Stored in Initialized Data Segment

static int b = 20; // Stored in Initialized Data Segment

B. Uninitialized Data Segment (BSS Segment)

 Stores global and static variables that are not initialized.


 These variables are automatically initialized to zero at runtime.

Example:

int x; // Stored in BSS

static int y; // Stored in BSS

3. Heap Segment

 Stores dynamically allocated memory using functions like malloc(), calloc(), and realloc().
 The heap grows towards higher memory addresses.
 Example:

int *ptr = (int*) malloc(sizeof(int) * 10); // Stored in Heap

4. Stack Segment

 Stores local variables and function call information.


 A stack frame is created each time a function is called.
 The stack grows downward (opposite to heap growth).
 Example:

void function() {

int local_var = 10; // Stored in Stack

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.

Example: Defining a Pointer to an Integer

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.

Example: Declaring Different Types of Pointers

int *a; // Pointer to an integer

char *c; // Pointer to a character

 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.

Example: Printing Pointer Address and Value

#include <stdio.h>

int main() {

int number = 50;

int *p;

p = &number; // Stores the address of number variable

printf("Address of p variable is %x \n", p);


printf("Value of p variable is %d \n", *p);

return 0;

Output

Address of p variable is fff4

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

1. Dynamic Memory Allocation

 In C, we can dynamically allocate memory using malloc() and calloc() functions, where pointers are
used.

2. Arrays, Functions, and Structures

 Pointers are widely used in arrays, functions, and structures, reducing code size and improving
efficiency.
Understanding Pointers in C

 In C, we use normal variables to store user data values.


 When we declare a variable, the compiler allocates the required memory with a specified name.
 Every variable in C has a name, data type, value, storage class, and address.
 A pointer is a special type of variable used to store the address of another variable with the same
data type.

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.

Accessing the Address of Variables


 In C programming, we use the reference operator (&) to access the address of a variable.
 For example, to access the address of a variable marks, we use &marks.
 We use the following printf statement to display the memory location (address) of the variable
marks:

printf("Address: %u", &marks);

 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.

Declaring Pointers (Creating Pointers)


 In C programming, the declaration of a pointer variable is similar to the creation of a normal
variable, but the pointer's name is prefixed with the * symbol.
 Syntax to declare a pointer variable:

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.

Assigning Addresses to Pointers


 To assign an address to a pointer variable, we use the assignment operator with the following
syntax:
pointerVariableName = &variableName;

For example, consider the following variable declaration:

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.

Accessing Variable Value Using Pointers


 Pointer variables are used to store the address of other variables.
 We can use this address to access the value of the variable through its pointer.
 We use the symbol * in front of the pointer variable name to access the value of the variable to
which the pointer is pointing.
 The general syntax is:

*pointerVariableName

Example Code

#include <stdio.h>
#include <conio.h>

void main() {
int a = 10, *ptr;
clrscr();

ptr = &a; // Assigning address of variable 'a' to pointer 'ptr'

printf("Address of variable a = %u\n", ptr);


printf("Value of variable a = %d\n", *ptr); // Dereferencing pointer to get value
printf("Address of variable ptr = %u\n", &ptr);
}

Initialization of Pointer Variables


 Pointer Initialization is the process of assigning the address of a variable to a pointer variable.
 It contains the address of a variable of the same data type. In C, the address operator (&) is used to
determine the address of a variable.
 The & (immediately preceding a variable name) returns the address of the variable associated with
it.
Example Code: Pointer Initialization

int a = 10;
int *ptr; // Pointer declaration
ptr = &a; // Pointer initialization

 A pointer variable always points to variables of the same data type.

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:

int *ptr = NULL;

Example Code: Pointer Initialization

#include <stdio.h>
#include <conio.h>

void main() {
int a = 10, *ptr;
clrscr();

ptr = &a; // Assign address of 'a' to ptr

printf("Address of variable a = %u\n", ptr);


printf("Value of variable a = %d\n", *ptr);
printf("Address of variable ptr = %u\n", &ptr);
}
Using the Pointer or Dereferencing of Pointer
 Once a pointer has been assigned the address of a variable, to access the value of the variable, the
pointer is dereferenced using the indirection operator or dereferencing operator *.
 Consider the following example for better understanding:

Example Code: Dereferencing a Pointer

#include <stdio.h>

int main() {
int a;
a = 10;
int *p = &a; // Declaring and initializing the pointer

// Print the value of 'a' using dereferencing


printf("%d\n", *p);

// Another way to print the value of 'a'


printf("%d\n", *&a);

// Print the address of 'a'


printf("%u\n", &a);

// Print the address stored in pointer 'p'


printf("%u\n", p);

// Print the address of the pointer 'p'


printf("%u\n", &p);

return 0;
}

Output:

10
10
3795480300
3795480300
3795480304

Pointer Expressions and Pointer Arithmetic


In general, expressions involving pointers conform to the same rules as other expressions. This section
examines a few special aspects of pointer expressions, such as assignments, conversions, and arithmetic.
Pointer Assignments
 You can use a pointer on the right-hand side of an assignment statement to assign its value to
another pointer.
 When both pointers are of the same type, the assignment is straightforward.

Example: Pointer Assignment

int s = 56;
int *ptr1, *ptr2;
ptr1 = &s;
ptr2 = ptr1;

Program: Pointer Assignment


#include <stdio.h>
int main(void) {
int s = 56;
int *ptr1, *ptr2;

ptr1 = &s;
ptr2 = ptr1;

/* Print the value of s twice */


printf("Values at ptr1 and ptr2: %d %d\n", *ptr1, *ptr2);

/* Print the address of s twice */


printf("Addresses pointed to by ptr1 and ptr2: %p %p", ptr1, ptr2);

return 0;
}

Output

Values at ptr1 and ptr2: 56 56


Addresses pointed to by ptr1 and ptr2: 0240FF20 0240FF20

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:

 Addition: ptr1 + ptr2 (Not valid)


 Multiplication: ptr1 * ptr2 (Not valid)
 Division: ptr1 / ptr2 (Not valid)

However, we can subtract one pointer variable from another.

Increment and Decrement Operators with Pointers

We can use the increment (++) and decrement (--) operators with pointers to modify the address contained
in the pointer variable.

Example

ptr1++; // Moves to the next memory location


ptr2--; // Moves to the previous memory location

Pointer Multiplication Example


int x = 10, y = 20, z;
int *ptr1 = &x;
int *ptr2 = &y;
z = *ptr1 * *ptr2; // Will assign 200 to variable z.
Pointer Division Issue
There is a blank space between / and * in expressions like:

z = 5 * -*ptr2 / *ptr1;
This is because the symbol /* is considered as the beginning of a comment, which causes a syntax error.

Valid Pointer Statements


If ptr1 and ptr2 are properly declared and initialized pointers, then the following statements are valid:

y = *ptr1 * *ptr2; // Multiplication of values stored in ptr1 and ptr2


sum = sum + *ptr1; // Adding value stored in ptr1 to sum
*ptr2 = *ptr2 + 10; // Incrementing value at ptr2 by 10
*ptr1 = *ptr1 + *ptr2; // Adding values stored at ptr1 and ptr2
*ptr1 = *ptr2 - *ptr1; // Subtracting values at ptr1 and ptr2
Pointer Arithmetic in C

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.

From the above example:

 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:

P2 - P1; // It gives the number of elements between P1 and P2.

Pointer Increment and Scale Factor

 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++;

 It will increment the address of the pointer variable by 2.


 So, if the address of the pointer variable is 2000, then after increment it becomes 2002.

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

/* Program to compute the sum of all elements stored in an array */


#include <stdio.h>
#include <conio.h>

int main()
{
int a[10], i, sum = 0, *p;

printf("Enter 10 elements:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);

p = a; // Assign pointer to the array

for (i = 0; i < 10; i++)


{
sum = sum + (*p);
p++;
}

printf("The sum is %d", sum);


getch();

return 0;
}
Output:

Enter 10 elements:
1
2
3
4
5
6
7
8
9
10

The sum is 55

Pointer and Arrays


 An array is a block of sequential data. Let's write a program to print the addresses of array
elements.

Example Code: Pointer and Arrays

#include <stdio.h>

int main() {
int x[4];
int i;

for (i = 0; i < 4; ++i) {


printf("&x[%d] = %p\n", i, &x[i]);
}

printf("Address of array x: %p", x);


return 0;
}

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.

Relation Between Arrays and Pointers

 From the above example, it is clear that &x[0] is equivalent to x.


 Similarly, x[0] is equivalent to *x.
 &x[1] is equivalent to x + 1 and x[1] is equivalent to *(x + 1).
 &x[2] is equivalent to x + 2 and x[2] is equivalent to *(x + 2).
 Basically, &x[i] is equivalent to x + i and x[i] is equivalent to *(x + i).

Example 1: Pointers and Arrays

#include <stdio.h>

int main() {
int i, x[6], sum = 0;
printf("Enter 6 numbers: ");

for (i = 0; i < 6; ++i) {


// Equivalent to: scanf("%d", &x[i]);
scanf("%d", x + i); // Using pointer notation

// Equivalent to: sum += x[i];


sum += *(x + i); // Using pointer notation
}

printf("Sum = %d", sum);


return 0;
}

 When you run the program, the output will be:

Enter 6 numbers:
2
3
4
4
12
4
Sum = 29
Pointer to Pointer (Double Pointer)

 As we know, a pointer is used to store the address of a variable in C.


 Pointers reduce the access time of a variable.
 However, in C, we can also define a pointer to store the address of another pointer. Such a pointer
is known as a double pointer (pointer to pointer).
 The first pointer is used to store the address of a variable, whereas the second pointer is used to
store the address of the first pointer.
 Let's understand it by the diagram given below.

Syntax of Declaring a Double Pointer

 The syntax for declaring a double pointer is given below:

int **p; // Pointer to a pointer which is pointing to an integer.

Example of Double Pointer

#include <stdio.h>

void main() {
int a = 10;
int *p;
int **pp;

p = &a; // Pointer p is pointing to the address of a


pp = &p; // Pointer pp is a double pointer pointing to the address of pointer p

printf("Address of a: %x\n", p);


printf("Address of p: %x\n", pp);
printf("Value stored at p: %d\n", *p);
printf("Value stored at pp: %d\n", **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.

Causes of Dangling Pointers

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.

Syntax of Void Pointer

void *pointer_name;

Declaration of Void Pointer

void *ptr;

 In the above declaration, void is the type of the pointer, and ptr is the name of the pointer.

Size of the Void Pointer in C

 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.

Example: Checking the Size of Void Pointer

#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.

Why Do We Use Void Pointers?

 We use void pointers because of their reusability.


 Void pointers can store the object of any type, and we can retrieve the object of any type by using
the indirection operator with proper typecasting.

Example: Using Void Pointers

#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'.

void *ptr; // Declaration of void pointer.

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.

POINTERS AND FUNCTIONS


1) Passing Arguments to Functions using Pointer

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.

Program: Swapping Two Numbers using Pointers

#include <stdio.h>

void swap(int *a, int *b); // Function prototype

int main() {
int p = 10, q = 20;

printf("Before Swapping:\n");
printf("p = %d\n", p);
printf("q = %d\n\n", q);

swap(&p, &q); // Passing address of p and q to the swap function

printf("After Swapping:\n");
printf("p = %d\n", p);
printf("q = %d\n", q);

return 0;
}

// Pointer a and b hold and point to the address of p and q


void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}

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.

Simple Example of Pointer to Function

#include <stdio.h>

int add(int x, int y) {


return x + y;
}

int main() {
int (*functionPtr)(int, int); // Function pointer declaration
int s;

functionPtr = add; // Assigning function address to pointer

s = functionPtr(20, 45); // Calling function using pointer


printf("Sum is %d", 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:

int (*add)(); // Legal declaration of a pointer to function


int *add(); // This is NOT a declaration of a pointer to function

 A function pointer can point to a specific function when it is assigned the name of the function.

int add(int, int);


int (*s)(int, int);
s = add; // s is now a pointer to function add

 Now, the function can be called using s:

s(10, 20);

2) Function Returning a Pointer

A function can also return a pointer to the calling function.

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.

Program: Finding the Larger of Two Numbers

#include <stdio.h>

int *checkLarger(int *, int *); // Function prototype

int main() {
int num1, num2;
int *ptr;

printf("Enter Two numbers: \n");


scanf("%d %d", &num1, &num2);

ptr = checkLarger(&num1, &num2); // Function call


printf("%d is larger\n", *ptr);

return 0;
}

int *checkLarger(int *m, int *n) {


if (*m > *n)
return m;
else
return n;
}

Output:

Enter Two numbers:


546 1213
1213 is larger

You might also like