Test the following code:
#include <stdio.h>
#include <stdlib.h>
main()
{
const char *yytext="0";
const float f=(float)atof(yytext);
size_t t = *((size_t*)&f);
printf("t should be 0 but is %d\n", t);
}
Compile it with:
gcc -O3 test.c
The GOOD output should be:
"t should be 0 but is 0"
But with my gcc 4.1.3, I have:
"t should be 0 but is -1209357172"
The gcc option -O enables different levels of optimization. Use -O0 to disable them and use -S to output assembly.
GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff. As compared to -O , this option increases both compilation time and the performance of the generated code.
you can get an idea of optimization using the option -fdump-tree-optimized with gcc . and you'll get an optimised file. you cannot run the code but using that you can get an idea of optimization . dont forget to include -O2 or -O3 or some other level.
The compiler optimizes to reduce the size of the binary instead of execution speed. If you do not specify an optimization option, gcc attempts to reduce the compilation time and to make debugging always yield the result expected from reading the source code.
Use the compiler flag -fno-strict-aliasing.
With strict aliasing enabled, as it is by default for at least -O3, in the line:
size_t t = *((size_t*)&f);
the compiler assumes that the size_t* does NOT point to the same memory area as the float*. As far as I know, this is standards-compliant behaviour (adherence with strict aliasing rules in the ANSI standard start around gcc-4, as Thomas Kammeyer pointed out).
If I recall correctly, you can use an intermediate cast to char* to get around this. (compiler assumes char* can alias anything)
In other words, try this (can't test it myself right now but I think it will work):
size_t t = *((size_t*)(char*)&f);
In the C99 standard, this is covered by the following rule in 6.5-7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:73)
a type compatible with the effective type of the object,
a qualified version of a type compatible with the effective type of the object,
a type that is the signed or unsigned type corresponding to the effective type of the object,
a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
a character type.
The last item is why casting first to a (char*) works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With