One of the most important features of C is that it provides low-level memory access with the concept of pointers. A pointer is a variable that stores the address of another variable in the memory.
The provision of pointers has many applications such as passing arrays and struct type to a function and dynamic memory allocation, etc. In this chapter, we will explain some important applications of pointers in C.
Using Pointers to Access Array Elements
Array elements are stored in a continuous memory location. Each subscript of the array is allotted bytes returned by the sizeof() function for the data type.
The pointer to an array is the address of its 0th element. When the array pointer is incremented by 1, it points to the next element in the array.
Example
The following example demonstrates how you can traverse an array with the help of its pointer.
#include <stdio.h>intmain(){int arr[]={1,2,3,4,5};int*ptr = arr;for(int i =0; i <=4; i++){printf("arr[%d]: %d\n", i,*ptr);
ptr++;}return0;}
Output
Run the code and check its output −
arr[0]: 1
arr[1]: 2
arr[2]: 3
arr[3]: 4
arr[4]: 5
Dynamic Memory Allocation
When an array is declared, the compiler allocates to it the required memory. This is a static memory allocation, as it cannot be changed in the runtime. Dynamic memory allocation lets you allocate the required memory during the runtime of a program.
C provides the following dynamic memory allocation functions −
void*calloc(int num,int size);
This function allocates an array of num elements each of which size in bytes will be size.
void*malloc(size_t size);
This function allocates an array of num bytes and leaves them uninitialized.
void*realloc(void*address,int newsize);
This function re−allocates memory extending it up to newsize.
The malloc() Function
This function is defined in the “stdlib.h” header file. It allocates a block memory of the required size and returns a void pointer.
void*malloc(size)
The size parameter refers to the block of memory in bytes. To allocate the memory required for a specified data type, you need to use the typecasting operator. For example, the following snippet allocates the memory required to store an int type.
int*ptr;
ptr =(int*)malloc(sizeof(int));
Here we need to define a pointer to character without defining how much memory is required and later, based on requirement, we can allocate memory.
Example
In this example, we use the malloc() function to allocate the required memory to store a string (instead of declaring a char array of a fixed size) −
#include <stdio.h>#include <stdlib.h>#include <string.h>intmain(){char*name;
name =(char*)malloc(strlen("TutorialsPoint"));strcpy(name,"TutorialsPoint");if(name ==NULL){fprintf(stderr,"Error - unable to allocate required memory\n");}else{printf("Name = %s\n", name );}}
Output
When the above code is compiled and executed, it produces the following output −
Name = TutorialsPoint
The calloc() Function
The C library function “calloc” (stands for contiguous allocation) allocates the requested memory and returns a pointer to it.
void*calloc(n, size);
Where “n” is the number of elements to be allocated and “size” is the byte size of each element.
The following snippet allocates the memory required to store 10 integer types.
int*ptr;
ptr =(int*)calloc(25,sizeof(int));
The realloc() Function
The realloc() function in C is used to dynamically change the memory allocation of a previously allocated memory. You can increase or decrease the size of an allocated memory block by calling the realloc() function.
void*realloc(*ptr, size);
The first parameter “ptr” is the pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated.
Dynamic memory allocation technique is extensively used in complex linear and non−linear data structures such as linked lists and trees, which are employed in operating system software.
Passing Arguments to a Function as a Reference
When a function is called by reference, the address of the actual argument variables passed, instead of their values.
Passing a pointer to a function has two advantages −
First, it overcomes the limitation of pass by value. Changes to the value inside the called function are done directly at the address stored in the pointer. Hence, we can manipulate the variables in one scope from another.
Second, it also overcomes the limitation of a function in that it can return only one expression. By passing pointers, the effect of processing a function takes place directly at the address. Secondly, more than one value can be returned if we return the pointer of an array or struct variable.
The following function receives the reference of two variables whose values are to be swapped.
/* function definition to swap the values */intswap(int*x,int*y){int z;
z =*x;/* save the value at address x */*x =*y;/* put y into x */*y = z;/* put z into y */return0;}
Example
The main() function has two variables “a” and “b”, their addresses are passed as arguments to the swap() function.
#include <stdio.h>intswap(int*x,int*y);intmain(){/* local variable definition */int a =10;int b =20;printf("Before swap, value of a : %d\n", a);printf("Before swap, value of b : %d\n", b);/* calling a function to swap the values */swap(&a,&b);printf("After swap, value of a: %d\n", a);printf("After swap, value of b: %d\n", b);return0;}
Output
When executed, it will produce the following output −
Before swap, value of a: 10
Before swap, value of b: 20
After swap, value of a: 20
After swap, value of b: 10
In this program, we have been able to swap the values of two variables out of the scope of a function to which they have been passed, and we could overcome the limitation of the function’s ability to pas only one expression.
Passing an Array to a Function
Let us use these characteristics for passing the array by reference. In the main() function, we declare an array and pass its address to the max() function.
The max() function traverses the array using the pointer and returns the largest number in the array, back to the main() function.
Example
Take a look at the following example −
#include <stdio.h>intmax(int*arr,int length);intmain(){int arr[]={10,34,21,78,5};int length =sizeof(arr)/sizeof(int);int maxnum =max(arr, length);printf("max: %d", maxnum);}intmax(int*arr,int length){int max =*arr;for(int i =0; i < length; i++){printf("arr[%d]: %d\n", i,(*arr));if((*arr)>max)
max =(*arr);
arr++;}return max;}
Output
Run the code and check its output −
arr[0]: 10
arr[1]: 34
arr[2]: 21
arr[3]: 78
arr[4]: 5
max: 78
The max() function receives the address of the array from the main() function in the pointer “arr”. Each time, when it is incremented, it points to the next element in the original array.
Leave a Reply