编译时检查是否存在枚举成员

时间:2020-09-19 19:15:17

标签: c gcc clang

这个问题是理论上的,我手头没有一个现实的例子,这只是我几次遇到的东西,想知道是否有通用的解决方法。

假设我有一个程序与一个暴露枚举的库接口。根据库的版本,某些枚举成员可能存在,而有些可能不存在。 我想根据它们的存在来编译条件代码。我知道库版本上还有其他最佳实践,例如#if-ing。但是,在某些情况下,仅检查枚举的存在是最干净,最简单的。

我看到的一些代码在声明枚举时遵循此约定:

enum foo {
    foo_bar = 1
#define foo_bar foo_bar
    foo_baz = 2
#define foo_baz foo_baz
    ...
};

这使我可以使用#ifdef foo_XXX来检查enum foo成员的存在。但是,它并不总是可用。

有什么方法可以测试当前词法范围内“名称”的定义?我专门针对枚举,但是也可以接受更通用的答案:)我认为没有“标准C”方式可以这样做,因此,仅适用于GCC或仅适用于clang的解决方案。

编辑:经过一番思考,我实现了一个名为__builtin_compile_time_ifdef的小型GCC“内置”。它接受名称作为 string ,如果定义了名称,则返回1。它工作正常。剩下的问题是,在我所知的所有提供条件评估的构造中(__builtin_choose_expr_Generic),仍会检查未评估的分支中是否有未声明的名称。因此,如果我想使用名称(而不只是检查是否存在),就不能使用。

2 个答案:

答案 0 :(得分:1)

我从未听说过这种功能,GNU cpp manual没有描述任何类似的功能。确实,在the description of #if中,他们明确指出enum常量未被识别。

而且,这样的功能将与预处理器的总体设计方案相反。 cpp不应尝试将其输入解析为C;它仅查找预处理器指令和宏以进行扩展。确实,人们经常使用cpp来预处理其他语言的代码(例如,汇编语言)。如果预处理器试图识别enum关键字并解析其语法,则其他语言可能会以完全不同的方式使用字符串enum的其他语言将其混淆,这与人们的期望相反。因此,我认为没有人会创造您想要的东西。

这是人们应该以其他方式解决的问题(您在已经知道的评论中提到)。

答案 1 :(得分:1)

为了以后参考,我写了a PoC plugin来说明我的需要:

#include <stdio.h>

enum x {
    v1 = 1,
    // v2 = 2
};

void main(void) {
    enum x v1 = (enum x)__builtin_lookup_name("v1", (enum x)-1);
    enum x v2 = (enum x)__builtin_lookup_name("v2", (enum x)-1);

    printf("%d %d\n", v1, v2); // prints "1 -1"
}
相关问题