function with side effects ignored

Andrew Haley aph@redhat.com
Tue Sep 29 17:18:00 GMT 2009


Matthew Woehlke wrote:
> Using gcc-4.3.2-7.x86_64 (Fedora 10).
> 
> I have these functions:
> 
> void my_ntoh_float(float *f)
> {
>   int p = (int*)f;
>   *p = ntohl(*p);
> }
> 
> float my_get_float(const void * buffer)
> {
>   float value;
>   memcpy(&val, buffer, sizeof(float);
>   my_ntoh_float(&value);
>   return value;
> }
> 
> ...which is compiled (-O2) like so:
> <my_get_float+0>:   push   %ebp
> <my_get_float+1>:   mov    %esp,%ebp
> <my_get_float+3>:   sub    $0x10,%esp
> <my_get_float+6>:   mov    0x8(%ebp),%eax
> <my_get_float+9>:   mov    (%eax),%eax
> <my_get_float+11>:  mov    %eax,-0x4(%ebp)
> <my_ntoh_float+0>:  mov    -0x4(%ebp),%eax
> <my_get_float+17>:  flds   -0x4(%ebp)
> <my_ntoh_float+6>:  ror    $0x8,%ax
> <my_ntoh_float+10>: ror    $0x10,%eax
> <my_ntoh_float+13>: ror    $0x8,%ax
> <my_ntoh_float+17>: mov    %eax,-0x4(%ebp)
> <my_get_float+34>:  leave
> <my_get_float+35>:  ret
> 
> Now, obviously this is not going to work correctly; the result of the
> call to my_ntoh_float is effectively discarded. Is the bug in the code,
> or in gcc? In either case, is there a way (besides dropping
> optimizations) to fix this that doesn't involve non-portable code?

It's in your code.  You're accessing an object (p) as an incompatible type.
See C99, Section 6.3.2.3 for all the details.

Do this:

float my_ntoh_float(float f)
{
  union
  {
    int i;
    float f;
  } u;

  u.f = f;
  u.i = ntohl(u.i);
  return u.f;
}

float my_get_float(const void * buffer)
{
  float value = *(float*)buffer;
  value = my_ntoh_float(value);
  return value;
}


Which generates this:

my_get_float:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$4, %esp
	movl	8(%ebp), %eax
	movl	(%eax), %eax
	bswap %eax
	movl	%eax, -4(%ebp)
	flds	-4(%ebp)
	leave
	ret

Andrew.



More information about the Gcc-help mailing list