C23 introduced a number of floating point types, including but not limited to:
_Float32_Float32x_Float32_t
I am unsure of the differences, such as:
- Are they keywords, or are they type aliases, or something else?
- Are they distinct types, or can they be aliases for
float? - What is the minimum range and precision of these types?
- Are they required to be IEEE-754-compliant (or IEC 60559)?
- Is
floatobsoleted by_Float32or other types?
The same questions apply to _Float64 vs double, and _Float128 vs long double.
Only
_FloatN_ttypes (e.g._Float32_t) are aliases from the<math.h>header. All the other types are required to be distinct, and their names are keywords. (See H.5.1 [Keywords])All of the types fall into one of four categories (see below). Choose between them as follows:
float,double, andlong double, if you are satisfied with the very lenient requirements of these types__STDC_IEC_60559_BFP__is defined, which makes them stricterfloatanddoubleif you are okay with them being the same type1)_FloatNif you need a specific IEC 60559 type with exactly N bits_FloatNxif you need an extended IEC 60559 type with minimum N precision_FloatN_tif you don't need IEC 60559 types, and you are not satisfied with the minimum requirements forfloatanddouble1) On architectures without a double-precision FPU,
floatanddoublemight be the same size (e.g. Arduino). Use other types (e.g._Float64_toverdouble) if you want software emulation of double-precision instead.Standard floating types
float,double, andlong doubleare collectively called standard floating types. Their representation is implementation-defined, but there are some requirements nonetheless:doublemust be able to represent anyfloat, andlong doublemust represent anydouble__STDC_IEC_60559_BFP__is defined,floatanddoubleare represented like_Float32and_Float64floatFLT_DECIMAL_DIG≥ 6FLT_MIN≤ 10-37FLT_MAX≥ 1037doubleDBL_DECIMAL_DIG≥ 10DBL_MIN≤ 10-37DBL_MAX≥ 1037long doubleLDBL_DECIMAL_DIG≥ 10LDBL_MIN≤ 10-37LDBL_MAX≥ 1037Usually,
floatanddoubleare binary32 and binary64 types respectively, andlong doubleis binary128, an x87 80-bit extended floating-point number, or represented same asdouble.See C23 Standard - E [Implementation limits]
Interchange floating types
_Float32,_Float64etc. are so called interchange floating types. Their representation must follow the IEC 60559 interchange format for binary floating-point numbers, such as binary32, binary64, etc. Any_FloatNtypes must be exactly N bits wide.The types
_Float32and_Float64might not exist, unless the implementation defines__STDC_IEC_60559_BFP__and__STDC_IEC_60559_TYPES__. If so:_Float32exists, andfloathas the same size and alignment as it (but is a distinct type)_Float64exists, anddoublehas the same size and alignment as it (but is a distinct type)_FloatN(typically_Float128) exists iflong doubleis a binaryN type with N > 64See C23 Standard - H.2.1 [Interchange floating types].
Extended floating types
_Float32x,_Float64x, etc. are so called extended floating types (named after IEC 60559 extended precision). Unlike their interchange counterparts, they only have minimum requirements for their representation, not exact requirements. A_FloatNxmust have ≥ N bits of precision, making it able to represent N-bit integers with no loss.These types might not exist, unless the implementation defines
__STDC_IEC_60559_TYPES__. If so:_Float32xexists if__STDC_IEC_60559_BFP__is defined, and may have the same format asdouble(but is a distinct type)_Float64xexists if__STDC_IEC_60559_DFP__is defined, and may have the same format aslong double(but is a distinct type)_Float128xoptionally existsSee C23 Standard - H.2.3 [Extended floating types]
Aliases
_Float32_t,_Float64_t, etc. are aliases for other floating types, so that:_FloatN_thas at least the range and precision of the corresponding real floating type (e.g._Float32_thas the at least the range and precision of_Float32if it exists)_Float64_tcan represent_Float32_t)See C23 Standard - H.11 [Mathematics <math.h>].