This blog is under construction

Friday, 1 November 2013

Void pointers

Generic Pointers

What is generic pointer/void pointer?

Pointer variable of type void is called generic pointer.  It is also called as void pointer. We cannot directly dereference generic pointers.  To dereference a generic pointer, first we need to type cast it to some other pointer type.

How to declare void pointer?
Below is the template for void pointer declaration.
     void * <variable_name>;

What is the use of void pointers?
Void pointers are used to store and retrieve data of any type.  Usually, we will get warning when we do assignment between pointers of different types.  For example, given an integer pointer "iPtr" and float pointer "fPtr", we are not allowed to do assignment between "iPtr" and "fPtr".  Whereas, void pointer can be assigned to any pointer type and any pointer can be assigned to a generic pointer.

Below program explains what happens when we do assignment between pointers of different types.


  #include <stdio.h>
  int main() {
        int num = 100;
        float *fPtr;
        /* assigning address of an int variable to float pointer */
        fPtr = &num;
        printf("Value of *fPtr is %f\n", *fPtr);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ gcc -Werror ptr.c 
  cc1: warnings being treated as errors
  ptr.c: In function ‘main’:
  ptr.c:6: error: assignment from incompatible pointer type



Below program shows what happens when we assign other pointer types to void pointer and vice versa.


  #include <stdio.h>
  int main() {
        int num = 100;
        void *vPtr;
        /* assigning address of an int variable to void pointer */
        vPtr = &num;
        /* type casted void pointer for dereferencing */
        printf("Value of *vPtr is %d\n", *((int *)vPtr));
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ gcc -Werror voidPtr.c 
  jp@jp-VirtualBox:~/$ ./a.out
  Value of *vPtr is 100



What is the size of void pointers?
Usually, address of any variable is an integer.  Pointer holds the address of a variable.  So, the size of void pointer is 4 bytes.  And it can be calculated using sizeof operator.


  #include <stdio.h>
  int main() {
        char ch = 'z';
        void *ptr = &ch;
        printf("Size of void pointer(ptr): %d\n", sizeof(ptr));
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Size of void pointer(ptr): 4



How to typecast void pointers?
To typecast a void pointer to some other pointer, we need to prefix pointer type in parenthesis as shown.

     int num = 100, *iPtr;
     void *vPtr;
     vPtr = &num;
     iPtr = (int *)vPtr;

Here, we have typecasted void pointer to integer pointer.


How to print void pointer value in C?
We need to type cast the void pointer before accessing the values referred by void pointer.  Below example shows how to print values referenced by void pointer.


  #include <stdio.h>
  int main() {
        int i, arr[5] = {10, 20, 30, 40, 50};
        void *vPtr;

        /* assigning address of arr[0] to void pointer vPtr */
        vPtr = &arr[0];

        printf("Output:\n");

        /* 
         * type casted void pointer to integer pointer inorder
         * to access value referenced by void pointer
         */
        for (i = 0; i < 5; i++) {
                printf("arr[%d]: %d\n", i, *(((int *)vPtr) + i));
        }
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Output:
  arr[0]: 10
  arr[1]: 20
  arr[2]: 30
  arr[3]: 40
  arr[4]: 50



How to compare void pointers?
memcmp() is the best option to compare values referenced by void pointers.  Below program checks whether the value referenced by given two void pointers are same.

Note:
memcmp() - compares given memory area


  #include <stdio.h>

  /*
   * compares value referenced by given two void pointers
   * and prints whether the contents/values are same or not
   */
  void compare(void *vPtr1, void *vPtr2, int sz) {
        int ret;
        ret = memcmp(vPtr1, vPtr2, sz);

        if (!ret) {
                printf("Contents are same\n");
        } else {
                printf("Contents are different\n");
        }
        return;
  }

  int main() {
        /* variable declarations */
        int num1 = 10, num2 = 20;
        float f1 = 10.23, f2 = 10.23;
        char ch1 = 'a', ch2 = 'c';

        /* comparing the values */
        printf("Comparing %d and %d => ", num1, num2);
        compare(&num1, &num2, sizeof(int));

        printf("Comparing %.2f and %.2f => ", f1, f2);
        compare(&f1, &f2, sizeof(float));

        printf("Comparing %c and %c => ", ch1, ch2);
        compare(&ch1, &ch2, sizeof(char));

        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Comparing 10 and 20 => Contents are different
  Comparing 10.23 and 10.23 => Contents are same
  Comparing a and c => Contents are different



How to dereference void pointers in c?
Void pointers cannot be deferenced until they are typecasted to some other pointer type. So, we need to type cast void pointer to some other type to access the value referenced by it(void pointer).

     int num1 = 10, num2;
     void *ptr = &num1;
     num2 = *((int *)num1);  // type casting void pointer to integer pointer type

Here, we have done type casting to access the value referenced by void pointer.


How to swap contents referenced by of given two void pointers?

memcpy() is the best option to swap the contents referenced by given two void pointers. Below program explains swapping two void pointer contents.



  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  /* swaps the contents referenced by given two void pointers */
  void swap(void *vPtr1, void *vPtr2, int sz) {
        int ret;
        void *tmp;

        /* dynamic memory allocation */
        tmp = (char *)malloc(sizeof(char) * sz);

        /* swapping the contents referenced by void pointers */
        memcpy(tmp, vPtr1, sz);
        memcpy(vPtr1, vPtr2, sz);
        memcpy(vPtr2, tmp, sz);
        return;
  }

  int main() {
        /* variable declarations */
        int num1 = 10, num2 = 20;
        float f1 = 11.23, f2 = 10.23;
        char ch1 = 'a', ch2 = 'c';

        printf("Values before swapping:\n");
        printf("num1: %-5d\tnum2 : %d\n", num1, num2);
        printf("f1  : %-5.2f\tf2   : %.2f\n", f1, f2);
        printf("ch1 : %-5c\tch2  : %c\n", ch1, ch2);

        /* swapping the contents */
        swap(&num1, &num2, sizeof(int));
        swap(&f1, &f2, sizeof(float));
        swap(&ch1, &ch2, sizeof(char));

        /* printing the result */
        printf("\nValues after swapping:\n");
        printf("num1: %-5d\tnum2 : %d\n", num1, num2);
        printf("f1  : %-5.2f\tf2   : %.2f\n", f1, f2);
        printf("ch1 : %-5c\tch2  : %c\n", ch1, ch2);
        return 0;
  }




  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Values before swapping:
  num1: 10   num2 : 20
  f1  : 11.23 f2   : 10.23
  ch1 : a        ch2  : c

  Values after swapping:
  num1: 20   num2 : 10
  f1  : 10.23 f2   : 11.23
  ch1 : c       ch2  : a


No comments:

Post a Comment