_Generic 可以是一个函数吗?或者 _Generic 可以与 __attribute__((cleanup)) 一起使用吗?

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

最佳答案

_Generic 不是一个函数,而是一个开始主表达式的关键字。

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

总结:

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

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

关于_Generic 可以是一个函数吗?或者 _Generic 可以与 __attribute__((cleanup)) 一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27639149/

相关文章:

c - exit 和 quick_exit 的区别

c++ - C 和 C++ 的某些标准之间的差异

c - 如何使用 __STDC_VERSION__ 检查 -std=c1x 是否正在使用?

c - 为子函数中的结构指针分配空间

c - 如何将 char* 拆分为 C 中的整数表

c++ - 编译器如何知道字符串文字(const char*)已经存在于数据存储器中?

java - 如何在 java 中编写一个接受两个相同类型参数的泛型方法?

java - 无法使用不同类型的参数实现接口(interface)

c++ - 提高 fgetc 性能

Java 8 和广义目标类型推断