假设我想要一个适用于任何类型的 C 宏。 我正在使用 GCC 编译器 (>= 4.6) 并且可以使用 GNU99 宏。
//code...
any_type_t *retVal = function_that_runs_very_long_time(a, b, &&c, **d, &e, *f);
//other code...
TIMER 的宏用法可以像这样看
//code...
any_type_t *retVal =
TIMER(
function_that_runs_very_long_time(a, b, &&c, **d, &e, *f),
"TIMING FOR VALUE <%d, %d>", a, b
);
//other code...
因此 TIMER 必须返回给定函数的值并打印其运行持续时间。
具有 void
返回类型的函数存在问题。
我显然可以有两个宏,如 TIMER_TYPE 和 TIMER_VOID,但我想使用单个 one to time 函数和任何返回值。
感谢您的建议。
这个 TIMER 宏的编辑示例
#define TIMER(expr, fmt_msg, ...) \
({ \
struct timeval before, after; \
uint64_t time_span; \
int time_span_sec, time_span_usec; \
gettimeofday(&before, NULL); \
typeof(expr) _timer_expr__ = (expr); \ // <- static if?
gettimeofday(&after, NULL); \
time_span = (after.tv_sec * 1000000 + after.tv_usec) \
- (before.tv_sec * 1000000 + before.tv_usec); \
time_span_sec = time_span / 1000000; \
time_span_usec = time_span % 1000000; \
TRACE(fmt_msg "\n%s : %d.%d seconds", \
#expr, time_span_sec, time_span_usec, ...); \
_timer_expr__; \
})
最佳答案
多么有趣的问题,荣誉!
经过几次实验,我找到了一个使用 __builtin_types_compatible_p
and __builtin_choose_expr
的解决方案GCC 的内在特性。
__builtin_types_compatible_p
引用 GCC 手册:
Built-in Function:
int __builtin_types_compatible_p (type1, type2)
You can use the built-in function
__builtin_types_compatible_p
to determine whether two types are the same.This built-in function returns
1
if the unqualified versions of the typestype1
andtype2
(which are types, not expressions) are compatible,0
otherwise. The result of this built-in function can be used in integer constant expressions.This built-in function ignores top level qualifiers (e.g.,
const
,volatile
). For example,int
is equivalent toconst int
.
下面是我们如何检查“void
ness”的方法。
#define __type_is_void(expr) __builtin_types_compatible_p(typeof(expr), void)
__builtin_choose_expr
Built-in Function:
type __builtin_choose_expr (const_exp, exp1, exp2)
You can use the built-in function
__builtin_choose_expr
to evaluate code depending on the value of a constant expression. This built-in function returnsexp1
ifconst_exp
, which is an integer constant expression, is nonzero. Otherwise it returnsexp2
.This built-in function is analogous to the
? :
operator in C, except that the expression returned has its type unaltered by promotion rules. Also, the built-in function does not evaluate the expression that is not chosen. For example, ifconst_exp
evaluates to true,exp2
is not evaluated even if it has side-effects.If
exp1
is returned, the return type is the same asexp1
's type. Similarly, ifexp2
is returned, its return type is the same asexp2
.
所以 __builtin_choose_expr
intrinsic 类似于在编译时评估的“静态开关”。
准备
我没有在此处粘贴您的 TIMER
宏,但我认为它能够将其拆分为两个版本:一个用于 void expr
,另一个用于其余版本。这里只是计算表达式并产生相同类型结果的 stub 。
#define __DO(expr) \
({ typeof(expr) __ret; __ret = (expr); __ret; })
#define __DO_VOID(expr) \
(void) (expr)
天真的解决方案
现在我们可以根据表达式的实际类型在两个实现之间静态切换。但实际上天真的解决方案不起作用,请参见下文。
#define DO(expr) \
__builtin_choose_expr(__type_is_void(expr), \
__DO_VOID(expr), \
__DO(expr)) # won't work
尝试通过 void 表达式编译此代码会出现以下错误:
test.c:28:9: error: variable or field ‘__ret’ declared void
test.c:28:9: error: void value not ignored as it ought to be
尽管选择了 __DO_VOID
,但是 __DO
会产生错误。手册中描述了此行为:
... the unused expression (
exp1
orexp2
depending on the value ofconst_exp
) may still generate syntax errors. This may change in future revisions.
工作解决方案
技巧是用一些非 void 值替换原始的 void expr
以便能够编译 __DO
情况(当 expr
无效)。
#define __expr_or_zero(expr) __builtin_choose_expr(__type_is_void(expr), 0, (expr))
#define DO(expr) \
__builtin_choose_expr(__type_is_void(expr), \
__DO_VOID(expr), \
__DO(__expr_or_zero(expr))) # works fine!
就是这样!这是 Ideone 上的完整源代码:http://ideone.com/EFy4pE
关于c - 如何在编译时检查 `typeof` 的 void 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12453165/