模拟默认定义的条件宏定义

Conditional macro definition to emulate default define

我正在编写一些基于几何的代码。手头的任务涉及使用边界框来包含固体样本。现在,在代码中我设计了两种不同类型的这种框,即 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 中的任何一个设置定义,当两者或 none 其中有明确定义。 我倾向于可移植代码,但特定于编译器的技巧也可以通过。我正在使用 Visual Studio 2012.

因为只有两个值,我将只使用一个布尔变量:

#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

可以通过立即使用单个多值开关选择它们来更好地完成像那些可靠的众多选择之一。

#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

这是我的结尾:

// 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

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