在 C++ 中确定 32 位和 64 位
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1505582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Determining 32 vs 64 bit in C++
提问by Joe Corkery
I'm looking for a way to reliably determine whether C++ code is being compiled in 32 vs 64 bit. We've come up with what we think is a reasonable solution using macros, but was curious to know if people could think of cases where this might fail or if there is a better way to do this. Please note we are trying to do this in a cross-platform, multiple compiler environment.
我正在寻找一种方法来可靠地确定 C++ 代码是在 32 位还是 64 位中编译。我们已经提出了我们认为使用宏的合理解决方案,但很想知道人们是否能想到这可能会失败的情况,或者是否有更好的方法来做到这一点。请注意,我们正尝试在跨平台、多编译器环境中执行此操作。
#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif
#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
Thanks.
谢谢。
采纳答案by JaredPar
Unfortunately there is no cross platform macro which defines 32 / 64 bit across the major compilers. I've found the most effective way to do this is the following.
不幸的是,没有跨平台宏定义跨主要编译器的 32 / 64 位。我发现最有效的方法如下。
First I pick my own representation. I prefer ENVIRONMENT64 / ENVIRONMENT32. Then I find out what all of the major compilers use for determining if it's a 64 bit environment or not and use that to set my variables.
首先我选择我自己的代表。我更喜欢 ENVIRONMENT64 / ENVIRONMENT32。然后我找出所有主要编译器使用什么来确定它是否是 64 位环境并使用它来设置我的变量。
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif
Another easier route is to simply set these variables from the compiler command line.
另一个更简单的方法是从编译器命令行简单地设置这些变量。
回答by Kirill V. Lyadvinsky
template<int> void DoMyOperationHelper();
template<> void DoMyOperationHelper<4>()
{
// do 32-bits operations
}
template<> void DoMyOperationHelper<8>()
{
// do 64-bits operations
}
// helper function just to hide clumsy syntax
inline void DoMyOperation() { DoMyOperationHelper<sizeof(size_t)>(); }
int main()
{
// appropriate function will be selected at compile time
DoMyOperation();
return 0;
}
回答by Contango
Unfortunately, in a cross platform, cross compiler environment, there is no single reliable method to do this purely at compile time.
不幸的是,在跨平台、交叉编译器环境中,没有单一可靠的方法可以完全在编译时执行此操作。
- Both _WIN32 and _WIN64 can sometimes bothbe undefined, if the project settings are flawed or corrupted (particularly on Visual Studio 2008 SP1).
- A project labelled "Win32" could be set to 64-bit, due to a project configuration error.
- On Visual Studio 2008 SP1, sometimes the intellisense does not grey out the correct parts of the code, according to the current #define. This makes it difficult to see exactly which #define is being used at compile time.
- 如果项目设置有缺陷或损坏(尤其是在 Visual Studio 2008 SP1 上),_WIN32 和 _WIN64 有时都可能未定义。
- 由于项目配置错误,标记为“Win32”的项目可能设置为 64 位。
- 在 Visual Studio 2008 SP1 上,根据当前的 #define,有时智能感知不会使代码的正确部分变灰。这使得在编译时很难准确地看到正在使用哪个 #define。
Therefore, the only reliablemethod is to combine 3 simple checks:
因此,唯一可靠的方法是结合3 个简单的检查:
- 1) Compile time setting, and;
- 2) Runtime check, and;
- 3) Robust compile time checking.
- 1)编译时间设置,以及;
- 2)运行时检查,以及;
- 3)强大的编译时检查。
Simple check 1/3: Compile time setting
简单检查1/3:编译时间设置
Choose any method to setthe required #define variable. I suggest the method from @JaredPar:
选择任何方法来设置所需的#define 变量。我建议使用@JaredPar 的方法:
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
Simple check 2/3: Runtime check
简单检查 2/3:运行时检查
In main(), double check to see if sizeof() makes sense:
在 main() 中,仔细检查 sizeof() 是否有意义:
#if defined(ENV64BIT)
if (sizeof(void*) != 8)
{
wprintf(L"ENV64BIT: Error: pointer should be 8 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 64-bit mode.\n");
#elif defined (ENV32BIT)
if (sizeof(void*) != 4)
{
wprintf(L"ENV32BIT: Error: pointer should be 4 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 32-bit mode.\n");
#else
#error "Must define either ENV32BIT or ENV64BIT".
#endif
Simple check 3/3: Robust compile time checking
简单检查 3/3:强大的编译时检查
The general rule is "every #define must end in a #else which generates an error".
一般规则是“每个#define 都必须以生成错误的 #else 结尾”。
#if defined(ENV64BIT)
// 64-bit code here.
#elif defined (ENV32BIT)
// 32-bit code here.
#else
// INCREASE ROBUSTNESS. ALWAYS THROW AN ERROR ON THE ELSE.
// - What if I made a typo and checked for ENV6BIT instead of ENV64BIT?
// - What if both ENV64BIT and ENV32BIT are not defined?
// - What if project is corrupted, and _WIN64 and _WIN32 are not defined?
// - What if I didn't include the required header file?
// - What if I checked for _WIN32 first instead of second?
// (in Windows, both are defined in 64-bit, so this will break codebase)
// - What if the code has just been ported to a different OS?
// - What if there is an unknown unknown, not mentioned in this list so far?
// I'm only human, and the mistakes above would break the *entire* codebase.
#error "Must define either ENV32BIT or ENV64BIT"
#endif
Update 2017-01-17
更新 2017-01-17
Comment from @AI.G:
评论来自@AI.G:
4 years later (don't know if it was possible before) you can convert the run-time check to compile-time one using static assert: static_assert(sizeof(void*) == 4);. Now it's all done at compile time :)
4 年后(不知道之前是否可行)您可以使用静态断言将运行时检查转换为编译时检查:static_assert(sizeof(void*) == 4);。现在一切都在编译时完成了:)
Appendix A
附录 A
Incidentially, the rules above can be adapted to make your entire codebase more reliable:
顺便说一句,可以调整上述规则以使您的整个代码库更可靠:
- Every if() statement ends in an "else" which generates a warning or error.
- Every switch() statement ends in a "default:" which generates a warning or error.
- 每个 if() 语句都以“else”结尾,这会生成警告或错误。
- 每个 switch() 语句都以“default:”结尾,它会生成警告或错误。
The reason why this works well is that it forces you to think of every single case in advance, and not rely on (sometimes flawed) logic in the "else" part to execute the correct code.
之所以如此有效,是因为它迫使您提前考虑每一个案例,而不是依赖“else”部分中的(有时是有缺陷的)逻辑来执行正确的代码。
I used this technique (among many others) to write a 30,000 line project that worked flawlessly from the day it was first deployed into production (that was 12 months ago).
我使用这种技术(以及许多其他技术)编写了一个 30,000 行的项目,该项目从第一次部署到生产中的那天起(那是 12 个月前)就完美无缺地运行了。
回答by alex tingle
You should be able to use the macros defined in stdint.h. In particular INTPTR_MAXis exactly the value you need.
您应该能够使用中定义的宏stdint.h。特别INTPTR_MAX是正是您需要的价值。
#include <cstdint>
#if INTPTR_MAX == INT32_MAX
#define THIS_IS_32_BIT_ENVIRONMENT
#elif INTPTR_MAX == INT64_MAX
#define THIS_IS_64_BIT_ENVIRONMENT
#else
#error "Environment not 32 or 64-bit."
#endif
Some (all?) versions of Microsoft's compiler don't come with stdint.h. Not sure why, since it's a standard file. Here's a version you can use: http://msinttypes.googlecode.com/svn/trunk/stdint.h
某些(所有?)版本的 Microsoft 编译器不附带stdint.h. 不知道为什么,因为它是一个标准文件。这是您可以使用的版本:http://msinttypes.googlecode.com/svn/trunk/stdint.h
回答by mattnewport
That won't work on Windows for a start. Longs and ints are both 32 bits whether you're compiling for 32 bit or 64 bit windows. I would think checking if the size of a pointer is 8 bytes is probably a more reliable route.
一开始,这在 Windows 上是行不通的。无论您是为 32 位还是 64 位窗口编译,Longs 和 ints 都是 32 位。我认为检查指针的大小是否为 8 字节可能是更可靠的路由。
回答by Anoop
You could do this:
你可以这样做:
#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif
回答by emj8321
Try this:
#ifdef _WIN64
// 64 bit code
#elif _WIN32
// 32 bit code
#else
if(sizeof(void*)==4)
// 32 bit code
else
// 64 bit code
#endif
回答by peterchen
"Compiled in 64 bit" is not well defined in C++.
“以 64 位编译”在 C++ 中没有很好的定义。
C++ sets only lower limits for sizes such as int, long and void *. There is no guarantee that int is 64 bit even when compiled for a 64 bit platform. The model allows for e.g. 23 bit ints and sizeof(int *) != sizeof(char *)
C++ 只为诸如 int、long 和void *. 即使为 64 位平台编译,也不能保证 int 是 64 位。该模型允许例如 23 位int和sizeof(int *) != sizeof(char *)
There are different programming modelsfor 64 bit platforms.
64 位平台有不同的编程模型。
Your best bet is a platform specific test. Your second best, portable decision must be more specific in whatis 64 bit.
您最好的选择是特定于平台的测试。你的第二个最好的、便携的决定必须更具体地说明什么是 64 位。
回答by cmaster - reinstate monica
Your approach was not too far off, but you are only checking whether longand intare of the same size. Theoretically, they could both be 64 bits, in which case your check would fail, assuming both to be 32 bits. Here is a check that actually checks the size of the types themselves, not their relative size:
您的方法并不太远,但您只是在检查long和int是否具有相同的大小。理论上,它们都可以是 64 位,在这种情况下,您的检查将失败,假设它们都是 32 位。这是一个检查,实际检查类型本身的大小,而不是它们的相对大小:
#if ((UINT_MAX) == 0xffffffffu)
#define INT_IS32BIT
#else
#define INT_IS64BIT
#endif
#if ((ULONG_MAX) == 0xfffffffful)
#define LONG_IS32BIT
#else
#define LONG_IS64BIT
#endif
In principle, you can do this for any type for which you have a system defined macro with the maximal value.
原则上,您可以对任何具有最大值的系统定义宏的类型执行此操作。
Note, that the standard requires long longto be at least 64 bits even on 32 bit systems.
请注意,long long即使在 32 位系统上,标准也要求至少为 64 位。
回答by Ameen
People already suggested methods that will try to determine if the program is being compiled in 32-bitor 64-bit.
人们已经提出了一些方法来尝试确定程序是在32-bit或中编译的64-bit。
And I want to add that you can use the c++11 feature static_assertto make sure that the architecture is what you think it is ("to relax").
我想补充一点,您可以使用 c++11 功能static_assert来确保架构是您认为的那样(“放松”)。
So in the place where you define the macros:
所以在你定义宏的地方:
#if ...
# define IS32BIT
static_assert(sizeof(void *) == 4, "Error: The Arch is not what I think it is")
#elif ...
# define IS64BIT
static_assert(sizeof(void *) == 8, "Error: The Arch is not what I think it is")
#else
# error "Cannot determine the Arch"
#endif

