<tgmath.h>头文件
<tgmath.h>头文件包括<math.h>头文件和<complex.h>头文件,并定义了一些泛型宏。
如果实现支持ISO/IEC 9899:2024标准,宏__STDC_VERSION_TGMATH_H__将扩展为值为202311L的整数常量表达式。
<math.h>头文件和<complex.h>头文件中的函数与<tgmath.h>头文件中的泛型宏之间存在多对一对应关系(many-to-one correspondence)。使用泛型宏会调用对应函数,函数类型由泛型形参(generic parameters)对应的实参类型决定。如果实参类型与所选函数的形参类型不兼容,其行为是未定义的。与标准库中的其它函数式宏一样,为使对应的普通函数可用,<tgmath.h>头文件中的泛型宏可以被抑制。
<math.h>头文件、<complex.h>头文件中无f(float)或者l(long double)后缀的函数中,一些函数存在一个或者多个double类型的形参;这些函数(<math.h>头文件中将结果舍入到更窄类型的函数以及modf函数除外。)都存在一个对应的泛型宏(type-generic macro)。函数概要(function synopsis)中对应实数类型为double类型的形参为泛型形参(generic parameters)。
某些十进制浮点类型函数不存在不带后缀的对应版本。在这些存在d64后缀的函数中,有些函数存在一个或者多个类型为_Decimal64类型的形参。对于这类函数(decodedecd64、encodedecd64、decodebind64、encodebind64函数除外。)都存在一个对应的泛型宏。函数概要(function synopsis)中对应实数类型为_Decimal64类型的形参为泛型形参(generic parameters)。
泛型宏泛型形参的对应实参中,如果某个实参是标准浮点类型(standard floating type),另一个实参是十进制浮点类型(decimal floating type),其行为是未定义的。
<math.h>头文件中将结果舍入到更窄类型的函数宏除外,使用泛型宏会调用一个函数,该函数的泛型形参对应的实数类型由实参类型按以下方式确定:
- 如果任一实参为十进制浮点类型,整数类型实参视为_Decimal64类型,否则视为double类型。
- 如果函数仅存在一个泛型形参,所确定类型是该泛型形参的对应实参的类型;即对于只有一个泛型形参的泛型宏,实参是什么类型,就调用对应类型的函数。
- 如果函数存在两个泛型形参,所确定类型是这两个泛型形参的对应实参执行常用算术转换(usual arithmetic conversions)后所得结果的类型;即对于存在两个泛型形参的泛型宏,先根据常用算术转换规则将两个实参统一成一个共同类型,然后根据共同类型调用对应的函数。
- 如果函数存在三个及三个以上泛型形参,所确定类型通过反复执行常用算术转换得到:首先对前两个泛型形参的对应实参执行常用算术转换,然后将结果类型与下一个泛型形参的对应实参执行常用算术转换,依此类推,直至对所有泛型形参的对应实参都执行完常用算术转换为止。也就是说,对于存在三个及三个以上泛型形参的泛型宏,从左到右逐个统一类型,先将前两个统一成一个共同类型,然后用这个共同类型和第三个统一......直至全部处理完,最后根据最终得到的类型调用对应的函数。
以泛型宏fabs为例:
|
|
输出:
TYPE(fabs(1)): double type
TYPE(fabs(1.0)): double type
TYPE(fabs(1.0f)): float type
TYPE(fabs(1.0L)): long double type
如果根据泛型形参的对应实参所确定的函数在<math.h>头文件和<complex.h>头文件中均未定义,其行为是未定义的。
对于<math.h>头文件中无后缀的函数以及<complex.h>头文件中的同名函数(存在字母前缀c。),对应的泛型宏是相同的,与<math.h>头文件中的那个函数同名。泛型宏fabs是个例外,其对应的函数分别是fabs(<math.h>头文件)和cabs(<complex.h>头文件)。
上述函数与泛型宏的对应关系如下表所示:
如果泛型宏中至少一个泛型形参对应的实参是复数,将调用复数函数;如果泛型宏中没有泛型形参对应的实参是复数,将调用实数函数。
以泛型宏sin为例:
|
|
输出:
sin(1.0) = 0.84
sin(1.0+1.0i) = 1.30+0.63i