首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >__tg_promote在tgmath.h中做什么?

__tg_promote在tgmath.h中做什么?
EN

Stack Overflow用户
提问于 2014-05-14 16:50:05
回答 1查看 349关注 0票数 1

我正在查看tgmath.h,并试图准确地了解它如何根据输入值的大小选择正确的函数。

特殊的酱汁似乎是这个__tg_promote宏,但我越深入挖掘,这个谜题就越深。有没有人对__tg_promote的实际工作有一个简短的回答?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-14 17:39:49

在clang的tgmath.h实现中,__tg_promote实际上是一个函数,而不是宏。定义可以找到这里

代码语言:javascript
复制
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的整数类型;对自身的浮点类型。)当您查看接下来的几个宏时,这一点很清楚:

代码语言:javascript
复制
#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),因为添加floatdouble (推广int的结果)会给出double__tg_promote3是相似的。

报头的其余部分由重载的函数定义组成,这些函数委托给各自的普通C函数:

代码语言:javascript
复制
// 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

代码语言:javascript
复制
#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)),这正是我们想要的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23660611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档