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
?