| | |
union vs reinterpret_cast<>()
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
Is there any real different between using an union between two types and a reinterpret_cast between two types, for example--
--the results of the test are the same between the union and the reinterpret_cast but I would like to know if there is some kind of difference I should be aware of when using both.
Thank you!
-Alex
c++ Syntax (Toggle Plain Text)
#include <iostream> int main(){ union{ unsigned short *a; float *b; }; float value = 0.6f; b = &value; std::cout << *a << std::endl; unsigned short *s; float *f; f = &value; s = reinterpret_cast< unsigned short*>(f); std::cout << *s << std::endl; return 0; }
--the results of the test are the same between the union and the reinterpret_cast but I would like to know if there is some kind of difference I should be aware of when using both.
Thank you!
-Alex
Last edited by Alex Edwards; Aug 22nd, 2008 at 5:25 pm.
The only thing Edward can think of is using a union like that isn't required to work even if the conversion is safe but a reinterpret_cast<> is. The rules say that assigning to one member of a union and then accessing a different member right away is undefined behavior.
If at first you don't succeed, keep on sucking until you do succeed.
Some additions:
In most of C++ implementations reinterpret_cast do nothing (like formally incorrect union trick, see Radical Edward's note). If you want to make a trick, do it honestly (it is open to question, of course
). It follows from this that reinterpret_cast is "better" than union trick (in the spirit of C++ language).
I know (old) computers where pointers are hardware-typed, so you can't refer to an integer via pointer to float (and vice versa). Probably, on such computers C++ compiler (in theory) can generate a proper conversion code for reinterpret_cast (but not for unions, of course). A very good compiler is capable to generate a proper run-time check up of a good object alignment (in debug mode, for example) for reinterpret_cast - and so on.
Apropos, reinterpret_cast for pointers has C++-defined result only if you previously assigned a pointer value to void* then reinterpret_cast this void* value to the same type!
Moral: use reinterpret_cast where possible, but a trick is a trick...
In most of C++ implementations reinterpret_cast do nothing (like formally incorrect union trick, see Radical Edward's note). If you want to make a trick, do it honestly (it is open to question, of course
). It follows from this that reinterpret_cast is "better" than union trick (in the spirit of C++ language).I know (old) computers where pointers are hardware-typed, so you can't refer to an integer via pointer to float (and vice versa). Probably, on such computers C++ compiler (in theory) can generate a proper conversion code for reinterpret_cast (but not for unions, of course). A very good compiler is capable to generate a proper run-time check up of a good object alignment (in debug mode, for example) for reinterpret_cast - and so on.
Apropos, reinterpret_cast for pointers has C++-defined result only if you previously assigned a pointer value to void* then reinterpret_cast this void* value to the same type!
Moral: use reinterpret_cast where possible, but a trick is a trick...
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
> Is there any real different between using an union between two types and a reinterpret_cast between two types
yes, there are quite a lot of differences.
a union reinterprets the layout of memory (depending on which member is accessed).
a reinterpret_cast is a conversion operator.
the conversions that can be performed using a reinterpret_cast are limited; the permissible ones are specified by the standard.
IS 5.2.10 - Reinterpret cast
and then it goes on to list the conversions that can be performed explicitly using reinterpret_cast. for example this is what is specified about pointer to integral and integral to pointer conversions:
and this is what is specified about a reinterpret_cast of one pointer type to a pointer of a different type:
however, for pointers to POD types, both a union and a reinterpret_cast should give identical results:
IS 5.4/5 says "...barring const_cast, C-style cast is equivalent to reinterpret_cast, (unless static_cast is possible)"
IS 9.5/1 "The size of a union is sufficient to contain the largest of its data members. Each data member is allocated as if it were the sole member of a struct"
IS 9.2/17 "A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member [...] and vice versa."
taken together, this seems pretty clear - these constrain the implementation of pointer reinterpret_cast; the source and destination pointer shall point to the same object (have the same value), unless this is impossible due to alignment requirements. even if they have different values (due to alignment requirements), the union and reinterpret_cast would give identical results.
an example showing some of the differences between union and reinterpret_cast:
yes, there are quite a lot of differences.
a union reinterprets the layout of memory (depending on which member is accessed).
a reinterpret_cast is a conversion operator.
the conversions that can be performed using a reinterpret_cast are limited; the permissible ones are specified by the standard.
IS 5.2.10 - Reinterpret cast
•
•
•
•
-1- The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T.
...
Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.
-2- The reinterpret_cast operator shall not cast away constness. ...
-3- The mapping performed by reinterpret_cast is implementation-defined. ...
•
•
•
•
-4- A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined.
[Note: it is intended to be unsurprising to those who know the addressing structure of the underlying machine. ]
-5- A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. [Footnote: Converting an integral constant expression with value zero always yields a null pointer, but converting other expressions that happen to have value zero need not yield a null pointer. --- end foonote]
•
•
•
•
-7- A pointer to an object can be explicitly converted to a pointer to an object of different type.
[Footnote: The types may have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness. --- end foonote]
Except that converting an rvalue of type ``pointer to T1'' to the type ``pointer to T2'' (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
IS 5.4/5 says "...barring const_cast, C-style cast is equivalent to reinterpret_cast, (unless static_cast is possible)"
IS 9.5/1 "The size of a union is sufficient to contain the largest of its data members. Each data member is allocated as if it were the sole member of a struct"
IS 9.2/17 "A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member [...] and vice versa."
taken together, this seems pretty clear - these constrain the implementation of pointer reinterpret_cast; the source and destination pointer shall point to the same object (have the same value), unless this is impossible due to alignment requirements. even if they have different values (due to alignment requirements), the union and reinterpret_cast would give identical results.
an example showing some of the differences between union and reinterpret_cast:
c++ Syntax (Toggle Plain Text)
#include <iostream> int main() { union { short s ; int i ; double d ; char bytes[ sizeof(double) > sizeof(int) ? sizeof(double) : sizeof(int) ] ; } ; i = 123456789 ; // sets first sizeof(int) bytes of the union // ok, interpret the first sizeof(int) bytes as an int std::cout << "i: " << i << '\n' // ok, interpret the first sizeof(double) bytes as a double << "d: " << d << '\n' // ok, interpret the first sizeof(short) bytes as a short << "s: " << s << '\n' // ok, interpret the third byte as a char << "bytes[3]: " << bytes[3] << '\n' ; // ok, reinterpret reference to int as reference to double std::cout << reinterpret_cast<double&>(i) << '\n' ; // ok, reinterpret reference to int as reference to short std::cout << reinterpret_cast<short&>(i) << '\n' ; // ok, reinterpret pointer to int as pointer to double std::cout << *reinterpret_cast<double*>(&i) << '\n' ; // ok, reinterpret pointer to int as pointer to short std::cout << *reinterpret_cast<short*>(&i) << '\n' ; // ok, pd gets the (numeric) value of the int double* pd = reinterpret_cast<double*>(i) ; // ok, pd gets the (numeric) value of the short pd = reinterpret_cast<double*>(s) ; // error, no such reinterpret_cast is possible fom int to double // std::cout << reinterpret_cast<double>(i) << '\n' ; // error, no such reinterpret_cast is possible // std::cout << reinterpret_cast<double>(s) << '\n' ; }
Last edited by vijayan121; Aug 23rd, 2008 at 5:01 am.
![]() |
Similar Threads
Other Threads in the C++ Forum
- Previous Thread: Need help debugging code
- Next Thread: understanding 3D
| Thread Tools | Search this Thread |
api array based beginner binary c++ c/c++ calculator char char* class classes code compile compiler console conversion count delete deploy desktop directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp homeworkhelper iamthwee ifstream input int integer java lib linkedlist linker linux list loop looping loops map math matrix memory news numbertoword output parameter pointer problem program programming project proxy python random read recursion recursive reference return rpg sorting string strings struct temperature template templates test text text-file tree unix url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






