3 回答

TA贡献1851条经验 获得超4个赞
不幸的是,没有跨平台宏可以在主要编译器中定义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
另一个更简单的方法是从编译器命令行简单地设置这些变量。

TA贡献1835条经验 获得超7个赞
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;
}

TA贡献2012条经验 获得超12个赞
不幸的是,在跨平台,跨编译器的环境中,没有一种可靠的方法可以完全在编译时执行此操作。
如果项目设置有缺陷或损坏(特别是在Visual Studio 2008 SP1上),则_WIN32和_WIN64有时都可能未定义。
由于项目配置错误,标记为“ Win32”的项目可能设置为64位。
在Visual Studio 2008 SP1上,根据当前的#define,有时intellisense不会使代码的正确部分变灰。这使得在编译时很难准确看到正在使用哪个#define。
因此,唯一可靠的方法是结合3个简单的检查:
1)编译时间设定,以及;
2)运行时检查;以及;
3)强大的编译时间检查。
简单检查1/3:编译时间设置
选择任何方法来设置所需的#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
简单检查2/3:运行时检查
在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
简单检查3/3:强大的编译时间检查
一般规则是“每个#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
更新2017-01-17
来自的评论@AI.G:
4年后(不知道之前是否可能),您可以使用静态断言将运行时检查转换为编译时检查:static_assert(sizeof(void *)== 4);。现在,一切都在编译时完成了:)
附录A
偶然地,上述规则可以进行调整以使您的整个代码库更可靠:
每个if()语句均以“ else”结尾,该警告会生成警告或错误。
每个switch()语句均以“ default:”结尾,该警告会生成警告或错误。
之所以如此有效,是因为它迫使您提前考虑每种情况,而不是依靠“其他”部分中的(有时是有缺陷的)逻辑来执行正确的代码。
我使用了这项技术(以及其他许多技术)来编写一个30,000行的项目,该项目从首次部署到生产的那天(即12个月前)就一直完美无缺。
- 3 回答
- 0 关注
- 514 浏览
添加回答
举报