【问题标题】:Putting a #endif inside a #if将#endif 放入#if
【发布时间】:2015-04-08 10:38:43
【问题描述】:

是否可以将#endif 放在#if 中作为块的“内容”而不是#if 的#endif 对?

#if (SOME_CONDITION)
    #if (ANOTHER_CONDITION)
#endif // pair endif for #if (SOME_CONDITION)


#if (SOME_CONDITION)
    #endif // pair endif for #if (ANOTHER_CONDITION)
#endif // pair endif for #if (SOME_CONDITION)

如果这不可能,如何有条件地编译 #if ... #endif 对?

这就是我正在做的。

我正在修改我们从另一家公司购买的代码库。为了在修改和不修改的情况下轻松编译它,我使用了如下所示的宏。

#if (MY_COMPANY_EDITS_ENABLED)
// My Modified code goes here
#else
// unmodified code from another company
#endif

通过这种方式,我可以轻松地编译入/出我的修改,同时保持我的编辑的可读性。我到处使用相同的#if #else #endif 块。但后来我遇到了一个正在编译的代码,在原始未修改的代码库中,基于一些宏值。

#if (FEATURE_A_IS_ENABLED)
// Line 1
// Line 2
#endif

但我想编译这段代码 [第 1 行和第 2 行],不管宏值 FEATURE_A_IS_ENABLED 是什么

我的第一个想法是遵循我迄今为止使用的相同约定[以保持我的编辑的可读性]。

#if (MY_COMPANY_EDITS_ENABLED)
//#if (FEATURE_A_IS_ENABLED)
#else
#if (FEATURE_A_IS_ENABLED)
#endif

// Line 1
// Line 2

#if (MY_COMPANY_EDITS_ENABLED)
// #endif
#else
#endif
#endif

然后我意识到这是不可能的。

我知道,存在替代方法来实现相同的目标。但想知道我是否可以使用相同的约定

#if (MY_COMPANY_EDITS_ENABLED)
// My Modified code goes here
#else
// unmodified code from another company
#endif

在这种情况下也是如此。

【问题讨论】:

  • 什么意思?如果是哪个结局?
  • 抱歉,不清楚。我会更新问题。
  • 对不起,说实话,这根本没有任何意义。
  • @NeonGlow 这根本不可能。预处理器应该如何知道哪个#if 与哪个#endif 搭配使用?!您可能可以改用良好的旧布尔逻辑来解决它。
  • @iharob :我知道这很荒谬,但只是出于好奇。

标签: c c-preprocessor


【解决方案1】:

不,这是不可能的。第一个#endif 将与最近的#if#else 匹配,因此您的代码将被解释为:

#if (SOME_CONDITION)
    #if (ANOTHER_CONDITION)
    #endif // pair endif for #if (ANOTHER_CONDITION)


    #if (SOME_CONDITION)
    #endif // pair endif for the second #if (SOME_CONDITION)
#endif // pair endif for the first #if (SOME_CONDITION)

【讨论】:

  • 没错,这就是为什么这是不可能的,尽管您可以从缩进中看到 OP 想要什么。
  • C 语言和标准 C 预处理器都忽略缩进。对我来说,缩进也不能解释 OP 的意图。
【解决方案2】:

这是不可能的,因为预处理器只对您的文件进行一次传递,并且#endif 与前面的#if 匹配。如果你想让 #if/#endif 有条件的块,那么只需将它嵌套在另一个 #if/#endif 块中:

#if CONDITION_A
#  if CONDITION_B
...
#  endif /* CONDITION_B */
#endif /* CONDITION_A */

换句话说,预处理指令不可能构造其他预处理指令,因为初始“构造”阶段的输出不会被预处理器重新解析。

例如,即使假设换行符不是问题(它们会在这里),下面的(愚蠢的)示例也不起作用:

#if DEFINE_X_TO_FIVE
#define X
#endif
#if DEFINE_X_TO_FIVE
5
#endif

【讨论】:

  • 这是不可能的,也不是因为预处理器。
  • @iharob:请澄清。这是因为预处理器的工作方式。
  • 你能用任何编程语言来做吗?我的意思是有条件地结束 if 块?假设你是编译器,你会怎么做?
  • @iharob:在宏处理器中可以对输入进行多次传递。我实际上并没有证实这一点,但我相信m2 可以。 make 不是宏处理器,但也可以选择使用 $$ 样式的扩展多次遍历输入。
  • 哦!我明白你的意思了。
【解决方案3】:

我建议根据功能集进行更改,而不是它们是否属于您,然后将它们组合在一起以创建给定版本 (MY_COMPANY_EDITS_ENABLED) 或其他:

#if (MY_COMPANY_EDITS_ENABLED)
     #define FEATUREA
     #define FEATUREB
     #define FEATUREC
     #define FEATURED
#else
     #define FEATUREA
     #undef  FEATUREB
     #undef  FEATUREC
     #undef  FEATURED
#endif

#ifdef FEATUREA
//do some feature A stuff
#endif

// do code

#ifdef FEATUREB
//do some feature B stuff
#endif

#ifndef FEATUREC
//do some stuff if not feature C
#endif

// etc...

从长远来看,这会更加灵活,并允许您通过重建打开和关闭更改功能。

【讨论】:

    【解决方案4】:

    当然,您可以嵌套预处理器指令:

    #ifdef CONDITION1
    // some code here
          # ifdef CONDITION2
          // some else here
          # endif
    #endif
    

    但请确保正确结束每个条件。

    另请参阅:http://www.ioccc.org/years.html#1995_vanschnitzhttp://www.ioccc.org/years.html#2004_vik2

    【讨论】:

    • 另见 C11: 6.10.1 p4
    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多