union vs reinterpret_cast<>()

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Jun 2008
Posts: 973
Reputation: Alex Edwards is a jewel in the rough Alex Edwards is a jewel in the rough Alex Edwards is a jewel in the rough Alex Edwards is a jewel in the rough 
Solved Threads: 107
Alex Edwards's Avatar
Alex Edwards Alex Edwards is offline Offline
Posting Shark

union vs reinterpret_cast<>()

 
0
  #1
Aug 22nd, 2008
Is there any real different between using an union between two types and a reinterpret_cast between two types, for example--

  1. #include <iostream>
  2.  
  3. int main(){
  4. union{
  5. unsigned short *a;
  6. float *b;
  7. };
  8.  
  9. float value = 0.6f;
  10. b = &value;
  11.  
  12. std::cout << *a << std::endl;
  13.  
  14. unsigned short *s;
  15. float *f;
  16.  
  17. f = &value;
  18. s = reinterpret_cast< unsigned short*>(f);
  19.  
  20. std::cout << *s << std::endl;
  21. return 0;
  22. }

--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.
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 351
Reputation: Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about 
Solved Threads: 62
Radical Edward's Avatar
Radical Edward Radical Edward is offline Offline
Posting Whiz

Re: union vs reinterpret_cast<>()

 
1
  #2
Aug 22nd, 2008
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.
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 2,001
Reputation: ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of 
Solved Threads: 343
ArkM's Avatar
ArkM ArkM is offline Offline
Postaholic

Re: union vs reinterpret_cast<>()

 
1
  #3
Aug 23rd, 2008
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...
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: union vs reinterpret_cast<>()

 
1
  #4
Aug 23rd, 2008
> 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
-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. ...
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:
-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]
and this is what is specified about a reinterpret_cast of one pointer type to a pointer of a different type:
-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.
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:
  1. #include <iostream>
  2.  
  3. int main()
  4. {
  5. union
  6. {
  7. short s ;
  8. int i ;
  9. double d ;
  10. char bytes[ sizeof(double) > sizeof(int) ? sizeof(double)
  11. : sizeof(int) ] ;
  12. } ;
  13.  
  14. i = 123456789 ; // sets first sizeof(int) bytes of the union
  15.  
  16. // ok, interpret the first sizeof(int) bytes as an int
  17. std::cout << "i: " << i << '\n'
  18. // ok, interpret the first sizeof(double) bytes as a double
  19. << "d: " << d << '\n'
  20. // ok, interpret the first sizeof(short) bytes as a short
  21. << "s: " << s << '\n'
  22. // ok, interpret the third byte as a char
  23. << "bytes[3]: " << bytes[3] << '\n' ;
  24.  
  25.  
  26. // ok, reinterpret reference to int as reference to double
  27. std::cout << reinterpret_cast<double&>(i) << '\n' ;
  28. // ok, reinterpret reference to int as reference to short
  29. std::cout << reinterpret_cast<short&>(i) << '\n' ;
  30.  
  31. // ok, reinterpret pointer to int as pointer to double
  32. std::cout << *reinterpret_cast<double*>(&i) << '\n' ;
  33. // ok, reinterpret pointer to int as pointer to short
  34. std::cout << *reinterpret_cast<short*>(&i) << '\n' ;
  35.  
  36. // ok, pd gets the (numeric) value of the int
  37. double* pd = reinterpret_cast<double*>(i) ;
  38. // ok, pd gets the (numeric) value of the short
  39. pd = reinterpret_cast<double*>(s) ;
  40.  
  41. // error, no such reinterpret_cast is possible fom int to double
  42. // std::cout << reinterpret_cast<double>(i) << '\n' ;
  43.  
  44. // error, no such reinterpret_cast is possible
  45. // std::cout << reinterpret_cast<double>(s) << '\n' ;
  46.  
  47. }
Last edited by vijayan121; Aug 23rd, 2008 at 5:01 am.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC