有趣的C宏

时间:2013-08-06 10:24:03

标签: c macros

假设我在C中有一个名为FOO的函数宏。还有两个名为BAR1BAR2的宏,它们基本上是同一个宏的两种口味。我想编写一个宏BAR,以便在使用BAR1前调用FOO的函数扩展为BAR,否则调用BAR2 。例如:

void func1(void)
{
    FOO();
    ...
    BAR();
}

等同于

void func1(void)
{
    FOO();
    ...
    BAR1();
}

虽然这个功能:

void func2(void)
{
    BAR();
}

等同于

void func2(void)
{
    BAR2();
}

我想避免在运行时引入全局变量或进行额外的检查。这甚至可能吗?

2 个答案:

答案 0 :(得分:3)

简短回答:不。 C预编译器对函数限制一无所知,因此即使您设法根据需要修改BAR宏,也不会局限于当前函数。

现在,如果您愿意,可以向BAR宏添加一些检查。并且可以编写这些检查以在编译时解决,因此不会产生运行时开销。

例如:

extern char _sentinel_[2];

#define FOO() char _sentinel_;

#define BAR() if (sizeof(_sentinel_) == 1) BAR1() else BAR2()

诀窍是变量_sentinel_的查找将解析全局变量或本地变量,具体取决于FOO()的使用。由于if中的条件是编译器常量,编译器将优化其他分支。

答案 1 :(得分:2)

我尝试使用goto的操作失败,因为在未使用FOO()时,BAR()缺少跳转标签。但是,不要害怕,我已经提出了更严重的黑客攻击。

您可以使用#include代替FOO()BAR()的宏。这将允许您绝对控制代码的扩展方式。

/* FOO file */
#define BAR_IS_BAR2
/* whatever code FOO needs to do */

/* BAR file */
#ifdef BAR_IS_BAR2
    BAR2();
    #undef BAR_IS_BAR2
#else
    BAR1();        
#endif

/*...in you source code...*/
void func1 () {
    #include "FOO"
    /*...*/
    #include "BAR"
}

void func2 () {
    #include "BAR"
}