Home > Software design >  why trying to deference void pointer does not work?
why trying to deference void pointer does not work?

Time:10-21

int main()
{
    int b = 12;
    void *ptr = &b;
    printf("%d", *ptr);
    return 0;
}

I expected for this code to print 12, but it does not. if instead of void pointer, we define int pointer it would work. I wanted to know how can we use void pointer and print the address allocated to it and the amount saved in it?

CodePudding user response:

Dereferencing a void * doesn't make sense because it has no way of knowing the type of the memory it points to.

You would need to cast to pointer to a int * and then dereference it.

printf("%d", *((int *)ptr));

CodePudding user response:

void pointers cannot be dereferenced.it will give this warning

Compiler Error: 'void' is not a pointer-to-object type*

so, you have to do it like this.

#include<stdio.h>
int main()
{
    int b = 12;
    void *ptr = &b;
    printf("%d", *(int *)ptr);
    return 0;
}

CodePudding user response:

A schoolbook example of when void pointers are useful is qsort.

This is the signature:

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) 

base is just a pointer to the first element. The reason it's a void pointer is because qsort can be used for any list, regardless of type. nitems is number of items (doh) in the list, and size is the size of each element. Nothing strange so far.

But it does also take a fourth argument, which is a function pointer. You're supposed to write a custom compare function and pass a pointer to this function. This is what makes qsort able to sort any list. But since it's supposed to be generic, it takes two void pointers as argument. Here is an example of such a compare function, which is a bit bloated for clarity:

int cmpfloat(const void *a, const void *b) {
    const float *aa = (float*) a;
    const float *bb = (float*) b;

    if(*aa == *bb) {
        return 0;
    } else if(*aa > *bb)  {
        return 1;
    } else {
        return -1;
    }
}

Pretty clear what is going on. It returns positive number if a>b, zero if they are equal and negative if b>a, which is the requirements. In reality, I'd just write it like this:

int cmpfloat(const void *a, const void *b) {
    return (*(float*)a - *(float*)b));
}

What you do with this is something like:

float arr[5] = {5.1, 3.4, 8.9, 3.4, 1.3};
qsort(arr, 5, sizeof *arr, cmpfloat);

Maybe it's not completely accurate to say that void pointers are used instead of templates, generic functions, overloaded functions and such, but they have the similarities.

CodePudding user response:

If p has type void *, then the expression *p has type void, which means "no value". You can't pass a void expression to printf for the %d conversion specifier (or any other conversion specifier).

In order to dereference a void *, you must first convert it to a pointer of the appropriate type. You can do it with a cast:

printf( "%d\n", *(int *) ptr );

or assign it to a pointer of the appropriate type:

int *p = ptr;
printf( "%d\n", *p );

The rules around void pointers are special such that they can be assigned to other pointer types without an explicit cast - this allows them to be used as a "generic" pointer type. However, you cannot directly examine the thing a void pointer points to.

  • Related