我想在C文件上运行工具x并获取宏后代码。 (如果我们只能做更像宏的功能)。我知道gcc -E
,但这也包含在一个大文件中。
基本上我想将一些C宏用于重复代码,但不希望最终代码包含任何宏,因为项目不赞成这些宏。
答案 0 :(得分:3)
使用您选择的脚本语言,注释掉所有#include
,然后运行gcc -E -Wp,-P,-C,-CC foo.c
,然后取消注释#include
。或者,您可以将#include
替换为不以#
开头的字符串...例如include#
或@include
;可能性是无止境。使用@
代替#
的方法可以让您完全控制哪些预处理程序指令执行和不扩展...代码那些您不希望使用@
扩展的代码,然后脚本只运行gcc -E
,然后将@
更改为#
。但是,我认为最好采用其他方式,使用特殊标记(例如@
)来指示您的可扩展宏。然后脚本会将前导#
转换为其他内容(例如,HIDE#
)并将标记(例如@
)转换为#
,运行gcc -E
然后将HIDE#
(或其他)转回#
。
-Wp
指定预处理器选项。 -P
表示不生成行指令,-C
表示不删除注释,-CC
表示不删除宏生成的注释 - 这意味着代码中的注释 - 生成宏将保留在输出中。要确定所有可用的预处理器选项(有很多,大部分都不感兴趣),运行gcc -Wp,--help anyfile.c
...这就是我做出这个答案的方法(在首次运行gcc --help
之后找到-Wp
选项)。 (知道如何找到东西比知道事情更重要。)
答案 1 :(得分:2)
如何在#include
列表后面的代码中放置分隔符,以便您可以手动删除包含文件扩展,但在运行gcc -E
后保持宏扩展?
类似的东西:
#include <one>
#include <two>
void delete_everything_above_and_put_includes_back(); // delimeter
#define MACRO(X) ...
//rest of the code
我不知道有一个工具可以扩展宏但不会扩展#include
...
答案 2 :(得分:1)
我决定添加另一个答案,因为它完全不同。
您是否考虑过将const
变量和inline
函数作为替代方案,而不是将宏扩展到项目源存储库中?
基本上这些是宏在项目中“皱眉”的原因。
你必须记住,inline
仅仅是一个“建议”(即:函数可能实际上没有内联),而const
将使用内存而不是一个常量字面(井) ,取决于编译器,良好的编译器将优化),但这将做两件事:
因此,请记住这一点,作为一种选择。
答案 3 :(得分:0)
作为您的问题的可能解决方案:“编写宏然后丢弃它,通过替换等效函数”,您可以使用原型函数式宏。它们有一些限制,必须小心使用。但它们的功能与功能几乎相同。
#define xxPseudoPrototype(RETTYPE, MACRODATA, ARGS) typedef struct { RETTYPE xxmacro__ret__; ARGS } MACRODATA
xxPseudoPrototype(float, xxSUM_data, int x; float y; );
xxSUM_data xxsum;
#define SUM_intfloat(X, Y) ( xxsum = (xxSUM_data){ .x = (X), .y = (Y) }, \
xxsum.xxmacro__ret__ = xxsum.x + xxsum.y, \
xxsum.xxmacro__ret__)
我在这里解释了详细信息(主要是第4节,类似函数的宏):
观察编译器对类型进行正确且透明的诊断 (但是,有必要对这些结构有所关注,如链接中所述)。
现在,如果您可以将宏的所有句子收集为由逗号分隔的函数调用链,那么您可以根据需要获得类似函数的宏。
此外,您可以轻松地将其转换为实际功能,因为已经定义了参数列表。类型检查已经完成,所以一切都会正常工作。 在上面的示例中,您必须通过以下其他行替换所有行(第一行除外):
#define xxPseudoPrototype(RETTYPE, MACRODATA, ARGS) typedef struct { RETTYPE xxmacro__ret__; ARGS } MACRODATA
float SUM_intfloat(int x, float y) { /* (1) */
xxPseudoPrototype(float, xxSUM_data, int x; float y; ); /* (2) */
xxSUM_data xxsum; /* (2) */
return /* (3) */
( xxsum = (xxSUM_data){ .x = x, .y = y }, /* (4) (5) (6) */
xxsum.xxmacro__ret__ = xxsum.x + xxsum.y, /* (5) (6) */
xxsum.xxmacro__ret__) /* (6) */
; /* (7) */
} /* (8) */
替换将遵循一个sistematic程序:
(1)宏标头变为功能标题。分号(;)由逗号(,)替换 (2)声明线在功能体内移动 (3)增加“返回”字样 (4)宏参数X,Y由函数参数x,y代替 (5)删除所有结尾的“\” (6)所有中间计算和函数调用保持不变 (7)添加分号 (8)关闭功能体。
问题:虽然这种方法可以满足您的需求,但请注意该功能已复制其参数列表。这不好:必须删除伪原型和重复:
float SUM_intfloat(int x, float y) {
return
( x + y )
;
}