Casting to void* and Back to Original_Data_Type*

眉间皱痕 提交于 2019-12-04 04:15:34

问题


I have seen and used this many times is C++, specially in various thread implementations. What I wonder is if there are any pitfalls/ issues of doing this? Is there any way that we could run in to an error or undefined condition when we are casting to void* and back again? How should we resolve such issues if there are any?

Thank you.


回答1:


What I wonder is if there are any pitfalls/ issues of doing this?

You need to be absolutely sure while casting the the void* back to the particular type, if you don't, you end up with an Undefined behavior and a potential disaster. Once you use void * you lose type safety.It is difficult to keep track of what type a void * is actually pointing to, there is no way to guarantee or determine that it indeed points to the type to which you are going to typecast it back to.

Is there any way that we could run in to an error or undefined condition when we are casting to void* and back again?

Yes, the scenario mentioned in #1.

How should we resolve such issues if there are any?

Avoid using void * in C++ completely, instead use templates and inheritance.
In C you might absoultely need it in certain situations but try to keep its use to a minimum.
Bottomline,
C/C++ allows you to shoot yourself in foot, it is up to you to do or not do so.




回答2:


I have not seen casting to void* much in C++. It was a practice in C that was actively avoided in C++.

Casting to void* removes all type safety.

If you use reinterpret_cast or static_cast to cast from a pointer type to void* and back to the same pointer type, you are actually guaranteed by the standard that the result will be well-defined.

The hazard is that you may cast a void* to the wrong type, since you are no longer assured of what the correct type was.




回答3:


The only thing the standard grants is that, given A* pa, (A*)(void*)pA == pA. A a consequence

void* pv = pA;
A* pA2 = (A*)pv;
pA2->anything ...

will be te same as pA->anything ...

Everything else is "not defined", ad -in fact- is somehow implementation dependent.

Based on my experience, here are some known pitfalls:

  • Consider A derived form B, pA and pB to be A* and B*. pB=pA makes pB to point to the base of A. That doesnt mean that pB and pA are the same address. hence pB = (B*)(void*)pA can actually point anywhere else into A (although single inheritance objects are commonly implemented sharing the same origin, so it apparently works fine)
  • The same is viceversa: Assuming pB actually is pointing to an A, pA = (A*)(void*)pB don't necessarily point correctly to the A object. The correct way is pA = static_cast<A*>(pB);
  • If the above points can work with the most of single inheritance implementations, will never work with multiple imheritance for bases other than the first: consider class A: public Z, public B { ... }; if Z is not empty, given an A, the B subcomponent will not have the same A address. (and multiple inheritance in C++ is everywhere an iostream is)
  • Sometimes things depend also on the platform: (char*)(void*)pI (where pI points to an integer) will not be the same as "*pI if *pI in(-128..+127)" (it will be only on little endian machines)

In general don't assume conversion between types works just changing the way an address is interpreted.




回答4:


I know a lot of functions within driver etc. using void pointers to return data to the caller, the schema is mostly the same:

int requestSomeData(int kindOfData, void * buffer, int bufferSize);

This function can take different data types as parameter. What they do is using bufferSize as a parameter to avoid writing to memory places they should not write to. If the bufferSize does not match or is smaller than the data that shall be returned, the function will return an error code instead.

Anyway: Avoid using them or think threefold before writing any code.



来源:https://stackoverflow.com/questions/12275321/casting-to-void-and-back-to-original-data-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!