Recently discovered a strange compilation parameter-fno-strict-aliasing, curious to do a little research;
The key reference Understanding C + + Strict aliasing;
The so-called aliasing is that multiple variables point to the same piece of memory, and the variables are aliases;
Strict-aliasing is a rule that the compiler expects developers to follow: although C + + variables can be arbitrarily assigned (coercion type conversion), but also please you converge a little, not too unconstrained;
If the developer writes the code according to this rule, the compiler can do better code optimization, such as this example:
void foo (double *dblptr) { 1; 0 ; Bar (anint);}
If the developer can be careful not to turn int* into Double*,bar (Anint) can be directly optimized to bar (1);
However, no constraint is allowed to do so, so the compiler does not dare to do such an optimization, only the bar (Anint) anint into the bar before adding a assembly instruction to read the value of Anint;
If the developer determines that his code complies with such rules, it can add an optimization parameter-fstrict-aliasing at compile time, which is turned on by default at GCC-o2,-o3, and-os optimization levels.
Then I tested the two main examples of the understanding C + + Strict aliasing article:
Example one:
#include <stdio.h>intAnint;voidBarinta) {printf ("%d\n", a);}voidFooDouble*dblptr) {Anint=1; *dblptr =0; Bar (anint);}intMain () {foo (Double*) &anint); return 0;}
Compiler version |
Compile parameters |
Results |
GCC 4.4.7 |
g++ |
0 |
|
g++-o3 |
1 |
|
g++-o3-fno-strict-aliasing |
0 |
GCC 4.8.5 |
g++ |
0 |
|
g++-o3 |
1 |
|
g++-o3-fno-strict-aliasing |
0 |
GCC 7.3.0 |
g++ |
0 |
|
g++-o3 |
1 |
|
g++-o3-fno-strict-aliasing |
0 |
As you can see, this case is optimized by the GCC compiler and can be circumvented with-fno-strict-aliasing;
Example two:
#include <iostream>#include<iomanip>using namespacestd;typedef unsignedintuint32_t;typedef unsigned Shortuint16_t;uint32_t swaphalves (uint32_t a) {uint32_t acopy=A; uint16_t*ptr = (uint16_t*) &acopy;//can ' t use Static_cast<> //You should is warned by.uint16_t tmp = ptr[0]; ptr[0] = ptr[1]; ptr[1] =tmp; returnacopy;}intMain () {uint32_t A; A= +; cout<< Hex << Setfill ('0') << SETW (8) << a <<Endl; A=Swaphalves (a); cout<< SETW (8) << a <<Endl;}
Compiler version |
Compile parameters |
Results |
GCC 4.4.7 |
g++ |
00000020 00200000 |
|
g++-o3 |
00000020 00000020 |
GCC 4.8.5 |
g++ |
00000020 00200000 |
|
g++-o3 |
00000020 00200000 |
GCC 7.3.0 |
g++ |
00000020 00200000 |
|
g++-o3 |
00000020 00200000 |
Find this case a bit of a meaning, only in the 4.4 version of the compiler will be a problem, the high version of the compiler has been fixed.
Without the energy to go into it, that's it.
Finally affixed to the rules of strict aliasing, the following article gives a good Chinese translation, and the author is obviously more than my research, I directly copied over:
6720141
- Compatible type (refers to the same type?) Or differ only in signed, unsigned, const, volatile types (such as const unsigned long * and long*)
- Aggregation types (struct or class) or union type (union) can alias the types they contain (such as int and the struct containing the int (including indirectly included))
- Character types (char *, signed char*, unsinged char*) can alias any type of pointer
- The type of the [C + +] base class (possibly with a const, volatile, and other CV-adornment) can be the type of the alias-derived class
C + + strict-aliasing