See my previous post else-thread for my understanding.
I didn't see any real explination, other than to provide a new
style cast for certain C style casts.
Note that my statement above is based on how compiler optimizers
work. The motivation behind the anti-aliasing rule (e.g. that
two pointers to different types cannot refer to the same object)
is to allow certain optimizations. Optimizations which are
important in some code. But this only works if the above is not
guaranteed to work.
As the C++ standard is currently written, the above *is*
guaranteed to work. I don't think that this was the intent,
however. C has (or had) similar rules. I know that the issue
was discussed in the C committee, but I don't know the exact
status of the proposed resolution.
//Start code for foo.cpp
#include <iostream>
using namespace std;
int main()
{
cout << sizeof(int) << " " << sizeof(short) << endl;
{
int x = 1;
short* s = reinterpret_cast<short*>(&x);
s[0] = 2;
s[1] = 3;
cout << x << endl;
}
{
int x = 1;
union { int u_int; short u_short_array[2]; };
u_int = x;
u_short_array[0] = 2;
u_short_array[1] = 3;
x = u_int;
cout << x << endl;
}
}
//Start prompt copy
bash-3.2$ g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
bash-3.2$ g++ -O3 foo.cpp -Wall
foo.cpp: In function âint main()â:
foo.cpp:9: warning: dereferencing type-punned pointer will break
strict-aliasing rules
bash-3.2$ ./a.out
4 2
1
196610
bash-3.2$
//end prompt copy
So, when the union is in scope, gcc "does the right thing",
and when reinterpret_cast is in scope, gcc does not "do the
right thing".
Which is, from a QoI point of view, an error.
In fact, I don't know whether this is an error in the coding,
a problem in the way that the optimizer works which would make
it difficult (and perhaps not worth it) to fix, or simply a bit
of stubborness on the part of g++ developers. It does mean that
reinterpret_cast is useless, which is certainly not the intent
of the committee.
The issue isn't simple. Historically (pre-ISO C), the union was
the preferred solution, at least from what I understood. For
whatever reasons, the ISO C committee (or at least the parts of
it which formallized the wording in this regard) designed to
make type punning via a union undefined behavior, which means
that only casting remains. The C++ committee simply followed
the C committee in this respect---I'm 100% sure that the intent
of the C++ committee is that a reinterpret_cast, when legal,
behave exactly the same as a cast in C.
In addition, there is a note (non-normative) in the C++ standard
(§5.2.10/3) concerning the mapping done by reinterpret_cast: "it
is intended to be unsurprising to those who know the addressing
structure of the underlying machine". Although this note is
directly attached to the pointer to integer conversion, in the
absense of any other indications, it seems reasonable to me to
apply it to the other uses of reinterpret_cast as well.
In any case, the current standard is very unclear with regards
to type punning---with the exception of character types. And I
don't think that this has changed in the more recent drafts---in
a very real sense, I think that it is more a C problem; that the
C++ committee should simply wait, and adopt whatever the C
committee finally decides.
Now, I don't know any other compilers offhand which optimize
with the strict aliasing allowance besides newer gcc versions,
I don't know of any that don't. It's a common optimization. It
was present in Microsoft C 1.0, for example (in which your union
example would break).
but I would suggest you revise your understanding of the QoI
implications of reinterpret_cast.
Why? My understanding of the QoI implications are based on the
actual words in the standard, and the various discussions that
I've followed in the standardization committees.
My previous argument succinctly: C-style casts were never
intended to get around strict aliasing.
Yes and no. An optimizer is expected to use the knowledge at
its disposal. If it can see that there is aliasing, whether
from a union or a cast, it should take it into account.
That is, by the way, the direction the C committee was going the
last time I looked.
reinterpret_cast was never intended to be more powerful than
C-style casts.
Certainly not. But since the C style cast should behave as
expected, when visible, so should the reinterpret_cast.
(The named casts were each intended to fulfill a specific role
of the several roles of C-style casts to remove potential
ambiguity to the code writer and readers.) Thus
reinterpret_cast was never intended to get around strict
aliasing.
You seem to be misunderstanding the motivation behind the strict
aliasing rule. It is to allow the compiler to assume no
aliasing in cases where it otherwise couldn't. There was never
any intent to allow the compiler to totally ignore aliasing that
it can clearly see.
Perhaps I am wrong about the original intent. However, I'm at
least right on the questions of fact, at least if we count gcc
as a good example.
I don't think you can count any single compiler as a
"reference".
You would need to type pun somewhere as the OS network calls
probably only work in terms of char pointers.
No. You do need to convert value types, but that's all.
For integral types, there's really no need for any type punning
whatsoever. In the case of floating point, the issue is more
complex, since the code necessary to portably convert a string
of bytes of a given format into a floating point value is
relatively complex, and more expensive than type punning an
uint_64 to a double, in the case where you know that the
external format and the internal format are the same (e.g.
IEEE).
So either the game code is type punning, or the network
library on top of the OS is type punning, or the device driver
is type punning (or written in assembly). Someone is probably
type punning in C or C++.
I've written a lot of network code in which there was no type
punning. I have an implemenation of an xdrstream which does no
type punning, even for floating point. For integral types, it's
about as fast as implementations which do type pun (but it is
far more portable); for floating point, it's measurably slower
(but has the advantage that it works regardless of the machine
floating point format), but not nearly as much as I initially
expected.