C 检测宏是否无效

C 检测宏是否无效,c,macros,c-preprocessor,c99,C,Macros,C Preprocessor,C99,我试图在编译时检测宏是否为void。我知道宏定义了一个类型,但它可以是任何类型(结构、指针、数组、函数指针等),我需要确定该类型是否为void。到目前为止,我已经设法使它适用于整数和浮点类型(下面的宏名为type) 代码基于以下描述: 在一般情况下(在所有类型中),是否有一种方法可以在编译时检测void?由于您参考的是gcc的文档,因此可以使用其内置项: #define IS_VOID(x) __builtin_types_compatible_p(x, void) 由于您参考的是gcc的文档

我试图在编译时检测宏是否为
void
。我知道宏定义了一个类型,但它可以是任何类型(结构、指针、数组、函数指针等),我需要确定该类型是否为
void
。到目前为止,我已经设法使它适用于整数和浮点类型(下面的宏名为
type

代码基于以下描述:


在一般情况下(在所有类型中),是否有一种方法可以在编译时检测void?

由于您参考的是
gcc
的文档,因此可以使用其内置项:

#define IS_VOID(x) __builtin_types_compatible_p(x, void)

由于您参考的是
gcc
的文档,因此可以使用其内置项:

#define IS_VOID(x) __builtin_types_compatible_p(x, void)

定义名称与保留字一致的宏是未定义的行为

下面是如何正确地做到这一点

#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"
  ^~~~~
>gcc-E test.c-DT=void
#1“测试c”
# 1 ""
# 1 ""
#1“测试c”
测试c:14:2:错误:#错误“类型无效”
#错误“类型为空”
^~~~~
>gcc-E测试.c-DT=int
#1“测试c”
# 1 ""
# 1 ""
#1“测试c”
测试c:16:2:错误:#错误“类型不为空”
#错误“类型不为空”
^~~~~

当然,这只适用于语法标识符的标记,因此您不能检查
int*
或任何类似的内容。

使用与保留字一致的名称定义宏是未定义的行为

下面是如何正确地做到这一点

#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"
  ^~~~~
>gcc-E test.c-DT=void
#1“测试c”
# 1 ""
# 1 ""
#1“测试c”
测试c:14:2:错误:#错误“类型无效”
#错误“类型为空”
^~~~~
>gcc-E测试.c-DT=int
#1“测试c”
# 1 ""
# 1 ""
#1“测试c”
测试c:16:2:错误:#错误“类型不为空”
#错误“类型不为空”
^~~~~

当然,这只适用于语法标识符的标记,因此您无法检查
int*
或任何类似内容。

使用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上的编译器消息:

错误:静态断言失败:“检测到无效类型T”


代码使用
void*
而不是
void
,因为
void
是一个不完整的类型,因此不能存在于_泛型表达式中。

使用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上的编译器消息:

错误:静态断言失败:“检测到无效类型T”


代码使用
void*
而不是
void
,由于
void
是一个不完整的类型,因此不能存在于泛型表达式中。

什么是
type
,您真的不应该为基本类型定义标记。您的
\define
都会导致未定义的行为
\define type const unsigned long int
您希望发生什么
类型
并且您确实不应该为基本类型定义标记。您的
定义
都会导致未定义的行为
#定义类型const unsigned long int