我有#define映射标识符(函数名)到新名称,如下所示:
#define A doStuff
这部分我无能为力,我必须访问“A”,因为实际的标识符(这里是doStuff)可能会改变(这不在我的控制之下)。现在引用的符号(doStuff)可能存在也可能不存在,我想在前一种情况下调用该函数。对于普通函数名称,我可以轻松地测试它:
#ifdef doStuff
doStuff();
#endif
然而,受限于宏名称,天真地做同样的事情:
#ifdef A
A();
#endif
由于定义了名称“A”而给出了错误,而“doStuff”则没有。我想检查宏解析的名称是否存在,基本上是:
#if defined(the-content-of-A)
但我不能让它发挥作用。
所以我的问题是:有没有办法检查是否定义了宏所代表的标识符?如果是的话,该怎么办?如果不是,是否有解决方法的常见模式?
虽然我不认为这是C或C ++特定的,但我想指出我需要一些适用于C ++中定义为“extern C”的标识符的东西。解决方案必须独立于平台。
很抱歉,如果之前有人询问过,我无法找到它,也无论是谷歌还是SO。
答案 0 :(得分:2)
定义标识符(函数,对象)是在预处理之后发生的事情,因此您无法在预处理期间确定是否稍后定义函数。
您可以做的解决方法是始终使用函数定义宏:
void A();
#define A_SUPPLIED
然后对此进行测试:
#ifdef A_SUPPLIED
...
#endif
答案 1 :(得分:1)
嗯,不。
我认为您真正的问题是您不了解宏之间的区别(使用#define
引入预处理器并使用文本替换进行扩展,然后在编译的后期实际编译结果)和标识符(这是预处理器无法测试的编译时结构)。
我说这是因为唯一的方法
#ifdef doStuff
doStuff();
#endif
如果doStuff()
是宏,则将按照您声称的方式运行。如果doStuff()是标识符(例如,函数或变量的名称),它将不起作用。
例如,在C ++中
#include <iostream>
void doStuff() {std::cout << "Hello\n";}
int main()
{
#ifdef doStuff
doStuff();
#else
std::cout << "Bye\n";
#endif
}
将打印Bye
而不是Hello
。这是因为函数定义不生成宏,#ifdef
未检测到。
关于唯一的方法是将宏定义为函数的伴侣
void DoStuff();
#define DoStuff_DEFINED
#ifdef DoStuff_Defined
DoStuff();
#else
ComplainBitterly(); /* assumes ComplainBitterly() exists of DoStuff_DEFINED is not defined */
#endif
答案 2 :(得分:1)
无论是否存在宏,您都无法确定纯C中是否存在标识符(您的#ifdef doStuff
示例实际上不起作用)。这是因为在宏扩展时,编译器只是进行文本替换;它不知道定义了什么符号。理想的方法是让您的库标题显示A_IS_PRESENT
宏或类似内容,您可以#ifdef
离开此处。
但是,如果这不是一个选项,则可以使用特定于平台的扩展。例如,在Linux上,您可以定义一个弱符号,然后确定它是否被真实交易覆盖:
#ifdef __cplusplus
extern "C" {
#endif
// Define a dummy function; if A is not present we will make A an alias of this
int A_surrogate() {}
#ifdef __cplusplus
}
#endif
// The alias attribute makes 'A' equivalent to 'A_surrogate'. The weak attribute
// means that if some other definition exists, that one takes precedence.
int __attribute__((weak, alias("A_surrogate"))) A();
int is_A_present() {
// Was A in fact overridden?
return &A != &A_surrogate;
}