使用C预处理器确定当前范围?

Ric*_*III 5 scope global-variables static-variables clang nested-function

我正在使用C/Objective-C开发一个应用程序(请不要使用C++,我已经有了解决方案),我遇到了一个有趣的用例.

因为clang不支持嵌套函数,所以我的原始方法不起作用:

#define CREATE_STATIC_VAR(Type, Name, Dflt) static Type Name; __attribute__((constructor)) void static_ ## Type ## _ ## Name ## _init_var(void) { /* loading code here */ }
Run Code Online (Sandbox Code Playgroud)

这段代码可以用GCC编译好,但由于clang不支持嵌套函数,我得到一个编译错误:

预期';' 在宣言结束时.

所以,我找到了一个适用于Clang函数内部变量的解决方案:

#define CREATE_STATIC_VAR_LOCAL(Type, Name, Dflt) static Type Name; ^{ /* loading code here */ }(); // anonymous block usage
Run Code Online (Sandbox Code Playgroud)

但是,我想知道是否有办法利用宏连接来为情况选择合适的方法,例如:

#define CREATE_STATIC_VAR_GLOBAL(Type, Name, Dflt) static Type Name; __attribute__((constructor)) void static_ ## Type ## _ ## Name ## _init_var(void) { /* loading code here */ }
#define CREATE_STATIC_VAR_LOCAL(Type, Name, Dflt) static Type Name; ^{ /* loading code here */ }(); // anonymous block usage

#define SCOPE_CHOOSER LOCAL || GLOBAL
#define CREATE_STATIC_VAR(Type, Name, DFLT) CREATE_STATIC_VAR_ ## SCOPE_CHOOSER(Type, Name, Dflt)
Run Code Online (Sandbox Code Playgroud)

显然,结束实现并不一定就是这样,但类似的东西就足够了.

我试图使用__builtin_constant_p__func__,但因为__func__不是一个编译时间常数,这是行不通的.

我也试过使用__builtin_choose_expr,但这似乎不适用于全球范围.

我在文档中还缺少其他东西吗?看起来这应该是相当容易做的事情,然而,我似乎无法弄明白.

注意:我知道我可以简单地键入CREATE_STATIC_VAR_GLOBALCREATE_STATIC_VAR_LOCAL代替乱用宏连接,但这是我试图突破编译器的限制.我也知道我可以使用C++并立即解决这个问题,但这不是我的目标.

Quu*_*one 3

#define SCOPE_CHOOSER LOCAL || GLOBAL
#define CREATE_STATIC_VAR(Type, Name, DFLT) CREATE_STATIC_VAR_ ## SCOPE_CHOOSER(Type, Name, Dflt)
Run Code Online (Sandbox Code Playgroud)

这里最大的困难是 C 预处理器通过文本替换来工作,所以即使你弄清楚如何做SCOPE_CHOOSER你想做的事,你最终也会得到一个看起来像这样的宏扩展

CREATE_STATIC_VAR_LOCAL || GLOBAL(Type, Name, Dflt);
Run Code Online (Sandbox Code Playgroud)

没有办法让预处理器在替换过程中“不断折叠”宏扩展;事物唯一被“折叠”的时候是它们出现在#if表达式中的时候。所以你唯一的希望(模轻微挥手)是找到一个可以在函数内部和外部工作的单一结构。

您能在这里详细解释一下最终目标吗?我不认为你可以用 加载变量的初始值__attribute__((constructor)),但也许有一种方法可以在第一次进入函数体时加载初始值......或者在编译时将这些变量的所有地址注册到全局列表中 -时间并有一个__attribute__((constructor))​​遍历该列表的函数......或者这些方法的一些混杂。我心里没有任何具体的想法,但如果你提供更多信息,也许会出现一些东西。

编辑: 我认为这对您也没有帮助,因为它不是预处理器技巧,但这里是一个常量表达式,它将在函数范围内计算为 0,在全局范围内计算为 1。

#define AT_GLOBAL_SCOPE __builtin_types_compatible_p(const char (*)[1], __typeof__(&__func__))
Run Code Online (Sandbox Code Playgroud)

但是,请注意我说的是“评估”而不是“扩展”。这些构造是编译时的,而不是预处理时的。