It's not actually legal to mix reinterpret_cast<> with pointers to void.

You've come to this page because you've mixed reinterpret_cast<> with pointers to void, with code similar to the following

struct T { /*…*/ } ; T * a = new T ; void * void_ptr = reinterpret_cast<void *>(a) ; T * b = reinterpret_cast<T *>(void_ptr) ;

This is the Frequently Given Answer to such admixtures.

You may think that it's legal to mix reinterpret_cast<> with pointers-to-void. Many people do. It's in numerous tutorials and code snippets on the World Wide Web (such as this one and this one), and occurs as an example in books. (It was even in Bjarne Stroustrup's The C++ Programming Language on page 342 until it was noticed and fixed in the 3rd Edition.) Programmers use it in code, and their C++ compilers accept it without batting an eyelid. It's passed around by word of mouth, and it's deeply entrenched in many people's thinking.

They're all wrong. If you want to create well-formed C++ programs, that actually adhere to the letter of the C++ Standard, then you must use static_cast<> for such conversions. The C++ Standard explicitly prohibits this use of reinterpret_cast<>.

In the opinions of a number of people, including some members of the U.K.'s C++ standards Panel, this is a defect in the C++ Standard that needs fixing. I've written a proposed revised wording for fixing this defect.

Nonetheless, as the C++ Standard stands, and as it has stood for the past decade, reinterpret_cast<> of pointers to void is not well-formed code.

What the wording of the C++ Standard actually prohibits and permits

The relevant portion of ISO/IEC 14882:1998 is §5.2.10 ¶1, which says:

Conversions that can be performed using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.

The simple fact of the matter is that none of the conversions listed below that paragraph is a conversion either to or from pointer to void. It's simply not there. Since it's not a listed conversion, it cannot, per the quite clearly expressed constraint upon programs that that paragraph lays out, be used in a well-formed program. Any program that mixes reinterpret_cast<> with pointers to void is, in fact, ill-formed.

One can use reinterpret_cast<> for converting between pointers to object types. This is permitted via ¶7 of §5.2.10. But as §3.9 ¶2 explains (and §4.10 ¶2 reiterates), pointers to void are not pointers to object types.

Conversion from a pointer to object type to pointer-to-void is a standard pointer conversion, as described in §4.10 ¶2 of the Standard. Similarly, both §5.2.9 ¶6 and ¶10 permit conversion from pointer-to-void to pointer to object type using static_cast<>. Thus the code snippet at the top of this Frequently Given Answer should, to be well-formed, read:

struct T { /*…*/ } ; T * a = new T ; void * void_ptr = a ; // standard pointer conversion, no explicit cast needed T * b = static_cast<T *>(void_ptr) ; // static_cast<> can reverse a standard pointer conversion

Self-contradiction in the Standard

Pretty much all C++ implementations permit this illegal use of reinterpret_cast<> in practice. One could view this as an implementation conformance issue, a diagnosable rule that no implementation actually enforces. But is far better viewed as a defect in the C++ Standard. The implementations are right. The Standard is wrong, and isn't standardizing existing practice.

It is far better viewed as a defect in the C++ Standard not least because the C++ Standard actually contradicts itself on this matter. The idea that one can reinterpret_cast<> to and from a pointer-to-void, despite the Standard explicitly saying that one cannot, is so pervasive that even the people who have worked on the Standard in the past 10 years think that it's the case, and have written other parts of the Standard on the basis that one can.

In particular, § ¶3 of the new version of ISO/IEC 9899, currently at Draft International Standard stage, explicitly defines program semantics in terms of reinterpret_cast<void *>. So the new draft C++ Standard is in the rather unfortunate position of defining things in terms of program constructs that it explicitly states to be prohibited.

© Copyright 2009 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.