我想使用像这样的宏参数:
#define D(cond,...) do{ \
#if cond \
#define YYY 1 \
#else \
#define YYY 0 \
} while(0)
有可能吗?
UPD
也许当源被预处理两次时:gcc -E source.c | gcc -xc -
接下来将起作用:
#define D(cond,...) #define YYY cond&DEBUG
#if YYY
#define D(...) printf( __VA_ARGS__ )
#else
#define D(...)
#endif
答案 0 :(得分:4)
这是不可能的。了解GNU cpp
preprocessor和C11标准(即n1570),然后查看here。 C preprocessor(概念上至少)在编译器的其余部分(它获取translation unit的预处理形式)之前运行。顺便说一句,对于文件foo.c
,您可以使用gcc -C -E foo.c > foo.i
(使用GCC)获取其预处理表单foo.i
,然后您可以检查foo.i
-since它是一个文本文件 - 带有寻呼机或编辑器。
但是,可生成.c
个文件(生成C代码是一种常见做法,至少从20世纪80年代开始;例如yacc,{{3} },bison,rpcgen,....;许多大型软件项目使用C或C ++代码的专用生成器......)。您可以考虑使用其他工具(可能是swig预处理器(或GPP)或其他一些程序或脚本来生成C文件(来自其他程序)。再看看GNU m4(它可能有类似于你的目标)。
您可能需要为此目的配置autoconf工具,例如为build automation修改Makefile
。
答案 1 :(得分:3)
不,这是不可能的。
在翻译期间,所有预处理指令(#define
,#include
等)都会在任何宏扩展发生之前执行,因此如果宏扩展为预处理指令,它不会被解释为 - 它将被解释为(无效的)源代码。
答案 2 :(得分:3)
正如其他人指出的那样,这是不可能的,但有一个解决方法:
int YYY;
/* global scope variables are sometimes considered bad practice... */
#define D(cond,...) do{ \
if (cond) { \
YYY = 1; \
} \
else { \
YYY = 0; \
} \
} while(0)
使用优化标记(例如:gcc/clang -O3
),它将替换死代码,就像它是一个宏一样。显然你可能想要改变YYY的类型,但你似乎像布尔一样使用它。
答案 3 :(得分:2)
不,因为C 2011 [N1570] 6.10.3.4 3说,关于宏替换,“结果完全宏替换的预处理令牌序列不会被处理为预处理指令,即使它类似于一个,......”
答案 4 :(得分:1)
预处理程序在编译之前会经历程序,并替换使用其指定值定义的每个宏。
答案 5 :(得分:0)
这是一些穷人的代码生成,因为将另一个工具集成到项目中是多余的。
像这样定义一个宏,根据您的需要进行扩展:
#define NESTED /* Comment out instead of backslash new lines.
*/ /*
*/ UNDEF REPLACED /*
*/ /*
*/ IFDEF CONDITION /*
*/ DEFINE REPLACED 1 /*
*/ ELSE /*
*/ DEFINE REPLACED 0 /*
*/ ENDIF
您的 NESTED
版本可以是类似函数的宏,而 REPLACED
可以具有更详细的主体。
让 CONDITION
和名为 macros 的指令没有定义。
DEFINE CONDITION
控制 NESTED
在编译时获得哪个值,类似于正常的 #ifdef
用法:
DEFINE CONDITION
NESTED
int i = REPLACED; //i == 1
UNDEF CONDITION
NESTED
int z = REPLACED; //z == 0
使用 NESTED
和其他宏的源代码将无法编译。要生成可以使用所选选项编译的 .c
或 .cpp
文件,请执行以下操作:
gcc -E -CC source.c -o temporary.c
gcc -E \
-DDEFINE=\#define -DUNDEF=\#undef \
-DIFDEF=\#ifdef -DELSE=\#else -DENDIF=\#endif \
temporary.c -o usableFile.c
rm temporary.c #remove the temporary file
-E
表示仅预处理,不编译。第一个 gcc
命令扩展 NESTED
和源中所有正常定义的宏。由于未定义 DEFINE
、IFDEF
等,它们及其未来的参数在 temporary.c
文件中保留为文字文本。
-CC
使注释保留在输出文件中。在预处理器用它的主体替换 NESTED
之后,temporary.c
在单独的行中包含指令宏,并带有注释。当下一个 gcc 命令的注释被删除时,换行符仍然是标准的。
#
在不带参数的宏的主体中被接受。但是,与宏不同,指令不会在扩展时重新扫描和执行,因此您需要另一个预处理器传递来使嵌套定义工作。所有与延迟定义相关的预处理也需要延迟,并立即提供给预处理器。否则,稍后传递中所需的指令和参数将被消耗并从前一个传递中的代码中删除。
第二个 gcc
命令将 -D
宏替换为延迟指令,使所有这些宏都可以在下一轮开始的预处理器中使用。指令及其参数不会在同一个 gcc 命令中重新扫描,而是在 usableFile.c
中保留为文字文本。
编译 usableFile.c
时,预处理器会执行延迟指令。