_Generic可以成为一个函数吗?或_Generic可以与__attribute __((清理))一起使用?

时间:2014-12-24 15:33:45

标签: c generics c11

给出以下源代码:

#include <stddef.h>
#include <sys/types.h>
#include <dirent.h>

static inline void closedirp(DIR **p) {
    if (*p)
        closedir(*p);
}

#define auto_cleanup(resource) _Generic((resource),     \
    DIR **: closedirp,                  \
        )(resource)

int main() {
#ifdef GENERIC
    __attribute__((cleanup(auto_cleanup))) DIR * t2 = NULL;
    t2 = opendir("/tmp");
#else
    __attribute__((cleanup(closedirp))) DIR * t1 = NULL;
    t1 = opendir("/tmp");
#endif
}

它编译并运行时没有泄漏,没有定义。但是,当定义GENERIC时,编译失败:

$ gcc foo.c -DGENERIC
foo.c: In function ‘main’:
foo.c:16:2: error: cleanup argument not a function
  __attribute__((cleanup(auto_cleanup))) DIR * t2 = NULL;
  ^

这是_Generic毫无意义的使用,但是我想扩展它并处理许多类型的资源来自动清理。

1 个答案:

答案 0 :(得分:1)

_Generic不是函数,而是启动主表达式的关键字。

但是在这里,你似乎更偏向于错误的轨道:auto_cleanup是一个宏。像宏这样的函数具有如果没有()之后没有扩展它们的特殊性。所以在这里你只需要为编译的后续阶段保留标识符auto_cleanup。但是这个标识符并未声明为后续阶段的任何内容。

总结:

  • 如果使用正确,您的宏将在编译的早期阶段以文本方式替换
  • 然后后面的阶段会看到一个_Generic表达式,并决定采用_Generic表达式的哪个分支
  • 只有那个分支才能生存下来#34;并编译在代码的那部分

在所有这些中,没有涉及可用于gcc的cleanup扩展的函数或函数指针。