दुर्भाग्य से, एक क्रॉस प्लेटफॉर्म, क्रॉस कंपाइलर वातावरण में, संकलित समय पर इसे शुद्ध रूप से करने के लिए कोई विश्वसनीय तरीका नहीं है।
- _WIN32 और _WIN64 दोनों कभी-कभी दोनों अपरिभाषित हो सकते हैं , अगर परियोजना सेटिंग्स त्रुटिपूर्ण या दूषित हैं (विशेष रूप से विजुअल स्टूडियो 2008 SP1 पर)।
- प्रोजेक्ट कॉन्फ़िगरेशन त्रुटि के कारण "Win32" नामक एक परियोजना 64-बिट पर सेट की जा सकती है।
- वर्तमान स्टूडियो #define के अनुसार, विजुअल स्टूडियो 2008 SP1 में, कभी-कभी कोड के सही भागों को नहीं हटाता है। इससे यह देखना मुश्किल हो जाता है कि संकलन के समय किस #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: रनटाइम चेक
मुख्य में (), यह देखने के लिए डबल चेक करें कि क्या साइज़ोफ़ () समझ में आता है:
#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: समय संकलन की जाँच करें
सामान्य नियम यह है कि "प्रत्येक # अल्पाइन को एक # अंत में समाप्त होना चाहिए जो एक त्रुटि उत्पन्न करता है"।
#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
गोपनीय रूप से, ऊपर दिए गए नियमों को आपके पूरे कोडबेस को अधिक विश्वसनीय बनाने के लिए अनुकूलित किया जा सकता है:
- हर अगर () कथन एक "और" में समाप्त होता है, जो एक चेतावनी या त्रुटि उत्पन्न करता है।
- हर स्विच () कथन "डिफ़ॉल्ट:" में समाप्त होता है, जो एक चेतावनी या त्रुटि उत्पन्न करता है।
यह अच्छी तरह से काम करने का कारण है कि यह आपको हर एक मामले के बारे में पहले से सोचने के लिए मजबूर करता है, और सही कोड को निष्पादित करने के लिए "और" भाग में तर्क (कभी-कभी त्रुटिपूर्ण) पर भरोसा नहीं करता है।
मैंने इस तकनीक का उपयोग (कई अन्य लोगों के बीच) एक 30,000 लाइन परियोजना को लिखने के लिए किया था जो उस दिन से त्रुटिपूर्ण रूप से काम करती थी जिस दिन इसे पहली बार उत्पादन में तैनात किया गया था (जो कि 12 महीने पहले था)।