|
-
August 8th, 2009, 07:53 PM
#16
Re: reinterpret_cast<> and where can it be used
 Originally Posted by nuzzle
So what everybody's said in this thread is allright because the C++ standard allows anything; Whatever you say is fine
The only sensible reaction is to never use reinterpret_cast, at least not if you're aiming for portability.
That would be a bit silly, sense it would mean that it's impossible to do some very basic things in a portable manner - ie it would be impossible to read or write portable binary files, since stream read and write methods only work on char*'s.
I haven't read the book in question, but I suspect that you somewhat misread or misunderstood the statement. I imagine the author's intent was to say that the types of actions that require reinterpret_cast are inherently not portable, unless you're careful.
Edit: Well, it wouldn't be impossible (the binary file thing), but it would require a convoluted method like using a union to be able to get the data as char. I'd say that's considerably worse than reinterpret_cast.
Last edited by Speedo; August 8th, 2009 at 08:01 PM.
-
August 8th, 2009, 08:24 PM
#17
Re: reinterpret_cast<> and where can it be used
 Originally Posted by Speedo
I suspect that you somewhat misread or misunderstood the statement.
I'll give you the exact wording (Josuttis on page 20),
-----
4. reinterpret_cast
The behavior of this operator is implementation defined. It may but is not required to reinterpret bits. Using this cast is usually not portable.
------
If you feel Josuttis is wrong please tell us how. Maybe exactly you have a better command of the C++ standard?
Last edited by nuzzle; August 8th, 2009 at 08:30 PM.
-
August 9th, 2009, 12:57 AM
#18
Re: reinterpret_cast<> and where can it be used
Just a couple of points (pls correct me if I am wrong):
1) I noticed a bug with my previous program:
The function printInBinary has an argument of type unsigned int
When I pass the value of the type bool, then type conversion is done implicitly. (something I didn't account for, because I do reinterpret_cast to bool& and on top of that implicit conversion is done to unsigned int). So this doesn't assure the bits are copied the way we expect it to as it involves implicit conversion.
2) I agree that reinterpret_cast is dangerous, I have stated my understanding of reinterpret_cast:
a) reinterpret_cast does a binary copy, so the bit pattern is retained.
b) reinterpret_cast allows you to convert back to the original type successfully.if you do a conversion from type A to type B, then conversion from B to A is possible and A would have the original value (provided sizeof(B) >= sizeof(A) so that you are able to accommodate all the bits)
c) Yes reinterpret_cast is not portable across systems but in the same system it can be converted back as stated above.
d) reinterpret_cast can convert totally unrelated types.
3) I have pasted below a program which tries show a) and b) and also compares with static_cast
Note - I have used a union, because that is the only way I could think of safely avoiding any implicit conversion while invoking the function printInBinary
The maximum number that a unsigned int can hold is 4294967295 (assuming it is 4 bytes).
So you can test the below program using 4294967295 (just easy to spot any bugs).
Code:
#include <iostream>
using std :: cout;
using std :: endl;
using std :: cin;
void printInBinary(const unsigned int pUnsignedNumber);
union UnionDataTypeSet
{
unsigned int unsignedNumber;
float floatNumber;
double doubleNumber;
bool boolean;
};
int main()
{
unsigned int decimalNumber0;
system("clear");
cout << "enter decimalNumber0 : ";
cin >> decimalNumber0;
cout << "decimalNumber0 in bits = ";
printInBinary(decimalNumber0);
cout << "\n=====================reinterpret_cast=====================\n";
//unsigned int to float
UnionDataTypeSet dataTypeSet1;
dataTypeSet1.floatNumber = reinterpret_cast<float&>(decimalNumber0);
cout << "floatNumber in bits = ";
printInBinary(dataTypeSet1.unsignedNumber);
//float to unsigned int
unsigned int decimalNumber1 = reinterpret_cast<unsigned int&>(dataTypeSet1.floatNumber);
cout << "decimalNumber1 in bits = ";
printInBinary(decimalNumber1);
cout << "=====================\n";
//unsigned int to double
UnionDataTypeSet dataTypeSet2;
dataTypeSet2.doubleNumber = reinterpret_cast<double&>(decimalNumber0);
cout << "doubleNumber in bits = ";
printInBinary(dataTypeSet2.unsignedNumber);
//double to unsigned int
unsigned int decimalNumber2 = reinterpret_cast<unsigned int&>(dataTypeSet2.doubleNumber);
cout << "decimalNumber2 in bits = ";
printInBinary(decimalNumber2);
cout << "=====================\n";
//unsigned int to bool (bits lost)
UnionDataTypeSet dataTypeSet3;
dataTypeSet3.boolean = reinterpret_cast<bool&>(decimalNumber0);
cout << "boolean in bits = ";
printInBinary(dataTypeSet3.unsignedNumber);
//bool to unsigned int
unsigned int decimalNumber3 = reinterpret_cast<unsigned int&>(dataTypeSet3.boolean);
cout << "decimalNumber3 in bits = ";
printInBinary(decimalNumber3);
cout << "=====================\n";
cout << "\n=====================static_cast=====================\n";
//unsigned int to float
UnionDataTypeSet dataTypeSet4;
dataTypeSet4.floatNumber = static_cast<float>(decimalNumber0);
cout << "floatNumber in bits = ";
printInBinary(dataTypeSet4.unsignedNumber);
//float to unsigned int
unsigned int decimalNumber4 = static_cast<unsigned int>(dataTypeSet4.floatNumber);
cout << "decimalNumber4 in bits = ";
printInBinary(decimalNumber4);
cout << "=====================\n";
//unsigned int to double
UnionDataTypeSet dataTypeSet5;
dataTypeSet5.doubleNumber = static_cast<double>(decimalNumber0);
cout << "doubleNumber in bits = ";
printInBinary(dataTypeSet5.unsignedNumber);
//double to unsigned int
unsigned int decimalNumber5 = static_cast<unsigned int>(dataTypeSet5.doubleNumber);
cout << "decimalNumber5 in bits = ";
printInBinary(decimalNumber5);
cout << "=====================\n";
//unsigned int to bool (bits lost)
UnionDataTypeSet dataTypeSet6;
dataTypeSet6.boolean = static_cast<bool>(decimalNumber0);
cout << "boolean in bits = ";
printInBinary(dataTypeSet6.unsignedNumber);
//bool to unsigned int
unsigned int decimalNumber6 = static_cast<unsigned int>(dataTypeSet6.boolean);
cout << "decimalNumber6 in bits = ";
printInBinary(decimalNumber6);
cout << "=====================\n";
cout << endl << endl;
return(0);
}
void printInBinary(const unsigned int pUnsignedNumber)
{
const unsigned short int SIZE_OF_TYPE_IN_BITS = sizeof(pUnsignedNumber) * 8;
for(short int index = SIZE_OF_TYPE_IN_BITS - 1; index >= 0; index --)
{
unsigned short int BIT = (pUnsignedNumber >> index) & 1;
cout << BIT;
}
cout << endl;
}
Last edited by Muthuveerappan; August 9th, 2009 at 03:26 AM.
Reason: edited the program to compare with static_cast
-
August 9th, 2009, 01:07 AM
#19
Re: reinterpret_cast<> and where can it be used
The behavior of this operator is implementation defined. It may but is not required to reinterpret bits. Using this cast is usually not portable.
Do you know what he means under "not portable"? I can say that 50%(less or more) C++ features not portable between different platforms. But it's true if you use things dependent on concrete platform. For example you have an address stored inside the int type and you use reinterpret_cast , you shouldn't hope you would have the same pointer's value on different platforms but this code would portable if you don't predict pointer's value.
-
August 9th, 2009, 03:28 AM
#20
Re: reinterpret_cast<> and where can it be used
 Originally Posted by nuzzle
If you feel Josuttis is wrong please tell us how. Maybe exactly you have a better command of the C++ standard?
In fact Josuttis is just paraphrasing the C++ standard:
 Originally Posted by C++03 Section 5.2.10 Paragraph 3
The mapping performed by reinterpret_cast is implementation-defined. [Note: it might, or might not, produce a representation different from the original value. ]
 Originally Posted by ixSci
For example you have an address stored inside the int type and you use reinterpret_cast , you shouldn't hope you would have the same pointer's value on different platforms but this code would portable if you don't predict pointer's value.
If you are just going to cast to and fro and that is all, that would be true. But after you cast you would likely be doing something with the result, and since that result is implementation defined, what you do with it is not guaranteed to be portable.
-
August 10th, 2009, 05:15 AM
#21
Re: reinterpret_cast<> and where can it be used
Thanks to all, has been a big learning
-
August 11th, 2009, 05:36 AM
#22
Re: reinterpret_cast<> and where can it be used
 Originally Posted by ixSci
Do you know what he means under "not portable"? I can say that 50%(less or more) C++ features not portable between different platforms.
With "not portable" he means that reinterpret_cast is defined by the C++ standard to be implementation dependent. It's left to each compiler to decide what to do with it. If you use reinterpret_cast you know that you don't know what will happen without consulting the actual compiler documentation.
The C++ language is not defined for 100% portability (like for example Java). C++ gives leeway for compiler specific variations, still the C++ standard is quite clear about the portability issues you may encounter.
To state that 50% of all C++ constructs are non-portable sounds like an exaggeration to me to say the least. Say the language itself is 5% non-portable and that non-compliancy among major compilers adds another 5%, I could agree that C++ is 10% non-portable at the most.
Note that you must separate the non-portability caused by C++ itself and its compilers, from the non-portability you induce yourself by using platform dependent constructs like specific APIs and fixed memory addresses or whatever. That's a different story. If you use Win32 and DirectX heavily throught-out your program you're likely to be 100% stuck with Microsoft Windows I should guess.
Last edited by nuzzle; August 11th, 2009 at 06:14 AM.
-
August 11th, 2009, 07:49 AM
#23
Re: reinterpret_cast<> and where can it be used
 Originally Posted by nuzzle
