检测 C 中的 64 位编译
- 2024-10-30 08:36:00
- admin 原创
- 58
问题描述:
是否有一个 C 宏或某种方法可以帮助我在 C 编译时检查我的 c 程序是编译为 64 位还是 32 位?
编译器:GCC 我需要检查的操作系统:Unix/Linux
另外,在运行我的程序时如何检查操作系统是否支持 64 位?
解决方案 1:
由于您已将其标记为“gcc”,请尝试
#if __x86_64__
/* 64-bit */
#endif
解决方案 2:
以下是正确且可移植的测试,它不假设 x86 或其他任何内容:
#include <stdint.h>
#if UINTPTR_MAX == 0xffffffff
/* 32-bit */
#elif UINTPTR_MAX == 0xffffffffffffffff
/* 64-bit */
#else
/* wtf */
#endif
解决方案 3:
编译器和平台中立的解决方案是这样的:
// C
#include <stdint.h>
// C++
#include <cstdint>
#if INTPTR_MAX == INT64_MAX
// 64-bit
#elif INTPTR_MAX == INT32_MAX
// 32-bit
#else
#error Unknown pointer size or missing size macros!
#endif
避免使用以一个或多个下划线开头的宏。它们不是标准的,并且可能在您的编译器/平台上缺失。
解决方案 4:
这是一个会让语言律师感到恶心的简单问题。
if(sizeof (void *) * CHARBIT == 64) {
...
}
else {
...
}
由于它是一个常量表达式,因此优化编译器将放弃测试并仅将正确的代码放入可执行文件中。
解决方案 5:
使用特定于编译器的宏。
我不知道您的目标架构是什么,但由于您没有指定,我会假设它是普通的英特尔机器,因此您很可能对英特尔 x86和AMD64 的测试感兴趣。
例如:
#if defined(__i386__)
// IA-32
#elif defined(__x86_64__)
// AMD64
#else
# error Unsupported architecture
#endif
但是,我更喜欢将它们放在单独的标题中并定义我自己的编译器中立宏。
解决方案 6:
GLIBC 本身使用了这个(在inttypes.h
):
#if __WORDSIZE == 64
解决方案 7:
同一个程序源可以(而且应该能够)在 64 位计算机、32 位计算机、36 位计算机等上进行编译……
因此,仅通过查看源代码,如果源代码不错,您无法判断它将如何编译。如果源代码不太好,也许可以猜测程序员假设将使用什么来编译它。
我的回答是:
有一种方法可以仅针对不良程序来检查源文件所需的位数。
您应该努力使您的程序能够正常工作,无论它们需要编译多少位。
解决方案 8:
使用此UINTPTR_MAX值来检查构建类型。
#include <stdio.h>
#include <limits.h>
#if UINTPTR_MAX == 0xffffffffffffffffULL
# define BUILD_64 1
#endif
int main(void) {
#ifdef BUILD_64
printf("Your Build is 64-bit
");
#else
printf("Your Build is 32-bit
");
#endif
return 0;
}
解决方案 9:
有多个预定义的 GCC 定义。尽管 URL 中有“cpp”,但大多数定义也适用于 C(如果没有说明不同)。我建议使用其中一个定义,因为它们不需要包含头文件。它们始终可用并由 GCC 本身定义(而不是由头文件定义)。
#if _LP64
#endif
或者:
#if __SIZEOF_LONG__ == 8
#endif
还有__LONG_MAX__
,__LONG_WIDTH__
但是页面说你不应该使用没有头文件的文件。
解决方案 10:
这个问题含糊不清,因为它没有具体说明要求是针对 64 位指针还是64 位本机整数运算,或者两者兼而有之。
其他一些答案指出了如何检测 64 位指针。尽管问题字面上规定了“编译为”,但请注意,这并不能保证 64 位地址空间可用。
对于许多系统来说,检测 64 位指针相当于检测未模拟 64 位算术,但这并不能保证在所有潜在情况下都能如此。例如,尽管 Emscripten 使用最大大小为 2 32 -1的 Javascript 数组模拟内存,以提供编译针对 64 位的 C/C++ 代码的兼容性,但我相信 Emscripten对这些限制并不知情(尽管我没有测试过)。然而,无论编译器规定的限制如何,Emscripten 始终使用 32 位算术。因此看起来 Emscripten 将采用针对 64 位int
和 64 位指针的 LLVM 字节码,并尽 Javascript 所能模拟它们。
我最初提出检测 64 位“本机”整数的方法如下,但正如 Patrick Schlüter 指出的那样,这只能检测到罕见的 ILP64 情况:
#include <stdint.h>
#if UINT_MAX >= 0xffffffffffffffff
// 64-bit "native" integers
#endif
因此,正确的答案是,通常您不应该根据编译器报告的限制值对模糊的“64 位”分类的地址空间或算术效率做出任何假设。您的编译器可能支持特定数据模型或微处理器架构的不可移植预处理器标志,但考虑到问题针对的是 GCC 和 Emscripten 场景(其中 Clang 模拟 GCC),即使这些也可能具有误导性(尽管我还没有测试过)。
一般而言,这些场景都不能可靠地指示64 位地址空间和非模拟 64 位算法是否可用,因此它们基本上是无用的(相对于所述属性),除非在非不可知的构建系统环境中。因此,对于所述属性,最好设置构建宏,以便构建系统可以选择编译哪个变体。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件