#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif
#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
感谢。#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif
#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
感谢。不幸的是,没有跨平台宏定义在主要编译器中定义32位/64位。我发现最有效的方法是以下方式。
首先,我选择自己的表示法。我更喜欢使用 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
另一种更简单的方法是直接从编译器命令行设置这些变量。
#if _WIN32 || _WIN64
表示如果编译器为Windows系统,则执行下面的代码;#elif __GNUC__
表示如果编译器为GNU编译器,则执行其后的代码;而#else
则表示如果以上两个条件都不成立,则执行其后的代码。最后,#error "Missing feature-test macro for 32/64-bit on this compiler."
表示在此编译器上缺少适用于32/64位的特性测试宏。 - Davislortemplate<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;
}
size_t
的大小足以容纳系统中分配的任何对象的大小。通常情况下,在条件编译时这是您想要了解的信息。如果这不是您想要的,您可以使用此代码片段,将其替换为其他类型,例如 void*
。 - Kirill V. Lyadvinsky很遗憾,在跨平台、跨编译器的环境下,没有一种单一可靠的方法可以纯粹地在编译时完成这个任务。
因此,唯一可靠的方法是结合三个简单的检查:
选择任何方法来设置所需的#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
在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
一般规则是“每个 #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
@AI.G
的评论:
四年之后(不知道以前是否可能),您可以使用静态断言将运行时检查转换为编译时检查:static_assert(sizeof(void*) == 4);。现在,这一切都在编译时完成 :)
顺便提一下,可以采用上述规则将整个代码库的可靠性提高:
这种方法能很好地起到作用,因为它迫使您预先考虑每种情况,而不是依赖于“else”部分中执行正确代码的(有时是有缺陷的)逻辑。
我使用了这种技术(以及其他许多技术)来编写一个由三万行代码组成的项目,从第一天投入生产以来一直没有出现故障(这是12个月前的事情了)。
sizeof(void*)
是在编译时还是运行时解决的?如果是在编译时解决的,那么在运行时检查总是会是 if(8!=8){...}
。 - Ameenstatic_assert(sizeof(void*) == 4);
。现在所有操作都在编译时完成 :) - Al.G.static_assert(sizeof(void*) * CHAR_BIT == 32)
更加表达清晰且技术上更加正确(尽管我不知道有哪种字节具有不同于8位的位数的架构)。 - Xeverous你应该能够使用在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
微软的某些(全部?)编译器版本不包含 stdint.h
。不确定为什么,因为它是一个标准文件。这里有一个可用的版本:http://msinttypes.googlecode.com/svn/trunk/stdint.h
<stdint.h>
和<cstdint>
。目前的情况是,VC++库源于Dinkumware(现在仍然如此——TR1也是从那里取出的),但据我所记,在VCBlog上阅读到的内容是它正在进行相当重要的重构工作,以便与/clr
编译干净、与所有MSVC非标准类型(如__int64
)兼容等等,这就是为什么它不像只需将其放入下一个编译器版本那样简单。 - Pavel Minaevintptr_t
保证是有符号类型,所以这个答案是正确的。你的方法也可以,如果我要对指针进行任何棘手的操作(除了重新进行符号扩展以使x86-64指针成为规范化之外),我会选择无符号类型,因为我认为指针是无符号整数。 - Peter Cordes首先,在Windows上这样做行不通。在32位或64位的Windows下,longs和ints都是32位的。我认为检查指针大小是否为8字节可能是更可靠的方法。
sizeof(void*) == 8 ? Do64Bit() : Do32Bit();
这样使用一个测试将其留到运行时。这可能仍然会在二进制文件中留下未使用的函数,但该表达式很可能只被编译为对“正确”函数的调用。 - Steve Jessoptemplate<int> struct Thing; template<> struct Thing<4> { typedef uint32_t type; }; template<> struct Thing<8> { typedef uint64_t type; }; typedef Thing<sizeof(void*)>::type thingtype;
- Steve Jessop#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif
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
以下代码在大多数当前环境下工作正常:
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define IS64BIT 1
#else
#define IS32BIT 1
#endif
_WIN64
需要先包含<windows.h>
。在Visual C++中,最好使用内置的编译器定义:_M_IX86
、_M_X64
、_M_ARM
、_M_ARM64
等。 - Chuck Walbourn__ppc64__
、__powerpc64__
和 _ARCH_PPC64
。这也适用于 AIX 和其他平台。 - jww借鉴Contango的优秀回答,结合Fluent C++的"更好的宏和更好的标志",你可以这样做:
// Macro for checking bitness (safer macros borrowed from
// https://www.fluentcpp.com/2019/05/28/better-macros-better-flags/)
#define MYPROJ_IS_BITNESS( X ) MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_##X()
// Bitness checks borrowed from https://dev59.com/JXI_5IYBdhLWcg3wJfkM#12338526
#if _WIN64 || ( __GNUC__ && __x86_64__ )
# define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_64() 1
# define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_32() 0
# define MYPROJ_IF_64_BIT_ELSE( x64, x86 ) (x64)
static_assert( sizeof( void* ) == 8, "Pointer size is unexpected for this bitness" );
#elif _WIN32 || __GNUC__
# define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_64() 0
# define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_32() 1
# define MYPROJ_IF_64_BIT_ELSE( x64, x86 ) (x86)
static_assert( sizeof( void* ) == 4, "Pointer size is unexpected for this bitness" );
#else
# error "Unknown bitness!"
#endif
#if MYPROJ_IS_BITNESS( 64 )
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
或者使用我添加的额外宏:
MYPROJ_IF_64_BIT_ELSE( DoMy64BitOperation(), DoMy32BitOperation() );
“在64位编译”在C++中没有明确定义。
C ++仅为int,long和void *等大小设置下限。即使为64位平台编译,也不能保证int是64位的。该模型允许例如23位int和sizeof(int *)!= sizeof(char *)
64位平台有不同的编程模型。
您最好进行特定于平台的测试。其次,可移植决策必须更具体地说明何为64位。
stdint.h
可能是你的朋友,或者你可能需要开发一些适当的 typedef。 - Phil Miller