void pointer in function parameter

22.1k views Asked by At

Consider following program:

#include <iostream>
void f(void* a)
{
    std::cout<<"(void*)fun is called\n";
    std::cout<<*(int*)a<<'\n';
}
int main()
{
    int a=9;
    void* b=(int*)&a;
    f(b);
    return 0;
}

If I change the function call statement like this:

f(&b);

It still compiles fine & crashes at runtime. Why? What is the reason? Should I not get the compile time error? Because the correct way to call the function is f(b). right? Also, why it is allowed to pass NULL to a function whose parameter is of type (void*)?

Please correct me If I am missing something or understanding something incorrectly.

7

There are 7 answers

0
Drew Dormann On BEST ANSWER

It still compiles fine & crashes at runtime. Why? What is the reason?

Because void* is a technique for removing all type-safety and type checking.

Should I not get the compile time error?

By using void* instead of the correct pointer type int*, you are expressly telling the compiler not to tell you if you are using a type incorrectly or in an undefined way.

Because the correct way to call the function is f(b). right?

That's where your function declaration and contents disagree.

    std::cout<<"(void*)fun is called\n";
    std::cout<<*(int*)a<<'\n';

The contents above imply that a pointer to int should be passed:

void f(void* a)

This declaration implies some pointer should be passed, and no other restrictions are made.

2
Xiaotian Pei On

void* can capture any type of pointers, there is no exception to void**

0
Kieren Pearson On

First

You can have a void* point to void**. Your code is one of the many examples showing how dangerous void* pointers can be.

Second

You should for type conversion use:

void* b = static_cast<int*>(&a);

instead of the c style conversion you are using:

void*b = (int*)&a;
0
Ed Heal On

Ok.

As requested.

Do not use void pointers unless it you cannot think of any other way around it.

And the go to bed and think again.

Void pointers enables the programmer to forget about types. This means that the compile can give up on simple checks. This also in my mind means that the programmer has lost the plot.

Downvote me if you wish.

Using types have the luxury that the compiler can check things out for you. E.g. how things are related. How to treat that object.

But using a void pointer you are very much on your own. Good luck

0
Abhishek Bagchi On

You'll not get a compile time error because f(&b) calls f and passes the address of b as a parameter which is then casted into a void*. You get a runtime error because then, you are trying to cast a pointer to an integer as an integer. But yes, as others have stated, doing this a very bad.

0
David Hammen On

If I change the function call statement like this: f(&b); It still compiles fine & crashes at runtime. Why?

Your function f(void*) will accept a pointer to any type, without complaint. Any pointer quietly converts to a void pointer. A pointer to a pointer is still a pointer. So your second case does indeed compile just fine. And then it crashes. Maybe.

In the first case, you converted from a pointer to int to a pointer to void back to a pointer to int. Those round trip conversions through void* (and also through char*) must work. In the second case, you converted from a void** to a void* to an int*. Now you're invoking undefined behavior. Anything goes. On my computer, my compiler, your code runs just fine. It prints garbage. I was quite sure that your code wouldn't erase my hard drive, but it could. Anything goes with undefined behavior. Don't invoke undefined behavior.

The reason for supporting void* is historic. There is a lot of old C and C++ code that use void pointers. The only reason to write new C++ code that uses void pointers is if you need to interact with one of those old functions that use void pointers.

1
Laura On

I found myself here because I am working on a homework assignment that requests the same functionality. After combining each comment, this is what I came up with.

// A function that accepts a void pointer
void f(void* a)
{
    std::cout<<"(void*)fun is called\n";
    std::cout<< "value for a: " << *(int*)a << '\n';
}


int main() {
    int a = 9;
    void* c = static_cast<int*>(&a);

    int b = 3;
    f(&b);
    f(c);
}