943,614 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Marked Solved
  • Views: 3135
  • C++ RSS
Aug 22nd, 2008
0

union vs reinterpret_cast<>()

Expand Post »
Is there any real different between using an union between two types and a reinterpret_cast between two types, for example--

c++ Syntax (Toggle Plain Text)
  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.
Similar Threads
Reputation Points: 392
Solved Threads: 108
Posting Shark
Alex Edwards is offline Offline
971 posts
since Jun 2008
Aug 22nd, 2008
1

Re: union vs reinterpret_cast<>()

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.
Reputation Points: 361
Solved Threads: 97
Posting Pro
Radical Edward is offline Offline
526 posts
since May 2008
Aug 23rd, 2008
1

Re: union vs reinterpret_cast<>()

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...
Reputation Points: 1234
Solved Threads: 347
Postaholic
ArkM is offline Offline
2,001 posts
since Jul 2008
Aug 23rd, 2008
2

Re: union vs reinterpret_cast<>()

> 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
Quote ...
-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:
Quote ...
-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:
Quote ...
-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:
c++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Need help debugging code
Next Thread in C++ Forum Timeline: understanding 3D





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC