是否有一些“好的”方法来检查传递给宏的变量是否为指针? e.g。
#define IS_PTR(x) something
int a;
#if IS_PTR(a)
printf("a pointer we have\n");
#else
printf("not a pointer we have\n");
#endif
这个想法是,这不是运行时而是编译时,如下所示:我们根据变量是否为指针得到不同的代码。所以我希望IS_PTR()以某种方式评估某种常量表达式。我是怎么回事这个想法的呢?
答案 0 :(得分:6)
当您在问题中暗示时,#if
中的预处理器肯定无法观察到。预处理器对类型一无所知,只知道从它们构造的标记和表达式。
C11有一个新功能,可以让你观察特定的指针类型,但不是一般的“指针”。例如,你可以做点什么
#define IS_TOTOP(X) _Generic((X), default: 0, struct toto*: 1)
或者如果您希望宏也适用于数组
#define IS_TOTOPA(X) _Generic((X)+0, default: 0, struct toto*: 1)
已经有一些编译器可以实现这一点,即clang,对于gcc和其他编译器,您已经可以使用一些内置函数模拟该功能,请参阅P99。
答案 1 :(得分:2)
NULL几乎是您唯一可以寻找的东西。无法确定某些东西是否为指针。
答案 2 :(得分:1)
我找到了这个问题的_Generic
解决方案。
警告:可能被触发为假阳性(请参见下面的示例)。
#define __INTERNAL_CHECK_POINTER(x) _Generic((x),\
int: 0, unsigned int: 0,\
long: 0, unsigned long: 0,\
long long: 0, unsigned long long: 0,\
float: 0, double: 0,\
long double: 0, \
default: 1)
/**
* Determines whether the variable has likely a pointer type (but may be triggered false-positive)
*/
#define IS_LIKELY_A_POINTER(x) ((sizeof(x) == sizeof(void*)) && __INTERNAL_CHECK_POINTER(x) ? 1 : 0)
演示:
char c = 0;
printf("c is a pointer: %s\n", IS_LIKELY_A_POINTER(c) ? "Yes" : "No");
unsigned long long l = 0;
printf("l is a pointer: %s\n", IS_LIKELY_A_POINTER(l) ? "Yes" : "No");
double d = 0.0;
printf("d is a pointer: %s\n", IS_LIKELY_A_POINTER(d) ? "Yes" : "No");
unsigned char* cp = 0;
printf("cp is a pointer: %s\n", IS_LIKELY_A_POINTER(cp) ? "Yes" : "No");
struct tm* tp = 0;
printf("tp is a pointer: %s\n", IS_LIKELY_A_POINTER(tp) ? "Yes" : "No");
char ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
printf("ia is a pointer: %s\n", IS_LIKELY_A_POINTER(ia) ? "Yes" : "No");
这将输出:
c is a pointer: No
l is a pointer: No
d is a pointer: No
cp is a pointer: Yes
tp is a pointer: Yes
ia is a pointer: Yes // false-positive!
如果您(像我一样)正在寻找一些日志记录(绘制或不绘制特定变量的*
),而又没有寻找可靠的结果,请尝试这样做,这可能会有所帮助。干杯!
注意:it won't compile under MSVC;使用gcc / clang / etc。而是使用以下条件进行自己的后备实现:
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
// use _Generic code
#else
// ¯\_(ツ)_/¯
#endif
答案 3 :(得分:0)
有一种方法没有误报或否定,但是如果参数既不是数组又不是指针,则编译会中断。
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
/* Is a an array? */
#define is_array(a) (!is_same_type((a), &(a)[0]))
/* Is p a pointer? */
#define is_pointer(p) (!is_array(p))
它需要内置的GCC __builtin_types_compatible_p()
。
行为:
如果p是一个数组,它将计算为0;
否则,如果p是一个指针,它将计算为1;
否则,编译会中断。