C预处理器:重新定义宏,宏重载

huangapple go评论95阅读模式
英文:

C preprocessor: redefine macro, macro overload

问题

以下是您要翻译的内容:

以下代码有一个由FLAG控制的宏,用于在编译时使用func1或func2。我想通过使用“FLAG”宏(定义/取消定义)在main()上执行的方式来使其在编译时在这两个函数之间切换。这只是一个示例,用法将跨多个文件。

我的问题是,这只执行func1(),因为预处理器已将符号分配给func_wrapper,而我没有更改它。另外,如果我执行#undef func_wrapper,就需要通过添加更多代码来重新定义它。

我的问题是,是否可以在不每次重新定义func_wrapper的情况下实现这一点。就像是在未定义FLAG时,预处理器再次经过宏并重新检查已定义的内容一样。

我希望得到类似以下代码的结果:

#include "functions.h"
#include "functions2.h"

#define FLAG

#ifdef FLAG
#define func_wrapper func1
#endif

#ifndef FLAG
#define func_wrapper func2
#endif

int main(){

	func_wrapper();

	#undef FLAG

	func_wrapper();

}

并且运行结果与以下类似:

...
//与之前相同
...
int main(){

	func_wrapper();

	#undef FLAG
	#ifndef FLAG
    #undef func_wrapper
	#define func_wrapper func2
	#endif

	func_wrapper();

}
英文:

The following code has a FLAG controlled macro to use func1 or func2 when compiling. I want to make it switch between the 2 function when compiling by using the "FLAG" macro (defining/undefining) as it's done on main(). This is just a sample/example, the usage will be across multiple files.

My question is that this only executes func1() as the preprocessor have assigned the symbol to func_wrapper and I'm not changing it. Also if if do #undef func_wrapperit will be required to redefine it by adding more code.

My question is if it is possible to achieve that without having the redefine of func_wrapper each time. It something like making the preprocessor do another pass over the macros when the FLAG is undefined and check again the defines that where defined under.

I want to get something that looks like the following code:

#include "functions.h"
#include "functions2.h"

#define FLAG

#ifdef FLAG
#define func_wrapper func1
#endif


#ifndef FLAG
#define func_wrapper func2
#endif


int main(){

	func_wrapper();


	#undef FLAG

	func_wrapper();

}

and runs like the follwing one:

...
//same as previous one
...
int main(){

	func_wrapper();


	#undef FLAG
	#ifndef FLAG
    #undef func_wrapper
	#define func_wrapper func2
	#endif

	func_wrapper();

}

答案1

得分: 3

if it is possible to achieve that without having the redefine of func_wrapper each time

不行。

making the preprocessor do another pass over the macros

你必须手动输入另一个遍历。

#include "functions.h"
#include "functions2.h"

#define FLAG

#ifdef FLAG
#define func_wrapper func1
#else
#define func_wrapper func2
#endif

int main() {
    func_wrapper();
    #undef FLAG
    #undef func_wrapper
    #ifdef FLAG
    #define func_wrapper func1
    #else
    #define func_wrapper func2
    #endif
    func_wrapper();
}

你可以把这部分放在一个头文件中。

// resolve_flag.h
#ifdef func_wrapper
#undef func_wrapper
#endif
#ifdef FLAG
#define func_wrapper func1
#else
#define func_wrapper func2
#endif
// main.h
#include "functions.h"
#include "functions2.h"

#define FLAG
#include "resolve_flag.h"

int main() {
    func_wrapper();
    #undef FLAG
    #include "resolve_flag.h"
    func_wrapper();
}

但也许可以使用运行时和一些全局状态来实现:

bool flag = 0;
void func_wrapper(void) {
    flag ? func1() : func2();
}

int main() {
    func_wrapper();
    flag = 1;
    func_wrapper();
}
英文:

> if it is possible to achieve that without having the redefine of func_wrapper each time

No.

> making the preprocessor do another pass over the macros

You have to type out that another pass.

#include "functions.h"
#include "functions2.h"

#define FLAG

#ifdef FLAG
#define func_wrapper func1
#else
#define func_wrapper func2
#endif

int main() {
    func_wrapper();
    #undef FLAG
#undef func_wrapper
#ifdef FLAG
#define func_wrapper func1
#else
#define func_wrapper func2
#endif
    func_wrapper();
}

You can put that in a header.

// resolve_flag.h
#ifdef func_wrapper
#undef func_wrapper
#endif
#ifdef FLAG
#define func_wrapper func1
#else
#define func_wrapper func2
#endif

// main.h
#include "functions.h"
#include "functions2.h"

#define FLAG
#include "resolve_flag.h"

int main() {
    func_wrapper();
    #undef FLAG
    #include "resolve_flag.h"    
    func_wrapper();    
}

But maybe just use runtime and some global state:

bool flag = 0;
void func_wrapper(void) {
     flag ? func1() : func2();
}

int main() {
     func_wrapper();
     flag = 1;
     func_wrapper();
}

答案2

得分: 1

Here's the translated content from your provided text:

如果 func_wrapper 最初不是宏,您可以重新定义它为其他内容,只需一行源代码:

#include "functions.h"
#include "functions2.h"

// 默认定义。我们可以使用宏让某些调用者直接调用func2
static inline void func_wrapper() {
  func1();
}
// #define func_wrapper func2


int main()
{
    func_wrapper();    // 调用func1
    #define func_wrapper func2
    func_wrapper();    // 调用func2

    #undef func_wrapper  // 现在它又成为func1的别名
}

这相当丑陋,看起来相当巧妙,而且失去了FLAG的单独名称,这个名称可能具有一些有用的语义意义。我不建议这样做。

如果函数实际上需要参数,您的包装器必须将它们传递下去。

您实际上不需要CPP,如果可以使用嵌套函数,这是GNU C的扩展。这在GCC中可以工作,但在clang中不行(Godbolt)。

// 默认定义
static inline void func_wrapper() {
  func1();
}

int main()
{
    func_wrapper();

    static inline void func_wrapper(){ func2(); }  // 遮蔽了全局定义

    func_wrapper();
}

这甚至更糟,因为包装器的定义会使您在其中使用它的函数变得混乱。

英文:

If func_wrapper is not originally a macro, you can redefine it to something else with only one line of source:

#include "functions.h"
#include "functions2.h"

// default definition.  We can use macros to have some callers call func2 directly
static inline void func_wrapper() {
  func1();
}
// #define func_wrapper func2


int main()
{
    func_wrapper();    //  call func1
    #define func_wrapper func2
    func_wrapper();    //  call func2

    #undef func_wrapper  // now it's back to an alias for func1
}

This is rather ugly and seems pretty hacky, and loses the separate name of FLAG which presumably has some useful semantic meaning. I wouldn't recommend doing this.

If the function actually takes args, your wrapper would have to pass them on.


You actually don't need CPP at all if you can use nested functions, a GNU C extension. This works in GCC but not clang (Godbolt).

// default definition
static inline void func_wrapper() {
  func1();
}

int main()
{
    func_wrapper();

    static inline void func_wrapper(){ func2(); }  // shadows the global definition

    func_wrapper();
}

This is even worse, since the wrapper definition clutters up the function you're using it inside.

huangapple
  • 本文由 发表于 2023年5月11日 16:37:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76225671.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定