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);?,F在,一切都在編譯時完成了:)
附錄A
偶然地,上述規則可以進行調整以使您的整個代碼庫更可靠:
每個if()語句均以“ else”結尾,該警告會生成警告或錯誤。
每個switch()語句均以“ default:”結尾,該警告會生成警告或錯誤。
之所以如此有效,是因為它迫使您提前考慮每種情況,而不是依靠“其他”部分中的(有時是有缺陷的)邏輯來執行正確的代碼。
我使用了這項技術(以及其他許多技術)來編寫一個30,000行的項目,該項目從首次部署到生產的那天(即12個月前)就一直完美無缺。
- 3 回答
- 0 關注
- 546 瀏覽
添加回答
舉報