Commit 2fc589293066d934bfdfbdff320574e1ea2f5c8a

Authored by Florian Forster
1 parent 170b042c

Implement the register <-> float conversion without breaking aliasing rules.

The previous implementation dereferenced a type-puned pointer, which is
illegal according to ANSI C. Some newer versions of GCC will complain
about this. This implementation uses "memcpy" to avoid this problem.
Showing 1 changed file with 9 additions and 9 deletions
src/modbus.c
@@ -1988,20 +1988,20 @@ uint8_t get_byte_from_bits(const uint8_t *src, int address, int nb_bits) @@ -1988,20 +1988,20 @@ uint8_t get_byte_from_bits(const uint8_t *src, int address, int nb_bits)
1988 /* Read a float from 4 bytes in Modbus format */ 1988 /* Read a float from 4 bytes in Modbus format */
1989 float modbus_read_float(const uint16_t *src) 1989 float modbus_read_float(const uint16_t *src)
1990 { 1990 {
1991 - float real;  
1992 - uint32_t ireal = (src[1] << 16) + src[0];  
1993 - real = *((float *)&ireal); 1991 + float r = 0.0f;
  1992 + uint32_t i;
1994 1993
1995 - return real; 1994 + i = (((uint32_t) src[1]) << 16) + src[0];
  1995 + memcpy (&r, &i, sizeof (r));
  1996 + return (r);
1996 } 1997 }
1997 1998
1998 /* Write a float to 4 bytes in Modbus format */ 1999 /* Write a float to 4 bytes in Modbus format */
1999 void modbus_write_float(float real, uint16_t *dest) 2000 void modbus_write_float(float real, uint16_t *dest)
2000 { 2001 {
2001 - uint32_t ireal; 2002 + uint32_t i = 0;
2002 2003
2003 - ireal = *((uint32_t *)&real);  
2004 - /* Implicit mask 0xFFFF */  
2005 - dest[0] = ireal;  
2006 - dest[1] = ireal >> 16; 2004 + memcpy (&i, &real, sizeof (i));
  2005 + dest[0] = (uint16_t) i;
  2006 + dest[1] = (uint16_t) (i >> 16);
2007 } 2007 }