C
ciccio
Hi,
I was wondering what the main reason is why reinterpret_cast fails to work
as expected when using optimizations. Here is the simple example code which
fail to give the correct result when optimizing.
#include <iostream>
int main() {
long D1 = 0xbcfbc4f0d9b65179;
long D2 = 0xbcfbc4f0d9b65042;
std::cout.setf(std::ios::showbase | std::ios::showpos);
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout.setf(std::ios::scientific,std::ios::floatfield);
std::cout.setf(std::ios::internal,std::ios::adjustfield);
std::cout.precision(20);
double E1 = *reinterpret_cast<double *> (&D1);
double E2 = *reinterpret_cast<double *> (&D2);
std::cout << E1 << "\t" << D1 << std::endl;
std::cout << E2 << "\t" << D2 << std::endl;
return 0;
}
This gives me the output when compiled without optimization flags :
$ g++ foo.cpp
$ ./a.out
-6.16602326664765606567e-15 0xbcfbc4f0d9b65179
-6.16602326664741072993e-15 0xbcfbc4f0d9b65042
while compiled with optimization (-O3)
$ g++ -O3 foo.cpp
$ ./a.out
+0.00000000000000000000e+00 0xbcfbc4f0d9b65179
-6.16602326664741072993e-15 0xbcfbc4f0d9b65042
Although this is only a minor difference here, it becomes ludricous when
doing some simple math operations. (Example code below). Identical results
are obtained when using pointer casts directly, i.e. *(double *) &D1 for
example.
I have read some stuff about aliassing (i.e.
<http://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html>) And I was
wondering if this is the same problem here, eventhough the standard of C++
does not say anything about this (or I just don't find it, sec 5.2.10). If
this is the same problem here, is there a way to solve it without using
the gnu extension?
Thanks
Ugly piece of code which goes completely bizerque when optimizing.
#include <iostream>
#include <cmath>
#include <float.h>
int main(void) {
int A = 0x40000000;
float B = *reinterpret_cast<float *>(&A);
std::cout.setf(std::ios::showbase | std::ios::showpos);
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout.setf(std::ios::scientific,std::ios::floatfield);
std::cout.setf(std::ios::internal,std::ios::adjustfield);
std::cout.precision(20);
for (int i = -3; i <= 3; ++i) {
int C = A+i;
B = *reinterpret_cast<float *>(&C);
std::cout << B << "\t" << A+i << std::endl;
}
int C = -A;
B = *reinterpret_cast<float *>(&C);
std::cout << B << "\t" << C << std::endl;
C = A*2;
B = *reinterpret_cast<float *>(&C);
std::cout << B << "\t" << C << std::endl;
B = 40;
C = *reinterpret_cast<int *>(&B);
std::cout << B << "\t" << C << std::endl;
B = 1;
C = *reinterpret_cast<int *>(&B);
std::cout << B << "\t" << C << std::endl;
B = 0.1;
C = *reinterpret_cast<int *>(&B);
std::cout << B << "\t" << C << std::endl;
long D1 = 0xbcfbc4f0d9b65179;
long D2 = 0xbcfbc4f0d9b65042;
std::cout.setf(std::ios::showbase | std::ios::showpos);
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout.setf(std::ios::scientific,std::ios::floatfield);
std::cout.setf(std::ios::internal,std::ios::adjustfield);
std::cout.precision(20);
double E1 = *reinterpret_cast<double *> (&D1);
double E2 = *reinterpret_cast<double *> (&D2);
double E3 = fabs(E1-E2);
long D3 = *reinterpret_cast<long *>(&E3);
std::cout << E1 << "\t" << D1 << std::endl;
std::cout << E2 << "\t" << D2 << std::endl;
std::cout << E3 << "\t" << D3 << "\t" << D1-D2 << std::endl;
std::cout << E3/E2 << "\t" << E3/E2/DBL_EPSILON << std::endl;
unsigned long F = D3;
F = F << 1;
F = F >> 53;
std:: cout << F << std::endl;
long GF = 0x42270feeda10f98e;
long G = GF + 512;
long HF = 0x413cd26c40d51215;
double H = (*reinterpret_cast<double *>(&G)) - (*reinterpret_cast<double
*>(&GF));
double I = H/(*reinterpret_cast<double *> (&HF));
std::cout << GF << " " << G << " " << H << " " << I << " " <<
I/DBL_EPSILON << std::endl;
return 0;
}
I was wondering what the main reason is why reinterpret_cast fails to work
as expected when using optimizations. Here is the simple example code which
fail to give the correct result when optimizing.
#include <iostream>
int main() {
long D1 = 0xbcfbc4f0d9b65179;
long D2 = 0xbcfbc4f0d9b65042;
std::cout.setf(std::ios::showbase | std::ios::showpos);
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout.setf(std::ios::scientific,std::ios::floatfield);
std::cout.setf(std::ios::internal,std::ios::adjustfield);
std::cout.precision(20);
double E1 = *reinterpret_cast<double *> (&D1);
double E2 = *reinterpret_cast<double *> (&D2);
std::cout << E1 << "\t" << D1 << std::endl;
std::cout << E2 << "\t" << D2 << std::endl;
return 0;
}
This gives me the output when compiled without optimization flags :
$ g++ foo.cpp
$ ./a.out
-6.16602326664765606567e-15 0xbcfbc4f0d9b65179
-6.16602326664741072993e-15 0xbcfbc4f0d9b65042
while compiled with optimization (-O3)
$ g++ -O3 foo.cpp
$ ./a.out
+0.00000000000000000000e+00 0xbcfbc4f0d9b65179
-6.16602326664741072993e-15 0xbcfbc4f0d9b65042
Although this is only a minor difference here, it becomes ludricous when
doing some simple math operations. (Example code below). Identical results
are obtained when using pointer casts directly, i.e. *(double *) &D1 for
example.
I have read some stuff about aliassing (i.e.
<http://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html>) And I was
wondering if this is the same problem here, eventhough the standard of C++
does not say anything about this (or I just don't find it, sec 5.2.10). If
this is the same problem here, is there a way to solve it without using
the gnu extension?
Thanks
Ugly piece of code which goes completely bizerque when optimizing.
#include <iostream>
#include <cmath>
#include <float.h>
int main(void) {
int A = 0x40000000;
float B = *reinterpret_cast<float *>(&A);
std::cout.setf(std::ios::showbase | std::ios::showpos);
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout.setf(std::ios::scientific,std::ios::floatfield);
std::cout.setf(std::ios::internal,std::ios::adjustfield);
std::cout.precision(20);
for (int i = -3; i <= 3; ++i) {
int C = A+i;
B = *reinterpret_cast<float *>(&C);
std::cout << B << "\t" << A+i << std::endl;
}
int C = -A;
B = *reinterpret_cast<float *>(&C);
std::cout << B << "\t" << C << std::endl;
C = A*2;
B = *reinterpret_cast<float *>(&C);
std::cout << B << "\t" << C << std::endl;
B = 40;
C = *reinterpret_cast<int *>(&B);
std::cout << B << "\t" << C << std::endl;
B = 1;
C = *reinterpret_cast<int *>(&B);
std::cout << B << "\t" << C << std::endl;
B = 0.1;
C = *reinterpret_cast<int *>(&B);
std::cout << B << "\t" << C << std::endl;
long D1 = 0xbcfbc4f0d9b65179;
long D2 = 0xbcfbc4f0d9b65042;
std::cout.setf(std::ios::showbase | std::ios::showpos);
std::cout.setf(std::ios::hex,std::ios::basefield);
std::cout.setf(std::ios::scientific,std::ios::floatfield);
std::cout.setf(std::ios::internal,std::ios::adjustfield);
std::cout.precision(20);
double E1 = *reinterpret_cast<double *> (&D1);
double E2 = *reinterpret_cast<double *> (&D2);
double E3 = fabs(E1-E2);
long D3 = *reinterpret_cast<long *>(&E3);
std::cout << E1 << "\t" << D1 << std::endl;
std::cout << E2 << "\t" << D2 << std::endl;
std::cout << E3 << "\t" << D3 << "\t" << D1-D2 << std::endl;
std::cout << E3/E2 << "\t" << E3/E2/DBL_EPSILON << std::endl;
unsigned long F = D3;
F = F << 1;
F = F >> 53;
std:: cout << F << std::endl;
long GF = 0x42270feeda10f98e;
long G = GF + 512;
long HF = 0x413cd26c40d51215;
double H = (*reinterpret_cast<double *>(&G)) - (*reinterpret_cast<double
*>(&GF));
double I = H/(*reinterpret_cast<double *> (&HF));
std::cout << GF << " " << G << " " << H << " " << I << " " <<
I/DBL_EPSILON << std::endl;
return 0;
}