Advantages of pointer:
datatype *pointer_name;
int *p;
float *f;
char *c;
&variable_name;
datatype *pointer_name = address;
datatype *pointer_name;
pointer_name = address;
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 0;
int *x = &a;
int *y = &b;
int *z = &c;
*z = *x + *y;
printf("The sum is %d", *z);
return 0;
}
#include <stdio.h>
int main()
{
int var = 10, *ptr;
ptr = &var;
printf("Value at ptr = %p\n", ptr); // prints 0x7ff7bec385a8
printf("Value at var = %d\n", var); // prints 10
printf("Value at *ptr = %d\n", *ptr); // prints 10
printf("Value at *(&var) = %d\n", *(&var)); // prints 10
printf("Value at &ptr = %p\n", &ptr); // prints address of ptr variable - 0x7ff7b1dc55a0
return 0;
}
/*
%p is used for printing address in Hexa decimal form
%u is unsigned form
*/
#include <stdio.h>
int main()
{
int a = 5, *p1;
float b = 2.5, *p2;
char c = 'a', *p3;
p1 = &a;
p2 = &b;
p3 = &c;
printf("%d", sizeof(p1)); // 8
printf("%d", sizeof(p2)); // 8
printf("%d", sizeof(p3)); // 8 - in my system pointer size is 8 bytes
return 0;
}
#include<stdio.h>
int main()
{
int var = 10;
int *ptr;
int *q;
ptr = &var;
// *q = *ptr; // this is invalid
// because (q) is not initialized with any address so we cannot dereference it.
return 0;
}
#include <stdio.h>
int main()
{
int var = 10, var2 = 20;
int *ptr;
int *q;
ptr = &var;
q = &var2;
*q = *ptr; // now this is valid
printf("%d", *q);
return 0;
}
#include<stdio.h>
int main()
{
// int *p = &a, a =10; // this statement is wrong because "a" have to be declared first.
int a = 10, *p, **q;
p = &a;
q = &p;
printf("%d", a); // 10
printf("%d", *p); // 10
printf("%d", **q); // 10
return 0;
}
To declare a pointer to a function in C, you use the following syntax:
return_type (*pointer_name)(argument_list);
For example, here's a declaration of a function pointer that takes two integers and returns an integer ↓
int (*add)(int, int);
To assign a function to a function pointer, you simply assign the address of the function to the pointer variable ↓
int sum(int a, int b)
{
return a + b;
}
add = ∑
To call the function through the pointer, you can use the following syntax ↓
int result = (*add)(3, 4);
Alternatively, you can use the shorthand notation ↓
int result = add(3, 4);
Here's a complete example program that demonstrates the use of function pointers in C ↓
#include <stdio.h>
int sum(int a, int b) {
return a + b;
}
int product(int a, int b) {
return a * b;
}
int main() {
int (*func_ptr)(int, int);
func_ptr = ∑
printf("sum(3, 4) = %d\n", (*func_ptr)(3, 4));
func_ptr = &product;
printf("product(3, 4) = %d\n", (*func_ptr)(3, 4));
return 0;
}
int *ptr;
// let's say address of "ptr" is 1000
ptr = ptr + 1;
// let's say integer takes 4 bytes then
ptr + 1 will be 1004
// now same with increment
p++ means 1004 + 4 = 1008
Program to show pointer arithmetic ↓
#include <stdio.h>
int main()
{
int a = 5, *pi = &a;
char b = 'x', *pc = &b;
float c = 5.5, *pf = &c;
printf("Value of pi = %d Address of a = %lu\n", *pi, (unsigned long)pi);
printf("Value of pc = %c Address of b = %lu\n", *pc, (unsigned long)pc);
printf("Value of pf = %.1f Address of c = %lu\n", *pf, (unsigned long)pf);
// Incrementing pointers using pointer arithmetic
pi++;
pc++;
pf++;
printf("After incrementing:\n");
printf("Modified address of a = %lu\n", (unsigned long)pi);
printf("Modified address of b = %lu\n", (unsigned long)pc);
printf("Modified address of c = %lu\n", (unsigned long)pf);
// Decrementing pointers using pointer arithmetic
pi--;
pc--;
pf--;
printf("After decrementing:\n");
printf("Modified address of a = %lu\n", (unsigned long)pi);
printf("Modified address of b = %lu\n", (unsigned long)pc);
printf("Modified address of c = %lu\n", (unsigned long)pf);
// Adding a constant value to pointers
pi += 2;
pc += 2;
pf += 2;
printf("After adding 2:\n");
printf("Modified address of a = %lu\n", (unsigned long)pi);
printf("Modified address of b = %lu\n", (unsigned long)pc);
printf("Modified address of c = %lu\n", (unsigned long)pf);
// Subtracting a constant value from pointers
pi -= 2;
pc -= 2;
pf -= 2;
printf("After subtracting 2:\n");
printf("Modified address of a = %lu\n", (unsigned long)pi);
printf("Modified address of b = %lu\n", (unsigned long)pc);
printf("Modified address of c = %lu\n", (unsigned long)pf);
return 0;
}
Output ↓
Value of pi = 5 Address of a = 140701867095480
Value of pc = x Address of b = 140701867095471
Value of pf = 5.5 Address of c = 140701867095452
After incrementing:
Modified address of a = 140701867095484
Modified address of b = 140701867095472
Modified address of c = 140701867095456
After decrementing:
Modified address of a = 140701867095480
Modified address of b = 140701867095471
Modified address of c = 140701867095452
After adding 2:
Modified address of a = 140701867095488
Modified address of b = 140701867095473
Modified address of c = 140701867095460
After subtracting 2:
Modified address of a = 140701867095480
Modified address of b = 140701867095471
Modified address of c = 140701867095452
x = *ptr++;
x = *ptr;
ptr = ptr + 1;
x = *++ptr;
*ptr = *ptr + 1;
x = *ptr;
x = ++*ptr
*ptr = *ptr + 1;
x = *ptr;
x = (*ptr)++
x = *ptr;
*ptr = *ptr + 1;
Let us take an example and understad how these expressions are interpreted.
Following program shows that the elements of an array are stored in consecutive memory locations.
#include <stdio.h>
int main()
{
int arr[5] = {5, 10, 15, 20, 25};
int i;
for (i = 0; i < 5; i++)
{
printf("Value of arr[%d] = %d\t", i, arr[i]);
printf("Address of arr[%d] = %u\n", i, &arr[i]);
}
return 0;
}
Output ↓
Value of arr[0] = 5 Address of arr[0] = 2000
Value of arr[1] = 10 Address of arr[1] = 2002
Value of arr[2] = 15 Address of arr[2] = 2004
Value of arr[3] = 20 Address of arr[3] = 2006
Value of arr[4] = 25 Address of arr[4] = 2008
arr -> Points to 0th element -> &arr[0] -> 2000
arr+1 -> Points to 1st element -> &arr[1] -> 2002 (assuming 'int' take 2 bytes)
arr+2 -> Points t0 2nd element -> &arr[2] -> 2004
arr+3 -> Points to 3rd element -> &arr[3] -> 2006
arr+4 -> Points to 4th element -> &arr[4] -> 2008
*arr -> Value of 0th element -> arr[0] -> 5
*(arr+1) -> Value of 1st element -> arr[1] -> 10
*(arr+2) -> Value of 2nd element -> arr[2] -> 15
*(arr+3) -> Value of 3rd element -> arr[3] -> 20
*(arr+4) -> Value of 4th element -> arr[4] -> 25
Program to print the value and address of elements of an array using pointer notation
#include <stdio.h>
int main()
{
int arr[5] = {5, 10, 15, 20, 25};
int i;
for (i = 0; i < 5; i++)
{
printf("Value of arr[%d] = %d\t", i, *(arr + i));
printf("Address of arr[%d] = %u\n", i, arr + i);
}
return 0;
}
Output ↓
Value of arr[0] = 5 Address of arr[0] = 2000
Value of arr[1] = 10 Address of arr[1] = 2002
Value of arr[2] = 15 Address of arr[2] = 2004
Value of arr[3] = 20 Address of arr[3] = 2006
Value of arr[4] = 25 Address of arr[4] = 2008
Example code ↓
#include <stdio.h>
int main()
{
int *ptr = NULL; // null pointer
printf("The value inside variable ptr is:%d",ptr);
return 0;
}
Output ↓
The value inside variable ptr is:0
Example code ↓
#include <stdio.h>
int main()
{
char a = 'a';
void *p; // void pointer
p = &a;
printf("The size of pointer is:%d", sizeof(p)); // size of p depends on compiler
return 0;
}
Output ↓
The size of pointer is:8
#include <stdio.h>
int main()
{
int a = 10;
void *ptr = &a;
printf("*ptr = %d", *(int *)ptr);
return 0;
}
Example code ↓
#include <stdio.h>
int main()
{
int *p; // wild pointer
printf("%d", *p);
return 0;
}
Output ↓
Segment fault
1. De-allocation of memory
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *ptr = (int *)malloc(sizeof(int));
// after free call, ptr becomes a dangling pointer
free(ptr);
ptr = NULL; // no more dangling pointer
return 0;
}
2. Function call
#include<stdio.h>
int * fun() // function returns address
{
// x is local variable and goes out of scope after an execution of fun() is over.
int x = 5;
return &x;
}
int main()
{
int *p = fun();
// p points to something which is not valid anymore
printf("%d", *p);
return 0;
}
3. Variable goes out of scope
void main()
{
int *ptr;
...
...
{
int ch;
ptr = &ch;
}
...
// here ptr is dangling pointer.
}
Example ↓
char near * str;
int near * a;
Example ↓
int far * ptr;
Example ↓
char huge * ptr;
An example of a 'swap' function to demonstrate pass by value ↓
#include <stdio.h>
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int a = 50;
int b = 100;
printf("\nBefore Swap : \n a = %d \n b = %d", a, b);
swap(a, b);
printf("\n\nAfter Swap : \n a = %d \n b = %d\n", a, b);
return 0;
}
output ↓
Before Swap :
a = 50
b = 100
After Swap :
a = 50
b = 100
Swap function using pass by reference ↓
#include <stdio.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int main()
{
int a = 50;
int b = 100;
printf("\nBefore Swap : \n a = %d \n b = %d", a, b);
swap(&a, &b);
printf("\n\nAfter Swap : \n a = %d \n b = %d\n", a, b);
return 0;
}
Output ↓
Before Swap :
a = 50
b = 100
After Swap :
a = 100
b = 50
Program to sort an array using pointer ↓
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void sort(int *arr, int n) {
for (int i = 0; i < n-1; i++) {
for (int j = i+1; j < n; j++) {
if (*(arr+j) < *(arr+i)) {
swap(arr+i, arr+j);
}
}
}
}
void printArray(int *arr, int n) {
for (int i = 0; i < n; i++) {
printf("%d ", *(arr+i));
}
printf("\n");
}
int main() {
int arr[] = {5, 3, 7, 1, 8};
int n = sizeof(arr) / sizeof(int);
printf("Original array: ");
printArray(arr, n);
sort(arr, n);
printf("Sorted array: ");
printArray(arr, n);
return 0;
}