如何在C23中用_Generic实现支持右值的IS_POINTER(p)宏?
用_Generic实现支持右值指针的IS_POINTER宏
原宏的问题在于尝试取右值指针的地址,而C标准不允许对右值取地址。可以通过以下方式改写宏,避免直接取P的地址:
#define IS_POINTER(P) \ _Generic( (P), \ typeof(&*P): 1, \ default: 0 \ )
原理说明
- 对于指针类型(包括左值指针和右值指针,比如
int* p或&i):*P会得到指针指向的左值,&*P的类型与P本身的类型完全一致,因此_Generic会匹配typeof(&*P)分支,返回1。 - 对于数组类型(比如
int a[1]):*a是数组首元素的左值,&*a的类型是元素指针(如int*),与数组本身的类型(int[1])不匹配,因此进入default分支,返回0。 - 对于非指针非数组的基本类型(比如
int i):&*i的类型是对应指针类型(如int*),与原类型(int)不匹配,进入default分支,返回0。
测试验证
#include <stdio.h> #define IS_POINTER(P) \ _Generic( (P), \ typeof(&*P): 1, \ default: 0 \ ) int main() { int i; int a[1]; int *p = &i; void (*pf)(void) = NULL; printf("IS_POINTER(a) = %d\n", IS_POINTER(a)); // 输出0,正确 printf("IS_POINTER(p) = %d\n", IS_POINTER(p)); // 输出1,正确 printf("IS_POINTER(&i) = %d\n", IS_POINTER(&i)); // 输出1,正确 printf("IS_POINTER(i) = %d\n", IS_POINTER(i)); // 输出0,正确 printf("IS_POINTER(pf) = %d\n", IS_POINTER(pf)); // 输出1,正确 return 0; }
内容的提问来源于stack exchange,提问作者Paul J. Lucas
相关产品推荐
相关产品推荐