If you use reinterpret_cast you know that you don't know what will happen without consulting the actual compiler documentation.
I have expressed my view below (correct me if I am wrong):
reinterpret_cast will do a binary copy and you will be able to cast back to original type (as long the type is large enough to hold the bits and if it is not used across the systems).
If you are planning to use the value of the pointer after casting then it could mean trouble but reinterpret_cast only means binary copy. It means trouble because, different types use different bit patterns to represent a value.
So if you are using it in the same system, then I don't think we need to know the implementation, because we can be guaranteed that it would be a binary copy.
-
August 11th, 2009, 08:23 AM
#24
Re: reinterpret_cast<> and where can it be used
If you feel Josuttis is wrong please tell us how. Maybe exactly you have a better command of the C++ standard?
The statement is ambiguous and misleading. It gives the impression (as evidenced by your posts) that you have literally no idea what reinterpret_cast will do on a given compiler. That is blatantly false. As usual, the standard tells us what:
- The result of reinterpret_cast is an lvalue only if the target type is a reference type.
- reinterpret_cast may not cast away constness
- A pointer can be converted to any integral type large enough to hold it
- A value of integral or enumeration type can by converted to a pointer
- A pointer converted to an integer, and back to a pointer of the same type will have its original value
- A pointer to a function can be converted to a pointer to a function of a different type, but the effect of calling the function through a pointer that doesn't match the function definition is undefined
- A pointer to an object can be converted to a pointer to an object of a different type
- A pointer to an object that's converted to a pointer to object of a different type and then back to the original type will have the original value
- The null pointer value is converted to the null pointer value of the target type
- A pointer to member can be converted to a pointer to member of a different type, but the result of the conversion is undefined except that converting the result back to the original type will yield the original value
- An lvalue of type "T1" can be cast to "reference to T2" if it is possible for reinterpret_cast to convert "pointer to T1" to "pointer to T2"; no temporary is created, no copy is made, no constructors or conversion functions are called
But it doesn't tell us anything about how:
- "The mapping performed by reinterpret_cast is implementation-defined. [Note: it might, or might not, produce a representation different from the original value. ]"
So while there is no promise of portability in the standard, I still maintain that the statement
The only sensible reaction is to never use reinterpret_cast, at least not if you're aiming for portability.
is a bit silly, for several reasons:
A significant number of instances when reinterpret_cast needs to be used are (or should be) already in platform-specific code.
To my knowledge, the major C++ compiler vendors all implement reinterpret_cast in the same manner. Avoiding reinterpret_cast then is kind of like insisting on code which doesn't assume that a byte is 8 bits. It's technically correct, but unless you know you're going to be targetting something that breaks with the norm, really, why bother?
There are instances where reinterpret_cast is the only cast which will work. You can't simply use a C-style cast in its place if you're being paranoid about portability - the compiler is still going to do the conversion via the same underlying [non-portable] methods. This means you're going to have to resort to something like unions, which I say is uglier than reinterpret_cast.
-
August 11th, 2009, 11:03 AM
#25
Re: reinterpret_cast<> and where can it be used
 Originally Posted by Muthuveerappan
reinterpret_cast will do a binary copy
It typically does, but that is not guaranteed, as I have quoted the standard.
 Originally Posted by Speedo
The statement is ambiguous and misleading. It gives the impression (as evidenced by your posts) that you have literally no idea what reinterpret_cast will do on a given compiler. That is blatantly false.
If you are talking about Josuttis' statement, then that would not be correct since Josuttis states that "the behavior of this operator is implementation defined". The term "implementation defined" makes it clear that one can find out its behaviour with respect to a given implementation, i.e., "what reinterpret_cast will do on a given compiler".
 Originally Posted by Speedo
