我正在查看tgmath.h
并试图准确了解它如何根据输入值的大小选择正确的函数。
特殊的酱料似乎是这个__tg_promote
宏,但我越深入这个谜题就越深。有人对__tg_promote
实际操作有一个简短的回答吗?
我正在查看tgmath.h
并试图准确了解它如何根据输入值的大小选择正确的函数。
特殊的酱料似乎是这个__tg_promote
宏,但我越深入这个谜题就越深。有人对__tg_promote
实际操作有一个简短的回答吗?
在 clang 的实现中,tgmath.h
它__tg_promote
实际上是一个函数,而不是宏。定义可以在这里找到。
typedef void _Argument_type_is_not_arithmetic;
static _Argument_type_is_not_arithmetic __tg_promote(...)
__attribute__((__unavailable__,__overloadable__));
static double _TG_ATTRSp __tg_promote(int);
static double _TG_ATTRSp __tg_promote(unsigned int);
static double _TG_ATTRSp __tg_promote(long);
static double _TG_ATTRSp __tg_promote(unsigned long);
static double _TG_ATTRSp __tg_promote(long long);
static double _TG_ATTRSp __tg_promote(unsigned long long);
static float _TG_ATTRSp __tg_promote(float);
static double _TG_ATTRSp __tg_promote(double);
static long double _TG_ATTRSp __tg_promote(long double);
static float _Complex _TG_ATTRSp __tg_promote(float _Complex);
static double _Complex _TG_ATTRSp __tg_promote(double _Complex);
static long double _Complex _TG_ATTRSp __tg_promote(long double _Complex);
这是一个具有多个重载的函数(通常在 C 中不允许)并且没有定义,这很好,因为它实际上从未被调用过!__tg_promote
仅用于确定应将数字类型提升为的类型。(整数类型到double
; 浮点类型到它们自己。)当您查看接下来的几个宏时,这一点很清楚:
#define __tg_promote1(__x) (__typeof__(__tg_promote(__x)))
#define __tg_promote2(__x, __y) (__typeof__(__tg_promote(__x) + \
__tg_promote(__y)))
#define __tg_promote3(__x, __y, __z) (__typeof__(__tg_promote(__x) + \
__tg_promote(__y) + \
__tg_promote(__z)))
该__tg_promote
函数没有被调用,因为它发生在特定于编译器的__typeof__
宏中。__tg_promote1
宏只是在括号内展开为其参数的提升类型。__tg_promote2
扩展为添加其参数的提升类型的两个值时将产生的类型(再次用括号括起来)。例如,__tg_promote2(0.0f, 0)
将是(double)
,因为添加 afloat
和 a double
(提升的结果int
)给出 a double
。__tg_promote3
类似。
头文件的其余部分由委托给相应普通 C 函数的函数的重载定义组成:
// atan2
static float
_TG_ATTRS
__tg_atan2(float __x, float __y) {return atan2f(__x, __y);}
static double
_TG_ATTRS
__tg_atan2(double __x, double __y) {return atan2(__x, __y);}
static long double
_TG_ATTRS
__tg_atan2(long double __x, long double __y) {return atan2l(__x, __y);}
例如,为了能够调用,atan2(1.0f, 1)
我们需要能够委托给__tg_atan2(double, double)
. 这是__tg_promote2
确定当我们有一个float
参数和一个int
参数时,两者都应该转换为double
:
#define atan2(__x, __y) __tg_atan2(__tg_promote2((__x), (__y))(__x), \
__tg_promote2((__x), (__y))(__y))
所以在这种情况下__tg_promote2((__x), (__y))
,(double)
我们得到__tg_atan2((double)(__x), (double)(__y))
,这正是我们想要的。