C 用宏包装函数调用

C 用宏包装函数调用,c,c-preprocessor,C,C Preprocessor,是否可以仅用宏包装函数调用 当我努力的时候 #define foo(x) bar(x) 它包装了函数调用和定义 我知道使用链接器包装函数,但在这种情况下,我不能使用此解决方案 让我们假设一些代码 #define foo(x) bar(z) int foo(int z){ //some code } int bar(int x){ //some code } int function(){ int a = foo(2); } 我想要int a=foo(2);预处理后变为int a=bar

是否可以仅用宏包装函数调用

当我努力的时候

#define foo(x) bar(x)
它包装了函数调用和定义

我知道使用链接器包装函数,但在这种情况下,我不能使用此解决方案

让我们假设一些代码

#define foo(x) bar(z)

int foo(int z){
//some code
}

int bar(int x){
//some code
}

int function(){
int a = foo(2);
}
我想要int a=foo(2);预处理后变为int a=bar(2)。 目前我只收到“重新定义”错误


编辑:我的示例显示了我想要实现的目标,但在实际代码中,我必须通过cmake文件将此宏放到项目中,并且我也不能修改目标文件中的源代码。很抱歉没有在前面提到它。

不确定这是否是您想要的,但您可以尝试将宏放在函数声明之后。所以

foo(...){}
bar(...){}
#ifdef REPLACE_FOO
#define foo(x) bar(x)
#endif
main(){
    foo(1);
}

这是因为预处理器不关心替换哪个字符串。 它还替换了原始函数定义
foo
,这意味着函数
定义了两次

您应该能够通过以下方式解决此问题:

#if !defined(foo)
int foo(int z){
   //some code
}
#endif

当然,这取决于您实际想要做什么。

使用undef来管理宏的生命周期,而不是处理不知道宏存在的代码部分

int foo(int z){
//some code
}

int bar(int x){
//some code
}

int function(){
    #define foo(x) bar(z)
    int a = foo(2);
    #undef foo
}
这个技巧扩展到了诸如标题选项之类的内容,通常包括Windows.h之类的内容,标题的定义取决于标题外部的定义,如下所示:

#define WIN32_LEAN_AND_MEAN // used in ifdef checks to not define/include rarely used stuff
#define NO_STRICT // used to allow HANDLE types to be used as void * without type errors
#define NO_MINMAX // used to avoid errors because MIN/MAX are already defined
#include <Windows.h>
#定义WIN32_LEAN_和_MEAN//在ifdef检查中用于不定义/包括很少使用的内容
#定义NO_STRICT//用于允许将句柄类型用作void*,而不会出现类型错误
#定义NO_MINMAX//用于避免错误,因为已经定义了MIN/MAX
#包括
这会污染宏的作用域,这些宏在标头完成解析后没有任何用处,因此您可以在include之后通过取消对它们的定义进行清理:

#define WIN32_LEAN_AND_MEAN // used in ifdef checks to not define/include rarely used stuff
#define NO_STRICT // used to allow HANDLE types to be used as void * without type errors
#define NO_MINMAX // used to avoid errors because MIN/MAX are already defined
#include <Windows.h>
#undef NO_MINMAX 
#undef NO_STRICT 
#undef WIN32_LEAN_AND_MEAN
#定义WIN32_LEAN_和_MEAN//在ifdef检查中用于不定义/包括很少使用的内容
#定义NO_STRICT//用于允许将句柄类型用作void*,而不会出现类型错误
#定义NO_MINMAX//用于避免错误,因为已经定义了MIN/MAX
#包括
#未定义最小值
#未定义不严格
#未定义WIN32\u精益\u和\u平均值

这使得阅读您的代码的人,尤其是C的初学者,更容易知道这些是选项,在包含发生后没有任何用处。这还允许您执行有趣的类似C++的行为,例如基于include之前定义的定义进行模板化,而不存在多次包含头的冲突。

它包装了函数调用和定义
--什么?它所做的只是将字符串
foo(x)
替换为
bar(x)
。预处理器不处理定义,这是在编译器阶段。你能更具体地说明你想要实现什么吗?如果你想在某个地方禁止宏扩展,你只需将宏放在括号中,例如
int(foo)(void)
。预处理器处理文本,它对C语法或语义一无所知。当它看到
foo
后跟括号时,它会替换它。@JensGustedt,我猜这是为了用外部单元测试文件中定义的备用存根来隐藏函数调用?对吗?我忘了这样的解决方案。我必须在cmake文件中定义宏,这样它的作用域就是整个项目。我编辑的解决方案行得通吗?我编辑了我的文章,提供了更多的细节。通常,如果
foo
有一个
\define
,那么定义foo(x)bar(z)会有一个事先测试的好处,但这会带来一些奇怪的麻烦,比如如果宏已经定义了,那么您必须创建另一个宏来跟踪您正在重新定义宏的事实,并且可能需要将其重新定义回之前的状态。避免这种情况的一种方法是生成一个guid,并用下划线替换“-”,并在guid前面加上u,这样实际上不太可能发生冲突,但牺牲了短宏的好处;我喜欢假设,如果我的宏短于3个字符,除了我之外,没有人应该使用它;许多头定义了许多短宏,如MIN和MAX或N,它们是理想的宏名称;几乎没有一个宏使用长度小于3个字符的小写宏,因此foo/bar/baz/a/b/c应该是真正安全的短期作用域宏。您应该在定义#ifdef宏之前对其进行测试,如果是,则在使用中对其进行取消定义。其中一个恼人的罪魁祸首是CreateWindow;您可能希望在类内创建方法CreateWindow,但Windows.h根据是否定义unicode来定义它。在这种情况下,我会取消创建窗口。