【问题标题】:How to enforce exactly one definition?如何严格执行一个定义?
【发布时间】:2009-06-10 12:57:49
【问题描述】:

给定一个需要支持多种环境的 C 项目,我如何使用预处理器来强制定义一个环境?

我已经可以了:

#如果定义了PROJA (等等等等等等) #elif 定义的 PROJB (ETC) #别的 #error "未定义项目" #万一

不过,所有要做的就是告诉我是否定义了 0 个项目。如果某个有用的灵魂同时定义了项目 A 和项目 B,则预处理器将只假定项目 A。但是,在我看来,正确的行为是标记错误。

当然,只定义了 2 个项目,这个问题是微不足道的。 200怎么解决?

【问题讨论】:

  • 使用 200 个预处理器 hack 维护起来非常痛苦,那么您宁愿需要让 makesystem 处理这个问题

标签: c c-preprocessor


【解决方案1】:

类似这样的:

#if defined PROJA
  #ifdef HAVE_PROJ
    #error 
  #endif

  #define HAVE_PROJ
#endif

#if defined PROJB
  #ifdef HAVE_PROJ
    #error 
  #endif

  #define HAVE_PROJ
#endif

#ifndef HAVE_PROJ
  #error No project selected (you need to define PROJA, PROJB, or ...)
#endif

【讨论】:

  • 我认为这将很快变得严峻,并且不应该在宏恕我直言。
【解决方案2】:

可能有不同的文件

include_proja.h
include_projc.h

然后使用您的 Makefile 或其他任何内容来包含正确的文件。然后,您可以使用代码生成 200 个不同的文件,并在编译时包含正确的文件。

这种东西就是构建系统的用途。如果你正在用宏做一些奇怪的事情......在源代码之外找到更好的方法。

每个文件都可以做(请原谅这里的冗长)

#define A_PROJECT_INCLUDE_WAS_INCLUDED

然后做

#ifndef A_PROJECT_INCLUDE_WAS_INCLUDED
    #error "No project include"
#endif

但是一些缺失的符号很可能会破坏它。

祝你好运

【讨论】:

  • “这种事情就是构建系统的用途。如果你正在用宏做一些奇怪的事情......在源代码之外找到更好的方法。”你完全正确。
【解决方案3】:

试试这个

#define ENV_UNKNOWN 0
#define ENV_MACOSX  1
#define ENV_LINUX   2
#define ENV_WIN32   3
/* and so on */


#ifndef ENVIRONMENT
/* no environment given, default to something (perhaps) */
#define ENVIRONMENT ENV_UNKNOWN
#endif

/* and now the environment specific parts */
#if (ENVIRONMENT == ENV_MACOSX)
#include "macosx_port.h"
#endif

#if (ENVIRONMENT == ENV_LINUX)
#include "linux_port.h"
#endif

#if (ENVIRONMENT == ENV_WIN32)
#include "win32_port.h"
#endif

#if (ENVIRONMENT == ENV_UNKNOWN)
#error You have to specify the ENVIRONMENT.
#endif

现在您可以在命令行上指定要编译的环境,如下所示:

cc -DENVIRONMENT=2 ...

另一种方法是根据您正在编译的环境,从您的构建系统中包含/链接不同的模块。

【讨论】:

    【解决方案4】:
    #if defined PROJA
    bool one_project_defined = true;
    #endif
    
    #if defined PROJB
    bool one_project_defined = true;
    #endif
    
    #if defined PROJC
    bool one_project_defined = true;
    #endif
    
    #if defined PROJD
    bool one_project_defined = true;
    #endif
    
    one_project_defined; // Won't compile in wrong builds
    

    【讨论】:

    • 这很简短。不过,它确实让我觉得有点老套。
    • 直到一些有帮助的合作社进行维护工作并认为,“嘿,这个变量不再被使用了......”
    【解决方案5】:

    嵌套 ifs 的问题在于,您最终会对 n 个项目进行 n^2 个不同的测试。

    在这种情况下,您只需要一些会给出编译时错误的表达式。也许:

    #ifdef PROJA
    #define PROJA-TEST "
    #else
    #define PROJA-TEST ""
    #endif
    

    B、C 等以此类推

    然后:

    const char *test_only_one_project = PROJA-TEST PROJB-TEST PROJC-TEST " "More than one project is defined!";
    

    编辑:...当然,这仅测试定义了奇数个项目。但这应该可行:

    #ifdef PROJA
    #define PROJA-TEST (
    #endif
    

    以此类推,然后

    const char *test_only_one_project = PROJA-TEST PROJB-TEST PROJC-TEST "More than one project is defined!" );
    

    【讨论】:

    • 我的第一个想法是,“是的,我也会这样做。”我的第二个问题是,“这就是为什么不再有人喜欢 C 的原因了?”
    • 没错。预处理器非常邪恶。
    【解决方案6】:

    也许你可以这样做:

    #if PROJ==A
    (blah blah blah)
    #elif PROJ==B
    (etc)
    #else
    #error "No project defined"
    #endif
    

    【讨论】:

      猜你喜欢
      • 2021-12-03
      • 2012-02-14
      • 2014-12-14
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多