我试图在编译时检测宏是否为void
。我知道宏定义了一个类型,但它可以是任何类型(结构,指针,数组,函数指针等),我需要弄清楚这个类型是否是void
。到目前为止,我已设法使其适用于整数和浮点类型(在所讨论的宏下面命名为type
)。
#define void +1
#define unsigned +0
#define signed +0
#define long +0
#define short +0
#define const +0
#define volatile +0
#if (type == void)
# warning "is void"
#else
# warning "is not void"
#endif
#undef volatile
#undef const
#undef short
#undef long
#undef signed
#undef unsigned
#undef void
代码基于此说明:https://gcc.gnu.org/onlinedocs/cpp/If.html#If
在一般情况下(在所有类型中)有没有办法在编译时检测void?
答案 0 :(得分:2)
定义名称与保留字一致的宏是未定义的行为。
以下是如何正确执行此操作。
#if !defined(T) // just for testing
#define T void
#endif
#define is_void 0
#define is_int 1
#define is_char 2
#define is_double 3
#define cat(x,y) cat2(x,y)
#define cat2(x,y) x##y
#if cat(is_, T) == is_void // use the test
#error "type is void" // or do something useful
#else
#error "type is not void" // or do something useful
#endif
测试:
> gcc -E test.c -DT=void
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
test.c:14:2: error: #error "type is void"
#error "type is void"
^~~~~
> gcc -E test.c -DT=int
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
test.c:16:2: error: #error "type is not void"
#error "type is not void"
^~~~~
这当然只适用于具有语法标识符的令牌,因此您无法检查int*
或类似的任何内容。
答案 1 :(得分:1)
由于您指的是gcc
的文档,您可以使用其内置函数:
#define IS_VOID(x) __builtin_types_compatible_p(x, void)
答案 2 :(得分:1)
使用C11和静态断言的替代方法:
#define IS_VOID(x) _Static_assert(_Generic((x*)0, \
void*: 0, \
default: 1), \
"void type " #x " detected")
...
#define T void
...
IS_VOID(T);
gcc上的编译器消息:
错误:静态断言失败:&#34;检测到无效类型T&#34;
代码使用void*
代替void
,因为void
是一个不完整的类型,因此不能存在于_Generic表达式中。