-1

I am trying to learn about void pointers and functions that have a typedef (in C). I can't seem to grasp the concept.

I have this simple code:

#include <stdio.h>

typedef int (*CompareFunc)(void*, void*);

int compareints(void *a, void *b)
{
    return a-b;
}

int comparedbls(void *a, void *b)
{
    return a-b;
}

int main()
{
    int a = 1, b = 1;

    int* ptrA = &a;
    int* ptrB = &b;

    CompareFunc test = compareints;
    printf("%d\n", test(ptrA, ptrB));


    return 0;
}

The output here is "-4". I don't understand why. I know it's some kind of casting that I'm not doing because I feel like I am subtracting addresses. I would print the values of void *a and void *b with printf("%d", a) to see what values they have, but it says it can't because a is a void pointer.

And with the CompareFunc function, would I have to make a new variable to point to every function I want? I am not quite sure in what case using a typedef on a pointer function would ever be useful. Why not just call compareints() directly? Asking because I have an assignment and can't figure out why we need to code it like this.

Any help would be appreciated. Thank you!

4
  • 1
    Use %p to print your void*s. Your output of -4 is unsurprising and you will see why once you print the addresses. You use function pointers so that you can store or pass around pointers to functions, or interchange functions with the same signature (e.g. see stdlib's qsort() for an example of where they are useful) Commented Sep 25, 2015 at 3:50
  • Thanks! That confirmed I was subtracting addresses. Never knew about %p, very handy. Commented Sep 25, 2015 at 3:58
  • 2
    You might find How to sort an array of structs in C and qsort() function — trying to use a comparator helpful. Commented Sep 25, 2015 at 3:59
  • Yep they are helpful, thanks! Commented Sep 25, 2015 at 4:07

2 Answers 2

2

compareints() returns the difference between two pointers, whether that was your intention or not. If not, you may want to try this:

int compareints(void *a, void *b)
{
    return *(int *)a - *(int *)b;
}

and this:

double comparedbls(void *a, void *b)
{
    return *(double *)a - *(double *)b;
}

The value resulting from how you called it is implementation defined, however, because local variables can be arranged on the stack in any order.

with the CompareFunc function, would I have to make a new variable to point to every function I want?

No. A function pointer can point to any function with the same signature as the pointer.

Typedefs of function pointers can be handy, for example, if you need to pass a comparison function to a generic sort algorithm. In your instance, function pointers are completely unnecessary.

As for casting, any pointer type is allowed to be implicitly converted into a void *, and vice versa. This is done when you call compareints(). When subtracting two pointers of the same type, a value of type ptrdiff_t is returned, which is then implicitly converted into an int when returned from compareints().


Sign up to request clarification or add additional context in comments.

3 Comments

I see, so I can keep redefining test to other functions that have the same header? Thanks for the explanation!
@Maru - Right, you can assign the address of any function that takes the same arguments and returns the same value as the function pointer.
Can you also answer the question about casting I asked below? In case, ameyCU doesn't answer.
1
int compareints(void *a, void *b)
{
    return a-b;
}

This returns difference between two pointers a and b .What value you get is however , implementation defined .

To get difference between their values you can do this -

int compareints(void *a, void *b)
{
    return *(int *)a-*(int *)b;
}

4 Comments

Can you explain the casting? From what I see, you are casting the void pointers to integer pointers then dereferencing?
@Maru It.s because you cant dereference void * . That will casue error . Because compiler don't size of object this pointer points to .Therefor , we use cast.
@Maru to subtract integers, instead of pointers to them, you need to dereference the pointers first... but you shouldn't try to dereference void* (because it could point to anything...), so instead cast it to what you know it is first.
That makes a lot of sense. Thank you both!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.