Imaš li ti dokaz da radi na svakom kompajleru? Pošto standard, koji definiše šta je C++, a ne kompajleri, za ovaj program kaže da je nedefinisan.
Ovaj kod nije portabilan, za razliku od C verzije koja jeste, u kojoj je ponašanje jasno određeno standardom.
Fundamentalni razlog može da bude vrlo prizeman, kao što je optimizacija, kada kompajler može da vidi da se u samo jedno polje unije upisivalo, i da zameni celu uniju samo jednim poljem, ostavljajući sve ostalo nedefinisano.
Već sam ti dao primere u prošlosti kada je kompajler zbog optimizacije kao fundamentalnog razloga, potpuno razbio neportabilne programe. Najčuveniji je strict-aliasing, koji je razbio mnogo toga, uključujući i Linux kernel. Evo Linusova poruka na tu temu (
https://lkml.org/lkml/2003/2/26/158, boldovanje moje):
Citat:
Why do you think the kernel uses "-fno-strict-aliasing"?
The gcc people are more interested in trying to find out what can be
allowed by the c99 specs than about making things actually _work_. The
aliasing code in particular is not even worth enabling, it's just not
possible to sanely tell gcc when some things can alias.
> Some users have complained that when the following code is
>compiled without the -fno-strict-aliasing, the order of the write and
>memcpy is inverted (which mean a bogus len is mem-copied into the
>stream).
The "problem" is that we inline the memcpy(), at which point gcc won't
care about the fact that it can alias, so they'll just re-order
everything and claim it's out own fault. Even though there is no sane
way for us to even tell gcc about it.
I tried to get a sane way a few years ago, and the gcc developers really
didn't care about the real world in this area. I'd be surprised if that
had changed, judging by the replies I have already seen.
I'm not going to bother to fight it.
https://www.mail-archive.com/[email protected]/msg01647.html
Citat:
That's INSANE. It's so incredibly insane that people who do that should
just be put out of their misery before they can reproduce. But real gcc
developers really thought that it makes sense, because the standard allows
it, and it gives the compiler the maximal freedom - because it can now do
things that are CLEARLY NONSENSICAL.
And to compiler people, being able to do things that are clearly
nonsensical seems to often be seen as a really good thing, because it
means that they no longer have to worry about whether the end result works
or not - they just got permission to do stupid things in the name of
optimization.
So gcc did. I know for a _fact_ that gcc would re-order write accesses
that were clearly to (statically) the same address. Gcc would suddenly
think that
unsigned long a;
a = 5;
*(unsigned short *)&a = 4;
could be re-ordered to set it to 4 first (because clearly they don't alias
- by reading the standard), and then because now the assignment of 'a=5'
was later, the assignment of 4 could be elided entirely! And if somebody
complains that the compiler is insane, the compiler people would say
"nyaah, nyaah, the standards people said we can do this", with absolutely
no introspection to ask whether it made any SENSE.
Još nekoliko primera, kao što su
https://davmac.wordpress.com/2009/10/ možeš naći na
https://stackoverflow.com/ques...ct-aliasing-and-horror-stories
Ne mogu da pronađem tačno kada je GCC podrazumevano uključio strict aliasing, ali
https://www.gnu.org/software/gcc/bugs/ kaže "recently":
Citat:
Recent versions of GCC turn on the option -fstrict-aliasing (which allows alias-based optimizations) by default with -O2. And some architectures then really print "1111 1111" as result. Without optimization the executable will generate the "expected" output "2222 2222".