如何使用以前的定义重新定义宏
假设我有以下宏:
#define xxx(x) printf("%s\n",x);
现在在某些文件中我想使用该宏的“增强”版本而不更改其名称。新版本探索了原始版本的功能并做了更多的工作。
#define xxx(x) do { xxx(x); yyy(x); } while(0)
这当然会给我重新定义警告,但为什么我得到“xxx”未在此范围内声明?我应该如何正确定义它?
编辑:根据此 http://gcc.gnu。 org/onlinedocs/gcc-3.3.6/cpp/Self_002dReferential-Macros.html 应该是可以的
Suppose I have the following macro:
#define xxx(x) printf("%s\n",x);
Now in certain files I want to use an "enhanced" version of this macro without changing its name. The new version explores the functionality of the original version and does some more work.
#define xxx(x) do { xxx(x); yyy(x); } while(0)
This of course gives me redefition warning but why I get 'xxx' was not declared in this scope? How should I define it properly?
EDIT: according to this http://gcc.gnu.org/onlinedocs/gcc-3.3.6/cpp/Self_002dReferential-Macros.html it should be possible
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不可能。宏可以使用其他宏,但它们使用的是扩展时可用的定义,而不是定义时的定义。 C 和 C++ 中的宏不能递归,因此新宏中的 xxx 不会扩展并被视为函数。
Not possible. Macros can use other macros but they are using the definition available at expand time, not definition time. And macros in C and C++ can't be recursive, so the xxx in your new macro isn't expanded and is considered as a function.
自引用宏根本不起作用:
http:// gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros
如果您正在使用 C++,则可以使用模板函数和命名空间获得相同的结果:
Self-referential macros do not work at all:
http://gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros
If you're working on C++ you can obtain the same results with template functions and namespaces:
您将无法重用宏的旧定义,但可以取消定义并进行新定义。希望复制和粘贴不会太复杂。
我的建议是定义一个
xxx2
宏。You won't be able to reuse the old definition of the macro, but you can undefine it and make the new definition. Hopefully it isn't too complicated to copy and paste.
My recommendation is defining an
xxx2
macro.如果我们知道“xxx”宏中“x”参数的类型,我们可以通过在函数中使用它来重新定义宏,然后将“xxx”宏定义为该函数
“xxx”宏的原始定义:
在某个文件中制作“xxx”宏的增强版本:
If we know type of 'x' parameter in the 'xxx' macro, we can redefine macro by using it in a function and then define the 'xxx' macro as this function
Original definition for the 'xxx' macro:
In a certain file make enhanced version of the 'xxx' macro:
来自: https://gcc.gnu.org/onlinedocs/gcc/ Push_002fPop-Macro-Pragmas.html
From: https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html
这不完全是您所要求的,但它可以提供帮助。
您可以在给宏定义新定义之前
#undef
宏。示例:
但我从未听说过(或见过)递归宏。我认为这是不可能的。
It is not exactly what you're asking for but it can help.
You can
#undef
a macro prior to giving it a new definition.Example:
I never heard of (or seen) a recursive macro though. I don't think it is possible.
这个答案并没有完全回答你的问题,但我觉得它在按照你打算使用你的方法的方式工作方面做得很好(如果可能的话)。
这个想法是让所有执行实际工作的文件特定宏具有唯一的名称(例如
LOG_GENERIC
和LOG_SPECIFIC
),并具有通用标记(在您的casexxx
) 只需指向当前适当的宏。另外,使用非标准但广泛使用的
#pragma push_macro
和#pragma pop_macro
我们都可以修改通用的xxx
令牌并将其恢复为以前的版本。例如,假设有两个头文件,
generic.hpp
和specic.hpp
,这里的公共标记是LOG
:通过这样做,我们得到优点:
#pragma push_macro
和#pragma pop_macro
以可恢复的方式修改LOG
的简单机制LOG_SPECIFIC
可以使用LOG_GENERIC
)LOG_SPECIFIC
定义中引用LOG
,我们必须遍历LOG_GENERIC
LOG_SPECIFIC
定义之上的宏影响它,听起来就像每次都做错事链接到上面示例的 github 存储库
This answer doesn't answer your question exactly, but I feel like it does a good job at working the way you would intend to use your method (if it was possible).
The idea is for all of your file-specific macros that do actual work to have a unique name (for example
LOG_GENERIC
andLOG_SPECIFIC
), and having the common token (in your casexxx
) simply point to the currently appropriate macro.Plus, using non-standard but widely available
#pragma push_macro
and#pragma pop_macro
we can both modify the commonxxx
token and restore it to the previous version.For example, imagine two header files,
generic.hpp
andspecific.hpp
, common token here beingLOG
:By doing things this way we get the benefits of:
LOG
in a restorable way via#pragma push_macro
and#pragma pop_macro
LOG_*
macros explicitly (LOG_SPECIFIC
can useLOG_GENERIC
)LOG
inside ofLOG_SPECIFIC
definition, we have to go throughLOG_GENERIC
LOG_SPECIFIC
definition to affect it, just sounds like the wrong thing to do every timeLink to a github repository with the example above