In this article, we will learn what is void pointer in C and how we can use void pointer in our C code. If you are new in c programming, you should read this article “C pointer concept“. In the C language pointer is used to store the address of any variable or function but we need to remember that types of the pointer should be the same as the types of the pointed object (variable, pointer, array, function …etc.).
For example, if you want to store the address of the character, the pointer should be a pointer to the character.
char cData; char *pcData = NULL; pcData = &cData;
To resolve the above problem, C language introduces a generic type of pointer (void pointer) that can store the address of any type.
What is void pointer in C?
A void pointer in c is called a generic pointer, it has no associated data type. It can store the address of any type of object and it can be type-casted to any type. According to C standard, the pointer to void shall have the same representation and alignment requirements as a pointer to a character type. A void pointer declaration is similar to the normal pointer, but the difference is that instead of data types we use the void keyword.
Syntax:
void * Pointer_Name;
Example,
void *pvHandle;
What is the size of a void pointer in C?
The size of a void pointer is similar to the size of the character pointer. According to C standard, the pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
The size of the pointers depending on the platform and it can be 2bytes, 4bytes or 8bytes …etc.
Let’s see some example code.
#include <stdio.h> int main(int argc, char *argv[]) { void *pvData = NULL; //void pointer int *iData = NULL;// integer pointer char *cData = NULL;//character pointer float *fData = NULL;//float pointer //size of void pointer printf("size of void pointer = %d\n\n",sizeof(pvData)); //size of void pointer printf("size of integer pointer = %d\n\n",sizeof(iData)); //size of void pointer printf("size of character pointer = %d\n\n",sizeof(cData)); //size of void pointer printf("size of float pointer = %d\n\n",sizeof(fData)); return 0; }
Output: On a 32-bit machine
size of void pointer = 4 size of integer pointer = 4 size of character pointer = 4 size of float pointer = 4
Dereferencing a void pointer in C
Using the indirection operator (*) we can get back the value which is pointed by the pointer, but in case of void pointer we cannot use the indirection operator directly. This is because a void pointer has no data type that creates a problem for the compiler to predict the size of the pointed object. So before dereferencing the void * we have to typecast it, it enables the compiler to predict the data types.
Let’s see some example code.
#include <stdio.h> int main(int argc, char *argv[]) { void *pvData; int iData = 10; pvData = &iData; printf("*pvData = %d",*pvData); return 0; }
Explanation: When we compile the above code, we will get the compiler error because in the above code I tried to dereference the void pointer without type casing.
But what happened if we type-cast the void pointer, its working fine see the below example code.
#include <stdio.h> int main(int argc, char *argv[]) { void *pvData; int iData = 10; pvData = &iData; printf("iData = %d",*(int*)pvData); return 0; }
Output: 10
In the above code void pointer, pvData is pointing to the address of iData (integer variable). So to access the value of integer variable (iData) through the void pointer we have to typecast void pointer through the integer pointer.
(int *)pvData;
Now above expression behave like an integer pointer. You already know how to dereference an integer pointer using an indirection operator (*).
*(int *)pvData
Now you will get the value of the integer which addresses pointed by the void pointer.
Why are void pointers use?
A very important feature of the void pointer is reusability. Using the void pointer we can store the address of any object and whenever required we can get back the object through the indirection operator with proper casting.
Let’s take an example,
#include <stdio.h> int main(int argc, char *argv[]) { void *pvData; int iData = 10; char cData = 'A'; float fData = 27.6; //Assigning address of character pvData = &cData; //dereferencing void pointer with character typecasting printf("cData = %c\n\n",*((char*)pvData)); //Assigning address of integer pvData = &iData; //dereferencing void pointer with integer typecasting printf("iData = %d\n\n",*((int *)pvData)); //Assigning address of float pvData = &fData; //dereferencing void pointer with float typecasting printf("fData = %f\n\n",*((float *)pvData)); return 0; }
Output:
cData = A iData = 10 fData = 27.600000
Explanation: In the above code, pvData is a void pointer. Using it I am storing the address of the different variables (float, int, and char) and after that getting back their values using the indirection operator and proper typecasting.
You can see in the example code, how a single pointer is dealing with different types of variables. This is a very interesting feature of the void pointer that makes the programmer helpless to use the void pointer.
If you want to learn more about the c language, here 10 Free days (up to 200 minutes) C video course for you.
Arithmetic operation on void pointers
Here I want to mention an important point about the arithmetic operation on a void pointer. If you will directly perform an arithmetic operation on the void pointer you may get unexpected results. So you should perform proper typecasting on the void pointer before performing the arithmetic operation.
#include<stdio.h> int main() { //integer array int aiData[3] = {100, 200,300}; //assigned first element address to the void pointer void *pvData = &aiData[0]; printf(" pvData = %lu\n", pvData); printf(" pvData+1 = %lu\n", pvData +1); //Incorrect return 0; }
When you will run the above code you will get the unexpected result.
Since the array (aiData) is the collection of integer element so the type of &aiData[0] would be a pointer to int (int*). So we have to typecast the void pointer pvData from the pointer to int (int*) before performing an arithmetic operation.
#include<stdio.h> int main() { //integer array int aiData[3] = {100, 200,300}; //assigned first element address to the void pointer void *pvData = &aiData[0]; printf(" pvData = %lu\n", pvData); printf(" pvData+1 = %lu\n", (int*)pvData +1); //Correct return 0; }
Output:
You can see, showing the correct value. In my case, the integer size is 4 byte.
Application of void pointer in C
Application of void pointers are very wide, we can not cover all the application in one article. Here I am taking one of the most popular applications of the void pointer in qsort function.
A qsort is a C standard library function that is used to sort arrays. Using the qsort function, we can sort the array of integer, double, long, etc.
Following is the declaration for qsort() function,
void qsort(void *arr, size_t elements, size_t size, int (*comp)(const void *, const void*));
Parameters of qsort:
arr − pointer to the first element of the array.
elements − number of elements in the array.
size − size(in bytes) of the element in the array.
comp − compare function that is used to compares two elements.
int comp(const void* a, const void* b);
Let see an example code to understand the working of qsort and importance of void pointer:
In this example code, I am showing how is the qsort function sort any type of array with the help of compare function.
#include <stdio.h> #define ELEMENT_SIZE(x) sizeof(x[0]) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) //compare function for intger array int compareInt(const void *a, const void *b) { int x = *(const int *)a; int y = *(const int *)b; if (x < y) return -1; //-1 for ascending, 1 for descending order. else if (x > y) return 1; //1 for ascending, -1 for descending order. return 0; } //compare function for float array int compareFloat(const void *a, const void *b) { float x = *(const float *)a; float y = *(const float *)b; if (x < y) return -1; //-1 for ascending, 1 for descending order. else if (x > y) return 1; //1 for ascending, -1 for descending order. return 0; } int main(int argc, char *argv[]) { //Integer array int iData[] = { 40, 10, 100, 90, 20, 25 }; //float array float fData[] = {1.2,5.7,78,98.5,45.67,81.76}; //array index int index = 0; //sorting integer array qsort(iData,ARRAY_SIZE(iData),ELEMENT_SIZE(iData),compareInt); for (index=0; index<ARRAY_SIZE(iData); index++) { printf ("%d ",iData[index]); } printf("\n\n"); //sortig float array qsort(fData,ARRAY_SIZE(fData),ELEMENT_SIZE(fData),compareFloat); for (index=0; index<ARRAY_SIZE(fData); index++) { printf ("%f ",fData[index]); } return 0; }
Output:
10 20 25 40 90 100 1.200000 5.700000 45.669998 78.000000 81.760002 98.500000
Disadvantages of the void pointer in C
- Like the other pointers, we cannot dereference the void pointers because the compiler does not have any information about the pointed object. If we try to compile the below code then we will get the compiler error.
#include<stdio.h> int main() { int iData = 100; void *piData = &iData; printf("%d", *piData); return 0; }
But with proper typecasting, we can dereference the void pointer and get back the value of the pointed address.
#include<stdio.h> int main() { int iData = 1000; void *piData = NULL; piData = &iData; printf("%d", (*(int*)piData)); return 0; }
- According to c standard arithmetic operation on void pointers is illegal that means the C standard doesn’t allow pointer arithmetic with void pointers. However, In GNU C, addition and subtraction operations are supported on void pointers to assuming the size of the void is 1.
#include<stdio.h> int main() { int aiData[3] = {100, 200,300}; void *pvData = &aiData[1]; //address of 200 pvData += sizeof(int); printf("%d", *(int *)pvData); return 0; }
Output: 300 or compiler error.
Explanation: When we compile the code then some compiler throw the compiler error but some compiler compiled the code and print 300 as output to assume the size of the void 1.
Note: Don’t perform the arithmetic operation on the void pointer. As per the C standard sizeof is not applicable on void but in GNU C we can calculate the size of the void and sizeof operator return 1.
Advantages of the void pointer in c
- Using the void pointer we can create a generic function that can take arguments of any data type. The memcpy and memmove library function are the best examples of the generic function, using these function we can copy the data from the source to destination.
Below code shows the implementation of memcpy in C
int Memcpy(void* dst, const void* src, unsigned int cnt) { uint8_t *pszDest = (uint8_t *)dst; const uint8_t *pszSource =( const uint8_t*)src; while(cnt) { *(pszDest++)= *(pszSource++); cnt--; } return 0; }
Using the memcpy we can copy the string, as well as the array of integers, see the below example codes.
#include<stdio.h> int main() { char *pszMessage = "Welcome to aticleworld!";//Source String char aszDisplayMessage[32]= {0}; //Destination string short siLenString=0; // siLenString = strlen(pszMessage)+1; // length of source string Memcpy(aszDisplayMessage, pszMessage,siLenString );//copy source to destination printf("Message = %s\n", aszDisplayMessage); return 0; }
#include<stdio.h> int main(void) { int iLoop = 0; int aiSrc [5] = {100,200,300,400,500};//integer array int aiDst[5]= {0}; //Destination array Memcpy(aiDst, aiSrc,sizeof(aiSrc));//copy integer array for(iLoop =0; iLoop <5 ; iLoop++) //print { printf("%d ",aiDst[iLoop]); } return 0; }
You can see how memcpy is working here as a generic copy function with the help of a void pointer.
- We know that void pointer can be converted to another data type that is the reason malloc, calloc or realloc library function return void *. Due to the void * these functions are used to allocate memory to any data type.
- Using the void * we can create a generic linked list. For more information see this link: How to create generic Link List.
You want to learn more about C Pointers, you can check the below articles.
- A brief description of the pointer in C.
- Dangling, Void, Null and Wild Pointers
- Function pointer in c, a detailed guide
- How to use the structure of function pointer in c language?
- Function pointer in structure.
- Pointer Arithmetic in C.
- 10 questions about dynamic memory allocation.
- Memory Layout in C.
- 100 C interview Questions
- File handling in C.
- C format specifiers.