Hi
in the following source code, I think swap32() itself should be ok,
while I am unsure if swapd() and swapd_wrap() invoke undefined
behavior.
The doubt is reinforced by gcc -O3 giving strange results with the
latter.
Any comments?
Specifically, consider a function that receives a double parameter and
returns a
double parameter like:
double func( double d )
{
// return d after whatever bit manipulations imaginable
}
that is used like:
double d1=SOME_VALUE, d2;
d2 = func(d1);
Will the parameter passing and the assignment in this code have to
preserve the
bit pattern? Even if d1 or d2 are unnormalized or NaN?
thanks for your attention
Herbert
/*
swapd.c
programs compiled with gcc 3.3.3 with
gcc -std=c99 -O3 -pedantic -W -Wall swapd.c -o swapd
and
gcc -std=c99 -pedantic -W -Wall swapd.c -o swapd
yield different results
*/
#include <stdio.h>
#include <stdint.h>
// reverse order of bytes in 32bit word, no undefined behavior, right?
void swap32( int32_t *in,
int32_t *out )
{
char *p_in = (char*)in;
char *p_out = (char*)out;
p_out[0] = p_in[3];
p_out[1] = p_in[2];
p_out[2] = p_in[1];
p_out[3] = p_in[0];
}
int32_t swap32_wrap( int32_t in )
{
int32_t ret;
swap32( (void*)&in, (void*)&ret );
return ret;
}
double swapd( double d )
{
double ret;
int32_t *p_out = (void*)&ret;
int32_t *p_in = (void*)&d;
swap32( &p_in[1], &p_out[0] );
swap32( &p_in[0], &p_out[1] );
return ret;
}
double swapd_wrap( double d )
{
double ret;
int32_t *p_out = (void*)&ret;
int32_t *p_in = (void*)&d;
p_out[0] = swap32_wrap( p_in[1] );
p_out[1] = swap32_wrap( p_in[0] );
return ret;
}
int main(void)
{
double d_init = 1.23456e7;
double d = 0;
double ds = 0;
double ds2;
fprintf( stderr, "sizeof(double) = %d:\n", sizeof(double) );
d = d_init;
ds = swapd( d );
ds2 = swapd( ds );
fprintf( stderr, "swapd():\n" );
fprintf( stderr, "d = %.8e\n", d );
fprintf( stderr, "ds = %.8e\n", ds );
fprintf( stderr, "ds2 = %.8e\n", ds2 );
fprintf( stderr, "ds2 - d = %.8e\n", ds2-d );
d = d_init;
ds = swapd_wrap( d );
ds2 = swapd_wrap( ds );
fprintf( stderr, "swapd_wrap():\n" );
fprintf( stderr, "d = %.8e\n", d );
fprintf( stderr, "ds = %.8e\n", ds );
fprintf( stderr, "ds2 = %.8e\n", ds2 );
fprintf( stderr, "ds2 - d = %.8e\n", ds2-d );
/*
with -03 prints:
sizeof(double) = 8:
swapd():
d = 1.23456000e+07
ds = 2.69795606e-315
ds2 = 1.23456000e+07
ds2 - d = 0.00000000e+00
swapd_wrap():
d = 1.23456000e+07
ds = 1.16542096e-314
ds2 = -1.99574670e+00
ds2 - d = -1.23456020e+07
*/
/*
without -03 prints:
sizeof(double) = 8:
swapd():
d = 1.23456000e+07
ds = 2.69795606e-315
ds2 = 1.23456000e+07
ds2 - d = 0.00000000e+00
swapd_wrap():
d = 1.23456000e+07
ds = 2.69795606e-315
ds2 = 1.23456000e+07
ds2 - d = 0.00000000e+00
*/
return 0;
}