检测宏是否无效

时间:2018-03-27 11:02:09

标签: c macros c-preprocessor c99

我试图在编译时检测宏是否为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?

3 个答案:

答案 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表达式中。