启用和禁用代码功能的 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?))

【问题讨论】:

我对@9​​87654324@ 和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 == 11 == 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】:

你不能用另一组#ifdefs吗?

#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 宏的主要内容,如果未能解决你的问题,请参考以下文章

打开excel总是提示宏禁用的解决方法

excel2016宏被禁用没有找到对应的杀毒软件

启用分析时禁用 OpenMP

由于宏安全设置,无法找到宏或宏被禁用怎么办?

WORD里面的宏禁用怎么解决

由于宏安全设置,无法找到宏或宏被禁用怎么办?