A significant number of instances when reinterpret_cast needs to be used are (or should be) already in platform-specific code.
In this I agree: it is certainly possible to isolate nonportable code and thus get a measure of portability by being able to cater for each specific implementation to be supported.
Consequently, I would summarise Sutter and Alexandrescu's opinion on this as presented in C++ Coding Standards: "Don't try to use reinterpret_cast to force the compiler to reinterpret the bits of an object of one type as being the bits of an object of a different type", but when you have to, e.g., due to "some low-level system-specific programming", "use unsafe casting as rarely as you can and only in well-hidden functions that abstract it away, so as to make your code ready for porting with minimal changes".
-
August 11th, 2009, 11:22 AM
#26
Re: reinterpret_cast<> and where can it be used
If you are talking about Josuttis' statement, then that would not be correct since Josuttis states that "the behavior of this operator is implementation defined". The term "implementation defined" makes it clear that one can find out its behaviour with respect to a given implementation, i.e., "what reinterpret_cast will do on a given compiler".
The behavior of reinterpret_cast -the actions that can be performed with it- is clearly defined by the standard. The results of those actions are implementation defined.
The distinction between those is subtle, and can be confusing, which is why I said that the author's statement was ambiguous.
-
August 11th, 2009, 11:44 AM
#27
Re: reinterpret_cast<> and where can it be used
I have a few doubts:
When the reinterpret_cast is implementation specific does it mean one of the the following or something else:
a) Different compilers use different bit patterns and hence binary copy would be different in different compilers, therefore reinterpret_cast would be different on different compilers (meaning reinterpret_cast does a binary copy but the bit patterns are different on different compilers / platforms) ?
b) Or does it mean reinterpret_cast in certain compilers might do something other than a binary copy ?
Which one of them is correct (or is it something else) ?
Thanks,
Muthu
-
August 11th, 2009, 11:50 AM
#28
Re: reinterpret_cast<> and where can it be used
 Originally Posted by Speedo
The behavior of reinterpret_cast -the actions that can be performed with it- is clearly defined by the standard. The results of those actions are implementation defined.
The distinction between those is subtle, and can be confusing, which is why I said that the author's statement was ambiguous.
Read the statement in context: immediately after stating that "the behavior of this operator is implementation defined", Josuttis goes on to explain that "it may reinterpret bits, but it is not required to do so". This means that Josuttis considers the specification of the result of reinterpret_cast as part of the specification of its behaviour, and I can find no fault with that.
If you still feel that the statement is too terse and thus results in ambiguity that may mislead a reader, take it up with the author, who has diligently published errata in the past.
 Originally Posted by Muthuveerappan
When the reinterpret_cast is implementation specific does it mean one of the the following or something else:
a) Different compilers use different bit patterns and hence binary copy would be different in different compilers, therefore reinterpret_cast would be different on different compilers (meaning reinterpret_cast does a binary copy but the bit patterns are different on different compilers / platforms) ?
b) Or does it mean reinterpret_cast in certain compilers might do something other than a binary copy ?
Which one of them is correct (or is it something else) ?
I consider the answer to be closer to b, but a is true as well in the sense that representation of a type may differ from implementation to implementation.
Last edited by laserlight; August 11th, 2009 at 11:55 AM.
-
August 11th, 2009, 03:29 PM
#29
Re: reinterpret_cast<> and where can it be used
 Originally Posted by Speedo
So while there is no promise of portability in the standard, I still maintain that the statement
"The only sensible reaction is to never use reinterpret_cast, at least not if you're aiming for portability."
is a bit silly, for several reasons:
Well, never to use reinterpret_cast should be your very strong ambition at least. Use it only under exceptional circumstances in low-level system-specific code. That's the general consensus. See for example #92. Avoid using reinterpret_cast (in C++ Coding Standards by Sutter & Alexandrescu.)
Last edited by nuzzle; August 11th, 2009 at 04:13 PM.
-
August 11th, 2009, 04:08 PM
#30
Re: reinterpret_cast<> and where can it be used
 Originally Posted by Speedo
The behavior of reinterpret_cast -the actions that can be performed with it- is clearly defined by the standard. The results of those actions are implementation defined.
The distinction between those is subtle, and can be confusing, which is why I said that the author's statement was ambiguous.
The behaviour of reinterpret_cast is defined in ten paragraphs in the C++ standard, and one of them states that "the mapping performed by reinterpret_cast is implementation-defined". This paragraph renders reinterpret_cast non-portable. But there's no "subtle distinction" that sets this paragraph apart from the other nine. It's an integral part of the total definition of the behaviour of reinterpret_cast.
Last edited by nuzzle; August 11th, 2009 at 04:36 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|