Fixed-Size Floating-Point Types I have created my own personal data structure libraries for C and I've re-engineered it about two times now and I've added alot of preprocessor checks and defines concerning OS type and compiler type.

One thing I've wanted to add to my personal libraries is having an informal "standard" fixed-size floating-point types.

#ifndef __float32_t_defined
#   if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#       define __float32_t_defined
        typedef float float32_t TYPE_MODE(__SF__);
#   elif FLT_MANT_DIG==24
#       define __float32_t_defined
        typedef float float32_t;
#   elif DBL_MANT_DIG==24
#       define __float32_t_defined
        typedef double float32_t;
#   endif
#endif

#ifndef __float64_t_defined
#   if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#       define __float64_t_defined
        typedef float float64_t TYPE_MODE(__DF__);
#   elif FLT_MANT_DIG==53
#       define __float64_t_defined
        typedef float float64_t;
#   elif DBL_MANT_DIG==53
#       define __float64_t_defined
        typedef double float64_t;
#   elif LDBL_MANT_DIG==53
#       define __float64_t_defined
        typedef long double float64_t;
#   endif
#endif

#ifndef __floatmax_t_defined
#   if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#       define __floatmax_t_defined
        typedef double floatmax_t TYPE_MODE(__XF__);
#   elif LDBL_MANT_DIG&gt;=64
#       define __floatmax_t_defined
        typedef long double floatmax_t;
#   elif DBL_MANT_DIG&gt;=64
#       define __floatmax_t_defined
        typedef double floatmax_t;
#   else
#       define __floatmax_t_defined
        typedef float floatmax_t;
#   endif
#endif


For Clang and GCC, I use the compiler extension that checks machine mode and sets the type definition to the largest width of the floating point type. I added further type definition checks in the event Clang or GCC are not used.

my main question is that, given the macros in float.h, is checking float size by its mantissa a wise/safe thing to do? If not, what alternative can I take?
float32_t   float64_t

Since the goal is: 


  float32_t and float64_t is that those types are always their fixed size


the macros nearly achieve that.




  is checking float size by its mantissa a wise/safe thing to do? If not, what alternative can I take?


Big caveat: OP's expressed goal is same size, not same encoding.  Two systems may have a 32-bit float, yet different mantissa, exponent range and other properties.  The biggest "safety" concern is assuming same floating point properties with same size.

C allows for a great diversity of implementations though.  The macros accommodate most current compilers well, yet they are not specified to be always typedef 32/64 bit types.

To be clear, checking xxx_MANT_DIG, FLT_RADIX, xxx_MIN_EXP, ... is not sufficient, in general, even though it may be practically sufficient.

It fundamental comes down to:


  what should code do if it encounters a novel implementation?  


I'd go with testing for the usual suspects and expand code when I encounter a true counter case.

#ifndef __float64_t_defined
  #if FLT_RADIX==2 &amp;&amp; DBL_MANT_DIG==53 &amp;&amp; DBL_MIN_EXP == -1021
    #define __float64_t_defined
    typedef double float64_t;
  #elif FLT_RADIX==2 &amp;&amp; FLT_MANT_DIG==53 &amp;&amp; FLT_MIN_EXP == -1021
    #define __float64_t_defined
    typedef float float64_t;
  // Expand list for variants that I have found 
  #elif FLT_RADIX==2 &amp;&amp; DBL_MANT_DIG==TBD &amp;&amp; DBL_MIN_EXP == TBD
  #else
    #error TBD code for float64_t
  #endif
#endif


Note: Code like DBL_MANT_DIG==24 is not even C compliant with FLT_RADIX==2.  DBL_MANT_DIG &gt;= 34 to meet precision requirements.   This looks like a test for a non-real machine.



I recommend 2 additions:

Report fail to typedef right away with #error

#   elif LDBL_MANT_DIG==53
#       define __float64_t_defined
        typedef long double float64_t;

// Add
#   else
#     error TBD code for float64_t

#   endif


With C11 or later, use _Static_assert

_Static_assert(sizeof (float64_t)*CHAR_BIT == 64, "Unexpected `float64_t` size");


With early compilers, see Static assert in C and others.



floatmax_t

After taking advantage or known COMPILER_CLANG, COMPILER_GCC compilers, I'd recommend more conventional code - Simply test for C99 or later.

#ifndef __floatmax_t_defined
#   if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#       define __floatmax_t_defined
        typedef double floatmax_t TYPE_MODE(__XF__);
#   elif (__STDC_VERSION__ &gt;= 199901L)
#       define __floatmax_t_defined
        typedef long double floatmax_t;
#   else
#       define __floatmax_t_defined
        typedef double floatmax_t;
#   endif
#endif




Similar question I posed

Detecting unicorn and dinosaur compilers