启用和禁用代码功能的 C 宏
Posted
技术标签:
【中文标题】启用和禁用代码功能的 C 宏【英文标题】:C macro to enable and disable code features 【发布时间】:2013-08-21 03:57:49 【问题描述】:我之前使用过一个代码库,它有一个用于启用和禁用代码段的宏系统。它看起来像下面这样:
#define IN_USE X
#define NOT_IN_USE _
#if defined( WIN32 )
#define FEATURE_A IN_USE
#define FEATURE_B IN_USE
#define FEATURE_C NOT_IN_USE
#elif defined( OSX )
#define FEATURE_A NOT_IN_USE
#define FEATURE_B NOT_IN_USE
#define FEATURE_C IN_USE
#else
#define FEATURE_A NOT_IN_USE
#define FEATURE_B NOT_IN_USE
#define FEATURE_C NOT_IN_USE
#endif
然后功能的代码如下所示:
void DoFeatures()
#if USING( FEATURE_A )
// Feature A code...
#endif
#if USING( FEATURE_B )
// Feature B code...
#endif
#if USING( FEATURE_C )
// Feature C code...
#endif
#if USING( FEATURE_D ) // Compile error since FEATURE_D was never defined
// Feature D code...
#endif
我的问题(我不记得的部分)是如何定义“USING”宏,以便在未将功能定义为“IN_USE”或“NOT_IN_USE”时出错?如果您忘记包含正确的头文件,可能会出现这种情况。
#define USING( feature ) ((feature == IN_USE) ? 1 : ((feature == NOT_IN_USE) ? 0 : COMPILE_ERROR?))
【问题讨论】:
我对@987654324@ 和NOT_IN_USE
的存在感到有些困惑。
我相信这只是为了让事情更具可读性。只要 USING 宏使用相同的字符,您就可以轻松地将特征定义为“X”和“_”或任何其他随机字符。
为什么不直接删除 NOT_IN_USE 定义?
我不明白你的意思。如果没有定义特征,例如示例中的 FEATURE_D,那将如何导致错误?
【参考方案1】:
您的示例已经实现了您想要的,因为如果未定义 USING
,#if USING(x)
将产生错误消息。你在头文件中需要的只是
#define IN_USE 1
#define NOT_IN_USE 0
#define USING(feature) feature
如果你想确保你也因为做类似的事情而得到一个错误
#if FEATURE
或
#if USING(UNDEFINED_MISPELED_FEETURE)
那么你可以这样做,比如说,
#define IN_USE == 1
#define NOT_IN_USE == 0
#define USING(feature) 1 feature
但你将无法防止这样的误用
#ifdef FEATURE
【讨论】:
如果未定义功能,我想要错误,而不是 USING 宏。例如我的示例中的 FEATURE_D。 @0x48492121 就像我说的:“或者 #if USING(fred) where fred 不是功能”。另外,你说你想检测不包括头文件......就像我说的,如果头文件不包括在内,你会得到一个错误,任何出现 #if USING(...) @0x48492121 再次:#if USING(FEATURE_D)
将使用我的第二个建议产生错误消息:error: missing binary operator before token "FEATURE_D" ... 如果你不这样做不喜欢那个提议,有无数类似的提议。
啊..对不起,我错过了理解弗雷德部分。似乎工作。我对“#define USING(feature) 1 feature”实际上在做什么感到困惑。
@0x48492121 特征是== 1
或== 0
,所以它产生1 == 1
或1 == 0
。如果您了解预处理器只是进行文本(或标记)替换,这应该很清楚。【参考方案2】:
以下作品。它会给你 FEATURE_D 的编译错误。如果您注释掉 FEATURE_D 的代码,那么它将执行 FEATURE_A 和 FEATURE_B 的代码。代码几乎是不言自明的。无需检查 FEATURE_D 或其他是否在 DoFeatures 函数中定义,您只需将它们放在 if 块中即可。这样,编译器将尝试执行代码块。如果为 1,则执行 if 块中的代码;如果为 0,则不会执行。如果它从未被定义,那么会得到一个编译错误。
#include <stdio.h>
#define IN_USE 1
#define NOT_IN_USE 0
#define FEATURE_A IN_USE
#define FEATURE_B IN_USE
#define FEATURE_C NOT_IN_USE
void DoFeatures()
if(FEATURE_A)
// Feature A code...
printf("Feature A\n");
if(FEATURE_B)
// Feature B code...
printf("Feature B\n");
if(FEATURE_C)
// Feature C code...
printf("Feature C\n");
if(FEATURE_D) // Compile error since FEATURE_D was never defined
// Feature D code...
printf("Feature D\n");
int main(int argc, char **argv)
DoFeatures();
return 0;
【讨论】:
这行得通,但它不会删除正在编译的代码并添加不必要的运行时检查。 @0x48492121 如果您进行优化,则没有不必要的运行时检查(如果不这样做,您就不会关心时间),但是当必须删除代码时它并不能解决问题,因为有否则会是语法错误或其他问题。 @JimBalter,我不明白这部分“在必须删除代码时无法解决问题,因为会出现语法错误”,因为问题是:“如果功能没有,则会出错” t 被定义为 'IN_USE' 或 'NOT_IN_USE'?如果您忘记包含正确的头文件,可能会出现这种情况。我想我已经确保了这个错误检查。 您引用的两件事彼此无关。 OP 需要预处理器#if
,而不是 C 语言级别 if(...)
。预处理器 ifdefs 通常在文件级别使用,您的表达式无法使用,或者注释掉依赖于 typedefs 或其他不可用声明的代码,因此代码会产生语法错误......将其放在 if(0) ...
中不会'不影响语法检查器。【参考方案3】:
不使用就不要定义
#if defined( WIN32 )
#define FEATURE_A
#define FEATURE_B
#else if defined( OSX )
#define FEATURE_C
#else
#endif
然后在你的代码中:
void DoFeatures()
#ifdef FEATURE_A
// Feature A code...
#endif
#ifdef FEATURE_B
// Feature B code...
#endif
#ifdef FEATURE_C
// Feature C code...
#endif
#ifdef FEATURE_D // Compile error since FEATURE_D was never defined
// Feature D code...
#endif
【讨论】:
如果未定义该功能,我将尝试生成错误。如果“#define FEATURE_A”在某个标头中并且您检查“#ifdef FEATURE_A”而不包括标头,它将默默地跳过该代码。【参考方案4】:你不能用另一组#ifdef
s吗?
#if defined(WIN32)
#define FEATURE_A
#define FEATURE_B
#elif defined (OSX)
#define FEATURE_C
#endif
// ...
#if defined(FEATURE_A)
do_a();
#endif
等等
【讨论】:
如果未定义该功能,我将尝试生成错误。这是为了防止诸如“#if defined(FAETURE_A)”之类的拼写错误,或者如果您忘记包含定义该功能的标题。 @0x48492121 然后将#define FEATURE_A
设置为1 或0,这取决于它是否存在,然后在#ifdef FEATURE_A
中,插入另一层条件:#if FEATURE_A
。然后,#ifdef
的#else
部分应该包含一个#error "feature inclusion typo detected"
。
USING 宏是通过没有额外的条件级别来保持代码更简洁。
@0x48492121 你知道你刚刚接受了一个基本上是我的副本的答案,大约 23 分钟后?
我做到了?我一定错过了什么。当未定义 FEATURE_D 时,我看不到您的答案如何产生错误。【参考方案5】:
#define IN_USE 1
//#define NOT_IN_USE _ //Not required
#if defined( WIN32 )
#define FEATURE_A IN_USE
#define FEATURE_B IN_USE
#define FEATURE_C NOT_IN_USE
#elif defined( OSX )
#define FEATURE_A NOT_IN_USE
#define FEATURE_B NOT_IN_USE
#define FEATURE_C IN_USE
#else
#define FEATURE_A NOT_IN_USE
#define FEATURE_B NOT_IN_USE
#define FEATURE_C NOT_IN_USE
#endif
#define USING( feature ) feature
然后是你的代码
【讨论】:
如果 USING 宏与未定义的功能一起使用,我希望编译器出错。【参考方案6】:这样的事情怎么样?
#define IN_USE 1
#define NOT_IN_USE 0
#if defined( WIN32 )
#define FEATURE_A IN_USE
#define FEATURE_B IN_USE
#define FEATURE_C NOT_IN_USE
#elif defined( OSX )
#define FEATURE_A NOT_IN_USE
#define FEATURE_B NOT_IN_USE
#define FEATURE_C IN_USE
#else
#define FEATURE_A NOT_IN_USE
#define FEATURE_B NOT_IN_USE
#define FEATURE_C NOT_IN_USE
#endif
#define USING(f) ((f == IN_USE) ? 1 : (f == NOT_IN_USE) ? 0 : (f))
#include <stdio.h>
void DoFeatures()
#if USING( FEATURE_A )
// Feature A code...
printf("Feature A\n");
#endif
#if USING( FEATURE_B )
// Feature B code...
printf("Feature B\n");
#endif
#if USING( FEATURE_C )
// Feature C code...
printf("Feature C\n");
#endif
#if defined( FEATURE_D ) // Compile error since FEATURE_D was never defined
// Feature D code...
printf("Feature D\n");
#else
#error FEATURE_D not defined.
#endif
int main(int argc, char **argv)
DoFeatures();
return 0;
对于编译错误,我不知道如何将它集成到宏中。如果有人能给我们一些启示,我们将不胜感激。 :P
【讨论】:
我知道可以,就是不知道怎么集成。以上是关于启用和禁用代码功能的 C 宏的主要内容,如果未能解决你的问题,请参考以下文章