91

编译 C 或 C++ 代码时找出 CPU 架构最可靠的方法是什么?据我所知,不同的编译器有自己的一组非标准预处理器定义(_M_X86在 MSVS 中__i386____arm__在 GCC 中等)。

有没有一种标准的方法来检测我正在构建的架构?如果没有,是否有各种编译器的此类定义的完整列表的来源,例如带有所有样板#ifdef的标头?

4

7 回答 7

18

没有编译器间标准,但每个编译器都趋于一致。您可以为自己构建一个标题,如下所示:

#if MSVC
#ifdef _M_X86
#define ARCH_X86
#endif
#endif

#if GCC
#ifdef __i386__
#define ARCH_X86
#endif
#endif

一个完整的列表没有多大意义,因为有成千上万的编译器,但只有 3-4 个被广泛使用(Microsoft C++、GCC、Intel CC,也许是 TenDRA?)。只需决定您的应用程序将支持哪些编译器,列出它们的#defines,并根据需要更新您的标头。

于 2008-09-30T07:03:40.770 回答
8

如果您想转储特定平台上的所有可用功能,您可以运行 GCC,如下所示:

gcc -march=native -dM -E - </dev/null

它会转储宏,如#define __SSE3__ 1#define __AES__ 1等。

于 2016-05-04T04:07:32.447 回答
7

享受,我是这个的原作者。

extern "C" {
    const char *getBuild() { //Get current architecture, detectx nearly every architecture. Coded by Freak
        #if defined(__x86_64__) || defined(_M_X64)
        return "x86_64";
        #elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
        return "x86_32";
        #elif defined(__ARM_ARCH_2__)
        return "ARM2";
        #elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__)
        return "ARM3";
        #elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T)
        return "ARM4T";
        #elif defined(__ARM_ARCH_5_) || defined(__ARM_ARCH_5E_)
        return "ARM5"
        #elif defined(__ARM_ARCH_6T2_) || defined(__ARM_ARCH_6T2_)
        return "ARM6T2";
        #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
        return "ARM6";
        #elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
        return "ARM7";
        #elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
        return "ARM7A";
        #elif defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
        return "ARM7R";
        #elif defined(__ARM_ARCH_7M__)
        return "ARM7M";
        #elif defined(__ARM_ARCH_7S__)
        return "ARM7S";
        #elif defined(__aarch64__) || defined(_M_ARM64)
        return "ARM64";
        #elif defined(mips) || defined(__mips__) || defined(__mips)
        return "MIPS";
        #elif defined(__sh__)
        return "SUPERH";
        #elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
        return "POWERPC";
        #elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
        return "POWERPC64";
        #elif defined(__sparc__) || defined(__sparc)
        return "SPARC";
        #elif defined(__m68k__)
        return "M68K";
        #else
        return "UNKNOWN";
        #endif
    }
}
于 2021-02-17T21:04:33.050 回答
4

如果您想要一个交叉编译器解决方案,那么只需使用Boost.Predef包含

  • BOOST_ARCH_对于正在编译的系统/CPU架构。
  • BOOST_COMP_对于正在使用的编译器。
  • BOOST_LANG_对于一个正在编译的语言标准。
  • BOOST_LIB_C_和 BOOST_LIB_STD_ 用于使用的 C 和 C++ 标准库。
  • BOOST_OS_对于我们正在编译的操作系统。
  • BOOST_PLAT_适用于操作系统或编译器之上的平台。
  • BOOST_ENDIAN_用于操作系统和架构组合的字节顺序。
  • BOOST_HW_对于硬件特定的功能。
  • BOOST_HW_SIMD用于 SIMD(单指令多数据)检测。

例如

#if defined(BOOST_ARCH_X86)
    #if BOOST_ARCH_X86_64
        std::cout << "x86_64 " << BOOST_ARCH_X86_64 << " \n";
    #elif BOOST_ARCH_X86_32
        std::cout << "x86 " << BOOST_ARCH_X86_32 << " \n";
    #endif
#elif defined(BOOST_ARCH_ARM)
    #if _M_ARM
        std::cout << "ARM " << _M_ARM << " \n";
    #elif _M_ARM64
        std::cout << "ARM64 " << _M_ARM64 << " \n";
    #endif
#endif

您可以在此处了解有关如何使用它的更多信息

于 2018-10-18T05:38:27.887 回答
3

没有什么标准。Brian Hook 在他的“Portable Open Source Harness”中记录了其中的一堆,甚至试图将它们变成连贯且可用的东西(ymmv 关于这一点)。请参阅此站点上的 posh.h 标头:

请注意,由于前一段时间的 DOS 攻击,上面的链接可能要求您输入一些虚假的用户名/密码。

于 2008-09-30T07:03:39.693 回答
1

这里#define有一个s的列表。之前有一个高度投票的答案包含此链接,但可能是由于 SO 的“答案必须有代码”规则而被 mod 删除。所以这里是一个随机样本。点击链接查看完整列表。

AMD64

类型 描述
鉴别 __amd64__ __amd64 __x86_64__ __x86_64 由 GNU C 和 Sun Studio 定义
鉴别 _M_X64 _M_AMD64 由 Visual Studio 定义
于 2021-11-05T16:36:15.090 回答
-2

如果您需要对 CPU 功能进行细粒度检测,最好的方法是同时发布一个 CPUID 程序,该程序将 CPU 支持的一组功能输出到 stdout 或某些“cpu_config.h”文件。然后将该程序与您的构建过程集成。

于 2008-09-30T14:41:30.170 回答