Search code examples
floating-pointlanguage-lawyerc99fixed-width

Where are the fixed width floating types?


What are the C standard fixed width floating point types and where are they defined?

From MISRA-C:2004, Rule 6.3:
typedefs that indicate size and signedness should be used in place of the basic numerical types.

The MISRA-C:2004, Rule 6.3 quotes that ISO (POSIX) typedefs are:

typedef          char   char_t;
typedef signed   char   int8_t;
typedef signed   short  int16_t;  
typedef signed   int    int32_t;
typedef signed   long   int64_t;
typedef unsigned char   uint8_t;
typedef unsigned short  uint16_t;
typedef unsigned int    uint32_t;
typedef unsigned long   uint64_t;
typedef          float  float32_t;
typedef          double float64_t;
typedef long     double float128_t;

At my company we are using C-99.
IAR Electronic Workbench, version 8.4

We are at MISRA-C:2004 because they voted not to upgrade MISRA, which would require create a validation test protocol and running the protocol.

Platform is ARM Cortex M running MicroCOS operating system.

Here are the detailed questions:

  1. What are the typedefs for the fixed width floating point types?
  2. What include file are they inside (or are they defined as default by the compiler)?

Solution

  • C standard fixed width floating point types are not defined

    • C floating point (FP) goals are designed to embrace variations and many implementations.

    • MISRA FP goals are to restrict variety.

    Fixed size FP types do not result in uniform bit encoding nor other consistent FP properties. They have limited usefulness in C - hence they are not part of the C standard or library.


    Fall-back

    Code could use below and a _Static_assert (since C11) or a C99 substitute.

    typedef      float  float32_t;
    typedef      double float64_t;
    typedef long double float128_t;
    
    _Static_assert(sizeof(float32_t)*CHAR_BIT == 32, "float 32");
    _Static_assert(sizeof(float64_t)*CHAR_BIT == 64, "float 64");
    _Static_assert(sizeof(float128_t)*CHAR_BIT == 128, "float 128");
    

    Further notes

    Compliant C may not have all 32, 64, 128 bit FP types, thus unable to define all float32_t, float64_t, float128_t.

    2 different Compliant C implementations may have a 32-bit FP types, but different encoding. Compare float32 vs. CCSI resulting in different range, precision and sub-normal support.

    2 different Compliant C implementations may have a 32-bit FP types with the same encoding, but different endians, even if their integer endians agree.

    Rule 6.3 (advisory): typedefs that indicate size and signedness should be used in place of the basic numerical types.: that goal "helps to clarify the size of the storage" and not much else.

    Rule 1.5 (advisory): Floating-point implementations should comply with a defined floating-point standard. is particularly difficult to achieve. Even if an implementation uses the same FP encoding as IEEE 754, C allows the operations enough implementation defined behavior to differ from IEE 754.

    Ideally, in C, an implementation that conforms to IEEE 754 defines __STDC_IEC_559__. Yet proving and maintaining conformity is challenging enough that an implementation may forego defining __STDC_IEC_559__ as it may only be 99.999% conforming.