【问题标题】:Conditional macro definition to emulate default define模拟默认定义的条件宏定义
【发布时间】:2017-11-24 08:57:16
【问题描述】:

我正在编写一些基于几何的代码。手头的任务涉及使用边界框来包含实体样本。现在,在代码中,我设计了两种不同类型的此类框,即INNER_BOUNDING_BOXOUTER_BOUNDING_BOX。该代码进一步期望使用两个盒子中的任何一个,但不能同时使用两者。我试图通过使用预处理器来实现它。 我已经基于几个宏编写了进一步的代码,即USE_INNER_BOUNDING_BOXUSE_OUTER_BOUNDING_BOX。我可以确保任何时候任何一个宏都是通过一些简单的结构来定义的:

#if defined(USE_INNER_BOUNDING_BOX) && defined(USE_OUTER_BOUNDING_BOX)
    #undef USE_INNER_BOUNDING_BOX
    #undef USE_OUTER_BOUNDING_BOX
    #define USE_INNER_BOUNDING_BOX
#endif

#ifndef USE_INNER_BOUNDING_BOX
    #ifndef USE_OUTER_BOUNDING_BOX
        #define USE_INNER_BOUNDING_BOX
    #endif
#endif

现在,如果我想使用任何特定的框,我可以定义相应的宏。困难在于想要使用默认设置宏 USE_DEFAULT_BOUNDING_BOX,然后我可以使用它来为 USE_INNER_BOUNDING_BOXUSE_OUTER_BOUNDING_BOX 中的任何一个设置定义,当它们都被明确定义或都没有被明确定义时。 我倾向于可移植代码,但编译器特定的技巧也可以通过。我正在使用Visual Studio 2012

【问题讨论】:

  • 不是你所问问题的真正答案,但你为什么不将单个开关 BOUNDING_BOX_TO_USE 定义为 INNER == 1 OUTER == 2 ?这样一来,它就不可能两者兼而有之。
  • 我可以写一些类似的东西。那个时候我并没有触动。 :) 我可能会尝试以不同的方式实现它。但是,这仍然是一个偶然的问题,而且很有趣,所以我问了。 :)
  • 这些宏块已经完全按照您的意愿行事:当两个宏都被定义或都没有定义时,定义其中一个宏。不过它可能会更短。

标签: c visual-studio-2012 c-preprocessor


【解决方案1】:

通过立即使用单个多值开关选择它们,可以更好地完成此类可靠的多选之一。

#define BOUNDING_INNER 1
#define BOUNDING_OUTER 2

/* default */
#define BOUNDING_BOX_TO_USE BOUNDING_INNER

/* alternatively please activate below line 
#define BOUNDING_BOX_TO_USE BOUNDING_OUTER
*/

如果您需要保持向后兼容某些配置,
例如您的代码已被其他人使用,
您可以从两者中派生单个开关,与您的默认行为相匹配。 好处是避免#undef(如果您同意这样做是一个好处)。

#if defined(USE_INNER_BOUNDING_BOX) && defined(USE_OUTER_BOUNDING_BOX)
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
#endif

#ifndef USE_INNER_BOUNDING_BOX
    #ifndef USE_OUTER_BOUNDING_BOX
        #define BOUNDING_BOX_TO_USE BOUNDING_INNER
    #endif
#endif

/* In case you are as paranoid a programmer as I am,
   you might want to do some plausibility checking
   here. ifndef, >0, <2 etc., triggering some #errors. */


/* Later, in code doing the actual implementation: */

#if (BOUNDING_BOX_TO_USE == BOUNDING_INNER)
/* do inner bounding stuff */
#endif
/* other code, e.g. common for inner and outer */
#if (BOUNDING_BOX_TO_USE == BOUNDING_OUTER)
/* do outer bounding stuff */
#endif

【讨论】:

  • 我会把它作为答案。我将在 equals 块中定义 USE_OUTER_BOUNDING_BOX 或 USE_INNER_BOUNDING_BOX,并用其他东西替换前面块中的相同内容。是的,我想保持定义它们的方式,并避免使用 undef。这不是一般意义上的好习惯,以免您处于与未连接、不了解的代码片段的冲突定义之中?
  • 我想我真的不明白你在问什么练习?使用 undef?在我看来不好。保持向后兼容已经分布的配置概念?在我看来很好。清理冲突的定义?好的。摆脱undefs这样做?很好。
  • 是的,您错过了 IDE 或项目文件、Makefile 中的定义。对不起,我不得不在谈话中离开。无论如何,我想我可以分享一些你似乎经历过的代码编译悲伤。让你想变得偏执,我希望我能有不同的想法。
【解决方案2】:

由于只有两个值,我只使用一个布尔变量:

#ifndef USE_OUTER_BOUNDING_BOX
    #define USE_OUTER_BOUNDING_BOX 0
#endif

如果USE_OUTER_BOUNDING_BOX 为零(假),则使用内部边界框。

test.c:

#include <stdio.h>

#ifndef USE_OUTER_BOUNDING_BOX
    #define USE_OUTER_BOUNDING_BOX 0
#endif

int main(void)
{
    printf("%d\n", USE_OUTER_BOUNDING_BOX);
    return 0;
}

例子:

$ cc -o test -DUSE_OUTER_BOUNDING_BOX=0 test.c
$ ./test 
0
$ cc -o test -DUSE_OUTER_BOUNDING_BOX=1 test.c
$ ./test
1

【讨论】:

  • 在这种情况下它肯定会在这里工作,但是之后的问题是试图获得一些过度杀伤的预处理器技巧,如果涉及两个以上的盒子,这将起作用。我应该这样表达这个问题。无论如何,您的代码也适用于我的情况,但它需要依赖于宏的值,我不想明确指定。我在这里完成了这个快速修复。当然,它需要针对更多的框类型(条件块)进行修改:
【解决方案3】:

这是我的结尾:

// Comment to use bigger outer Bounding-Box
#define USE_INNER_BOUNDING_BOX

#define INNER_BOUNDING_BOX 0
#define OUTER_BOUNDING_BOX 1

#define DEFAULT_BOUNDING_BOX OUTER_BOUNDING_BOX

#if defined(USE_INNER_BOUNDING_BOX) && !defined(USE_OUTER_BOUNDING_BOX)
    #define USE_BOUNDING_BOX INNER_BOUNDING_BOX
#elif defined(USE_OUTER_BOUNDING_BOX)
    #define USE_BOUNDING_BOX OUTER_BOUNDING_BOX
#else
    #define USE_BOUNDING_BOX DEFAULT_BOUNDING_BOX
#endif

#if (USE_BOUNDING_BOX == INNER_BOUNDING_BOX)
    #undef USE_OUTER_BOUNDING_BOX
    #define USE_INNER_BOUNDING_BOX
#else
    #undef USE_INNER_BOUNDING_BOX
    #define USE_OUTER_BOUNDING_BOX
#endif

这仅适用于这种情况。如果有更多框,我会附加条件块。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    相关资源
    最近更新 更多