简体   繁体   中英

Passing pointer to struct, vs. passing void pointer and casting to struct

I'm working on a legacy code base that has this pattern:

struct sometype_t { /* ... */ };

int some_method(void *arg1) { // void pointer
    ((sometype_t*)arg1)->prop1; // cast
}

Is there any (common) scenario where it would be unsafe to use sometype_t * instead of void * ?

int some_method(sometype_t *arg1) {
    arg1->prop1;
}

The pointer isn't passed across ABIs or into 3rd-party libraries; it stays entirely within C++ code that we own.

It's usually not a good choice, but the only situation I'm aware of where this really make sense is if you want to have stateful callbacks passed into a function, without using templates:

void takes_callback(void(*f)(void*), void * data);

Basically the gist is that since you aren't using templates, you have to fix the function signature you accept (of course, it can and often does take other arguments and return something as well). If you just call the function with your own parameters though, the function can only hold state between calls via global variables. So instead the contract for takes_callback promises to call f with data as a parameter.

So, if you wanted to use some_method as a callback in such an API, you would have to have it take void* , and do the cast internally. Obviously, you are throwing away type safety here, and if you happen to call takes_callback with &somemethod and a pointer to anything that's not a sometype_t you have UB.

Having a C ABI is one reason to avoid templates, but it's not the only one. Maybe they were worried about code bloat, or wanted to keep the implementation in a .so so that versions could be upgraded without recompiling, etc.

The obvious common scenario that immediately comes to mind is callbacks for some functions from C standard library.

For example, the proper way to write the comparison callback for std::qsort is to declare the function with two const void * arguments and then cast them to proper specific pointer types inside the callback.

Replacing these const void * parameters with specifically-typed pointers will simply prevent the code from compiling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM