使用宏进行类型通用编程:确定类型的技巧? [英] Type-generic programming with macros: tricks to determine type?
问题描述
可以在 C 中使用某些类型的泛型函数作为宏,例如:
(x)== sizeof(float)?sqrtf((x)):\
sizeof(x)== sizeof(double)?sqrt(x) (x)):\
sqrtl((x)))
大多数情况下)只要 x
是一个浮点类型。
但是如果我想要一个type-通用宏,可以采用整数类型或指针类型,可能具有相同的大小。有一种聪明的方法来测试宏参数是一个整数还是一个指针?你可以检测一个表达式是一个整型表达式还是一个<$ c
$ c $> char * 表达式,至少在从指针转换到 uintptr_t
的体系结构中定义明确: #define INT_OR_CHARP(X)(((uintptr_t)((X)+1) - (uintptr_t)(X))== 1)
这将检测 X
是否是指向< c $ c> T 与 sizeof(T)> 1
。这不适用于 void *
和其他角落案例。因为 X
会被评估两次,所以您必须注意副作用。为避免整数如果 X
是例如类型 signed int
,您可以替换(X)
with
(1?(X):(uintmax_t)0)
$ c $这保证了如果 X
是一个整数表达式,这将是<$ c>类型的
$ C> uintmax_t型。然后 +1
可能会环绕,但结果总是定义良好,两部分之间的区别始终是 1
。如果 X
是一个指针表达式,那么这是因为任何值为 0
的常量整型表达式也是一个空指针常量。
这总共给出了
<$ c $ (uintptr_t)((1≤(x):(uintmax_t)0)+1) - (uintptr_t)(1≤(X):( uintmax_t)0))== 1)
It's possible to do certain types of type-generic-functions as macros in C, for instance things like:
#define SQRT(x) (sizeof(x) == sizeof(float) ? sqrtf((x)) : \
sizeof(x) == sizeof(double) ? sqrt((x)) : \
sqrtl((x)) )
This works (mostly) as expected as long as x
is a floating point type.
But what if I want a type-generic macro that can take either an integer type or a pointer type, which might have the same size. Is there a clever way to test whether the macro argument is an integer or a pointer? What about an integer versus a floating point type?
You may detect if an expression is an integer expression or a char*
expression, at least on architectures where cast from pointer to uintptr_t
is well defined:
#define INT_OR_CHARP(X) (((uintptr_t)((X)+1) - (uintptr_t)(X)) == 1)
This will detect if X
is a pointer to a type T
with sizeof(T) > 1
. This will not work for void*
and other corner cases. And because X
is evaluated two times you'd have to watch for side effects.
To avoid problems with integer overflow if X
is e.g of type signed int
you may replace (X)
with
(1 ? (X) : (uintmax_t)0)
This guarantees that if X
is an integer expression this will be of type uintmax_t
. The +1
will then perhaps wrap around, but the result is always well defined and the difference between the two parts will always be 1
. If X
is a pointer expression, then this is so because any constant integer expression of value 0
is also a null pointer constant.
In total this gives
#define INT_OR_CHARP(X) (((uintptr_t)((1 ? (X) : (uintmax_t)0)+1) - (uintptr_t)(1 ? (X) : (uintmax_t)0)) == 1)
这篇关于使用宏进行类型通用编程:确定类型的技巧?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!