NULL and Void Pointers

The indirection operator, represented by an *, returns the value pointed to by a pointer variable; we call this action dereferencing a pointer.

#include <stdio.h>


int main(void){
    
    int number = 47;
    
    int *p = &number;
    
    printf("%d\n", *p);
    
    *p = 73;
    
    //displays 73
    printf("%d\n", number);
    
    return 0;
}

The NULL pointer constant is a pointer that does not point to anything; this means that it does not point to an area of memory. NULL is defined as (void *)0. 

#include <stdio.h>


int main(void){
    
    int *p = NULL;
    int  *p2 = (void *)0;
    //displays (nil)
    printf("%p\n", p);
    
    //displays (nil)
    printf("%p\n", p2);
    
    return 0;
}

Note that NULL should not be used in contexts other than pointers.

A pointer to void can be used to hold references to any data type.The void keyword here is meant to indicate an absence of type. We can think of a void pointer as a sort of general purpose pointer.

#include <stdio.h>


int main(void){
    double dare = 1.61803;
    char letter = 's';
    
    //declare and initialize
    //void pointer
    void *ptr = &dare;
    ptr = &letter;
    
    return 0;
    
}

We cannot directly dereference a void pointer. We must instead cast it to a pointer with a specific type; for instance, int *, double*, char*, etc. Casting, as we know, is a way to tell the machine to treat a value of one type as if it were another type.

#include <stdio.h>


int main(void){
    int i = 73;
    double decker = 3.14159;
    void *ptr = &i;
    
    printf("%d\n", *((int*)ptr));
    
    
    ptr = &decker;
    
    printf("%f\n", *((double*)ptr));
    return 0;
    
}

 

Note that we cannot perform pointer arithmetic on void pointers.

#include <stdio.h>


int main(void){
    
    double trouble = 0.57721;
    double *dPtr = &trouble;
    double *dPtr2;
    
    int number = 8088;
    int *iPtr = &number;
    int *iPtr2;
    
    //don't use ampersand
    void *ptr = dPtr;
    
    dPtr2 = (double *)ptr;
    
    printf("*dPtr2 = %f\n", *dPtr2);
    
    //don't use ampersand
    ptr = iPtr;
    
    iPtr2 = (int*)ptr;
    
    
    printf("*iPtr2 = %d\n", *iPtr2);
    
    return 0;
}