【问题标题】:Can _Generic be a function? Or can _Generic be used with __attribute__((cleanup))?_Generic 可以是一个函数吗?或者 _Generic 可以与 __attribute__((cleanup)) 一起使用吗?
【发布时间】:2014-12-24 15:33:44
【问题描述】:

给定以下源代码:

#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 的毫无意义的使用,但是我想扩展它并处理多种类型的资源以自动清理。

【问题讨论】:

    标签: c generics c11


    【解决方案1】:

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

    但在这里,您似乎走错了路:auto_cleanup 是一个宏。像宏这样的函数有一个特殊性,即如果后面没有(),它们不会被扩展。所以在这里你只需保留标识符auto_cleanup 用于编译的后期阶段。但是这个标识符并没有被声明为这些后续阶段的任何东西。

    总结一下:

    • 如果使用正确,您的宏将在编译的早期阶段以文本形式替换
    • 随后的阶段将看到 _Generic 表达式并决定采用该 _Generic 表达式的哪个分支
    • 只有该分支才能“存活”并在该部分代码中编译

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

    【讨论】:

      猜你喜欢
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 1970-01-01
      • 2011-08-15
      • 2018-02-16
      • 2020-06-30
      相关资源
      最近更新 更多