【问题标题】:Compiler #defines for g++ and clg++ 和 cl 的编译器#defines
【发布时间】:2010-11-09 13:24:27
【问题描述】:

我正在编写一个跨平台的程序。在某些地方,我必须指定依赖于操作系统的调用。

#ifdef WINDOWS
..do windows only stuff
#endif
#ifdef LINUX
..do linux only stuff    
#endif

是否有任何由编译器定义的预处理器指令,因此我在使用命令行编译器时不必显式定义它们。即。

cl -DWINDOWS 程序.cpp

g++ -DLINUX 程序.cpp

我意识到我可以很容易地编写一个 makefile 或一个 shell/batch 脚本来自动执行此操作。但我宁愿默认使用与编译器相同的编译器(如果存在)。

【问题讨论】:

标签: visual-c++ g++


【解决方案1】:

是的。我相信 WIN32 是,但我现在不在 Windows 上测试它:D

见: http://en.wikipedia.org/wiki/C_preprocessor(它提到了WIN32)

【讨论】:

  • 它说它仅由 Win32 编译器定义。不是 Unix/Linux。
  • 这似乎不适用于 Visual Studios 命令行编译器。我通过说 #ifndef WIN32 #error 这个编译器没有定义 WIN32 #endif 并且它打印出一个错误来检查它
  • 很奇怪。不过,我很确定 WIN32 是由 Mingw 定义的。
【解决方案2】:

我在this 网站上找到了所有 g++ 的完整列表。

  • #define __HAVE_BUILTIN_SETJMP__ 1
  • #define __unix__ 1
  • #define unix 1
  • #define __i386__ 1
  • #define __SIZE_TYPE__ unsigned int
  • #define __ELF__ 1
  • #define __GNUC_PATCHLEVEL__ 3
  • #define __linux 1
  • #define __unix 1
  • #define __linux__ 1
  • #define __USER_LABEL_PREFIX__
  • #define linux 1
  • #define __STDC_HOSTED__ 1
  • #define __EXCEPTIONS 1
  • #define __GXX_WEAK__ 1
  • #define __WCHAR_TYPE__ long int
  • #define __gnu_linux__ 1
  • #define __WINT_TYPE__ unsigned int
  • #define __GNUC__ 3
  • #define __cplusplus 1
  • #define __DEPRECATED 1
  • #define __GNUG__ 3
  • #define __GXX_ABI_VERSION 102
  • #define i386 1
  • #define __GNUC_MINOR__ 2
  • #define __STDC__ 1
  • #define __PTRDIFF_TYPE__ int
  • #define __tune_i386__ 1
  • #define __REGISTER_PREFIX__
  • #define __NO_INLINE__ 1
  • #define _GNU_SOURCE 1
  • #define __i386 1
  • #define __VERSION__ "3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)"

Visual C++ 已经定义了 Win32 以用于任何 Widnows 版本。

【讨论】:

  • 请注意,此列表高度依赖于调用 gcc/g++ 的选项。例如。所有不以下划线开头的宏都在 -std=c89 或 -std=c99 下。 __CHAR_UNSIGNED__ 在存在 -funsigned-char 等时出现。没有可移植的方式来确定任何系统上任何编译器的操作系统。我们所能做的就是做出一些在大多数情况下都有效的假设。
【解决方案3】:

是的,有这样的预定义符号,但我不建议您使用它们,除非您永远不会预见到支持更多平台、编译器或操作系统版本。这是逻辑。

首先,您最好使用自己的最少组定义的编译常量,以便在代码中使用。因为你可能会从这样的事情开始:

#if defined(_WIN32)
    // do windows stuff
#endif
#if defined(_linux)
    // linux stuff
#endif

假设您允许在未自动定义 _WIN32 的 Windows 的新编译器下进行编译?您可以将每个 _WIN32 行更改为:

#if defined(_WIN32) || defined(ming)

如果您有多个要更改的内容,那真是令人头疼。你可以把这样的东西放在一个高层次上:

#if defined(ming)
#define _WIN32
#endif

但是您可能会发现某些系统或库头文件因为碰巧使用 _WIN32 而异常。最好把它抽象到一个通用的头文件中:

#if defined(_WIN32) || defined(ming)
    #define PLAT_WINDOWS
#endif

然后在需要的地方简单地使用#if defined(PLAT_WINDOWS)。

但是那个通用的头文件呢?好吧,当一个新的编译器/操作系统/任何东西出现时,你必须开始调整它以确保它说正确的事情。很快,只有了解地球上每个操作系统上每个编译器的每个版本,才能理解这种可笑的毛球。哎呀,谁没有,但所做的任何更改都必须在任何地方进行测试,这很痛苦。

所以,最好在 makefile 内部或什至外部设置一些高级设置,上面写着“如果你在 Windows 上,-DPLAT_WINDOWS”并完成它。

当然,如果您在代码中使用最常用的函数和特性,所有这些都会被最小化。

【讨论】:

    【解决方案4】:

    所有这些答案都非常好。对我有用的解决方案如下。

    #ifdef _WIN32
    
    #endif
    
    #ifdef linux
    
    #endif
    

    WIN32 不是由 cl 定义的,但 _WIN32 是。 linux是由g++定义的。

    【讨论】:

    • 很高兴看到您通过组合或解决方案来回答您的问题,但这并不能解决我获得代表的问题,因为您无法接受我们所有的答案。 ;-)
    • _WIN32 可能是在 Visual C++ 中定义的,但我很确定它是在 Mingw 中定义的。
    【解决方案5】:

    您可以将代码放在#ifndef #else 块中,而不是针对特定平台使用两个宏。例如:

    #ifndef _WIN32
    // linux specific code
    #else
    // windows specific code
    #endif
    

    使用此解决方案,ifndef-else 块将确保您不会在两个 #ifdef 块之间意外添加代码(据说它们以相同的方式处理程序执行流程)。

    上面的代码还可以让你独立编译这段代码,不仅适用于 linux,而且适用于任何 unix 平台,只要它支持调用,而无需将宏标签从 linux 更改为 unix 或其他。

    【讨论】:

      猜你喜欢
      • 2018-05-09
      • 2011-06-07
      • 2019-08-02
      • 1970-01-01
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多