Будет ли формат с плавающей точкой зависеть от big-endian и little endian?

Я знаю, что целочисленный формат будет отличаться между машиной big-endian и машиной little-endian, это то же самое для формата float point (IEEE 754)?

4 ответов


спецификация IEEE754 для чисел с плавающей запятой просто не покрывает проблему endianness. Поэтому числа с плавающей запятой могут использовать разные представления на разных машинах, и теоретически даже возможно, что для двух процессоров целочисленная эндианность одинакова, а плавающая точка различна или наоборот.

посмотреть эта статья в Википедии для получения дополнительной информации.


Если у вас есть окно Linux, у вас, вероятно, будет /usr/include/ieee754.ч... (Примечание #ifs)

...
union ieee754_float
  {
    float f;

    /* This is the IEEE 754 single-precision format.  */
    struct
      {
#if     __BYTE_ORDER == __BIG_ENDIAN
        unsigned int negative:1;
        unsigned int exponent:8;
        unsigned int mantissa:23;
#endif                          /* Big endian.  */
#if     __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned int mantissa:23;
        unsigned int exponent:8;
        unsigned int negative:1;
#endif                          /* Little endian.  */
      } ieee;
  ...

проблемы Endianness возникают, как только вы рассматриваете что-то, состоящее из меньших единиц. Способ расположения меньших единиц может измениться.

тогда, если вы заботитесь о вариациях в формате FP, вы должны знать, что IEEE 754 не описывает представление FP (даже если это одна диаграмма предлагает один), и есть по крайней мере еще один вариант, чем тот, который связан с endianness: бит, обозначающий сигнальные субнормалы, интерпретируется по-разному в разных реализация.


вот предложение о том, как вы можете справиться с этим переносным способом независимо от компилятора C. Пожалуйста, расцените это как псевдо-код, он написан здесь и сейчас в моем веб-браузере и не проверял:

#include <stdint.h>
#include <stdio.h>

static uint16_t endian = 0xAABB;
#if ( *(const uint8_t*)&endian == 0xAA )
  #define BIG_ENDIAN
#else
  #define LITTLE_ENDIAN
#endif


#ifdef BIG_ENDIAN

  #define FLOAT_NEGATIVE  0x80000000U
  #define FLOAT_EXPONENT  0x7F800000U
  #define FLOAT_MANTISSA  0x007FFFFFU

  #define SHIFT_NEGATIVE  31U
  #define SHIFT_EXPONENT  23U
  #define SHIFT_MANTISSA   0U

#elif defined LITTLE_ENDIAN

  #define FLOAT_NEGATIVE  0x00000001U
  #define FLOAT_EXPONENT  0x000001FEU
  #define FLOAT_MANTISSA  0xFFFFFE00U

  #define SHIFT_NEGATIVE  0U
  #define SHIFT_EXPONENT  1U
  #define SHIFT_MANTISSA  9U

#endif


typedef union 
{
  float     as_float;
  uint32_t  as_int;

} ieee745_t;



uint32_t  float_negative (ieee745_t ieee);
uint32_t  float_exponent (ieee745_t ieee);
uint32_t  float_mantissa (ieee745_t ieee);



uint32_t  float_negative (ieee745_t ieee)
{
  return (ieee.as_int & FLOAT_NEGATIVE) >> SHIFT_NEGATIVE;
}


uint32_t  float_exponent (ieee745_t ieee)
{
  return (ieee.as_int & FLOAT_EXPONENT) >> SHIFT_EXPONENT;
}


uint32_t  float_mantissa (ieee745_t ieee)
{
  return (ieee.as_int & FLOAT_MANTISSA) >> SHIFT_MANTISSA;
}


int main()
{
  ieee745_t f = {-1.23f};

  printf("%f\n", f.as_float);
  printf("Negative:\t%X\n", float_negative(f) );
  printf("Exponent:\t%X\n", float_exponent(f) );
  printf("Mantissa:\t%X\n", float_mantissa(f) );
  getchar();

  return 0;
}