有没有办法用 C 宏代替普通的 C 代码
我想在 C 文件上运行工具 x 并获取后宏代码。 (如果我们能只做宏那样的功能就更好了)。我知道 gcc -E ,但这也将所有内容包含到一个大文件中。
基本上,我想使用一些 C 宏来执行重复代码,但不希望最终代码包含任何宏,因为项目不赞成它们。
I want to run tool x on a C file and get the post-macro code. (If we can do only function like macros even better). I know about gcc -E
but that does all the includes into one big file as well.
Basically I'd like to use some C macros for repetitive code but don't want the final code to contain any macros because they are frowned upon by the project.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用您选择的脚本语言,注释掉所有
#include
,然后运行gcc -E -Wp,-P,-C,-CC foo.c
,然后取消注释#include
。或者您可以将#include
替换为一些不以#
开头的字符串...例如,include#
或@包括
;可能性是无限的。使用@
而不是#
的方法使您可以完全控制哪些预处理器指令会被扩展,哪些不会被扩展...编写您不想扩展的指令@
,然后脚本只运行gcc -E
,然后将@
更改为#
。但是,我认为最好以相反的方式进行,使用特殊标记(例如,@
)来指示您的可扩展宏。然后脚本会将前导#
转换为其他内容(例如HIDE#
)并将标记(例如@
)转换为< code>#,运行gcc -E
,然后将HIDE#
(或其他)转回#
。-Wp
指定预处理器选项。-P
表示不生成行指令,-C
表示不删除注释,-CC
表示不删除生成的注释通过宏——这意味着代码生成宏中的注释将保留在输出中。要确定所有可用的预处理器选项(有很多,大部分不感兴趣),请运行 gcc -Wp,--help anyfile.c ......这就是我得出这个答案的方法(首次运行gcc --help
找到-Wp
选项后)。 (知道如何发现事物比了解事物更重要。)Using the scripting language of your choice, comment out all
#include
s, then rungcc -E -Wp,-P,-C,-CC foo.c
then uncomment the#include
s. Or you could replace#include
with some string that doesn't start with a#
... e.g.,include#
or@include
; the possibilities are endless. The approach of using@
instead of#
gives you complete control over which preprocessor directives do and don't get expanded ... code the ones you don't want expanded with@
, and then the script just runsgcc -E
and then changes@
to#
. However, I think it would be better to do it the other way around, using a special marker (e.g.,@
) to indicate your expandable macros. Then the script would turn leading#
s into something else (e.g.,HIDE#
) and turn the marker (@
, for instance) into#
, rungcc -E
, then turnHIDE#
(or whatever) back into#
.-Wp
specifies preprocessor options.-P
means don't generate line directives,-C
means don't delete comments, and-CC
means don't delete comments generated by macros -- that means that comments in your code-generating macros will be preserved in the output. To determine all available preprocessor options (there are a great many, mostly not of interest), rungcc -Wp,--help anyfile.c
... that's what I did to come up with this answer (after first runninggcc --help
to find the-Wp
option). (Knowing how to find things out is more important than knowing things.)如何在代码中的 #include 列表之后放置一个分隔符,以便您可以手动删除包含文件扩展,但在运行 gcc -E< 后保持宏扩展完好无损/代码>?
比如:
我不知道有什么工具可以扩展宏但不会扩展
#include
...How about putting a delimiter in your code right after the
#include
list, so that you could get rid of the include files expansions manually, but have the macro expansion intact after runninggcc -E
?Something like:
I'm not aware of a tool that expands macros but doesn't expand
#include
s...我决定添加另一个答案,因为它完全不同。
您是否考虑过使用 const 变量和内联函数作为替代方案,而不是使用技巧将宏扩展到项目源存储库中?
基本上,这些就是宏在您的项目中“不受欢迎”的原因。
您必须记住,
inline
只是一个“建议”(即:该函数实际上可能不是内联的),并且const
将使用内存而不是常量文字(嗯,取决于编译器,好的编译器会优化),但这会做两件事:因此,请记住这一点,作为一种选择。
I decided to add another answer, because it's entirely different.
Instead of having tricks to expand macros into the project source repository - have you considered using
const
variables andinline
functions as alternative?Basically those are the reasons that the macros are "frown upon" in your project.
You have to keep in mind that
inline
is merely a "suggestion" (i.e.: the function might not be in fact inlined) andconst
will use memory instead of being a constant literal (well, depends on compiler, good compiler will optimize), but that will do two things:So keep that in mind as well, as an option.
作为问题的可能解决方案:“编写一个宏,然后通过用等效函数替换来丢弃它”,您可以使用原型函数式宏。它们有一些局限性,使用时必须小心。但它们的工作方式几乎与函数相同。
我已经在这里解释了详细信息(主要是第 4 节,对于类似函数的宏):
宏伪造函数
观察编译器对类型进行正确且透明的诊断。
(但是,有必要谨慎对待这些结构,如链接中所述)。
现在,如果您可以将宏的所有句子收集为以逗号分隔的函数调用链,那么您就可以根据需要获得类似函数的宏。
此外,您可以轻松地将其转换为实际函数,因为参数列表已经定义。类型检查已经完成,所以一切都会正常进行。
在上面的示例中,您必须将所有行(第一行除外)替换为其他行:
替换将遵循系统过程:
(1) 宏头变成函数头。分号 (;) 替换为逗号 (,)。
(2) 声明行移至函数体内。
(3)加了“回”字。
(4) 宏参数X、Y被函数参数x、y替代。
(5) 删除所有结尾的“\”。
(6) 所有中间计算和函数调用均保持不变。
(7) 添加分号。
(8) 关闭函数体。
问题:虽然此方法可以满足您的需求,但请注意该函数已重复其参数列表。这不好:必须删除伪原型和重复项:
As a possible solution to your problem: "write a macro and then discard it, by replacing by an equivalent function", you can use prototyped function-like macros. They have some limitations, and must be used with some care. But they work almost the same way as a function.
I have explained the details here (mainly section 4, for function-like macros):
Macros faking functions
Observe that the compiler does right and transparent diagnostics of types.
(However, it is necessary to have some care with these constructs, as explained in the link).
Now, if you can collect all the sentences of your macro as a chain of function-calls separated by commas, then you can obtain function-like macro, as you desired.
Moreover, you can easily convert it into a real function, since the list of parameters is already defined. The type-checking was already done, so everything will work fine.
In the example above, you have to replace all the lines (except the first), by these other ones:
The replacement will follow a sistematic procedure:
(1) Macro header turned into function header. Semicolons (;) are replaced by commas (,).
(2) Declaration lines are moved inside function body.
(3) The "return" word is added.
(4) Macro arguments X, Y, are replaced by function parameters x, y.
(5) All ending "\"s are removed.
(6) All intermediante calculations and function calls are left untouched.
(7) Semicolon added.
(8) Closing function body.
Problem: Although this approach solves your needs, note that the function has duplicated its list of parameters. This is not good: pseudoprototypes and duplicates have to be erased: