सी ++ में 32 बनाम 64 बिट का निर्धारण


136

मैं मज़बूती से यह निर्धारित करने का एक तरीका ढूंढ रहा हूं कि क्या C ++ कोड 32 बनाम 64 बिट में संकलित किया जा रहा है। हम मैक्रोज़ का उपयोग करके एक उचित समाधान के साथ आए हैं, लेकिन यह जानने के लिए उत्सुक थे कि क्या लोग उन मामलों के बारे में सोच सकते हैं जहां यह विफल हो सकता है या यदि ऐसा करने का एक बेहतर तरीका है। कृपया ध्यान दें कि हम एक क्रॉस-प्लेटफॉर्म, कई कंपाइलर वातावरण में ऐसा करने की कोशिश कर रहे हैं।

#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif

#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif

धन्यवाद।


8
यदि आप वास्तव में परवाह करते हैं कि आपकी वास्तुकला का शब्द-आकार क्या है, तो इस संभावना को नजरअंदाज न करें कि यह 32 या 64-बिट नहीं है। वहाँ 16 और 128-बिट आर्किटेक्चर हैं, आप जानते हैं।
एलेक्स टिंगल

64 बिट और 32 बिट ऑपरेशन में क्या अंतर है?
पीटरचेन

2
आपको वास्तव में लक्ष्य प्लेटफ़ॉर्म की शब्द-चौड़ाई पर इसे सशर्त नहीं करना चाहिए। इसके बजाय, क्या करना है यह निर्धारित करने के लिए सीधे संबंधित डेटाटिप्स के आकार का उपयोग करें। stdint.hआपका मित्र हो सकता है, या आपको अपने स्वयं के कुछ उपयुक्त टाइपफेड विकसित करने की आवश्यकता हो सकती है।
फिल मिलर

यह परीक्षण Visual Studio 2008 SP1 पर काम नहीं करता है। यह 32-बिट और 64-बिट दोनों के लिए "IS64BIT" पर अटक जाता है।
कंटैंगो

जवाबों:


99

दुर्भाग्य से कोई क्रॉस प्लेटफॉर्म मैक्रो नहीं है जो प्रमुख कंपाइलरों में 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

एक और आसान मार्ग कम्पाइलर कमांड लाइन से बस इन चरों को सेट करना है।


3
अच्छी तरह से, जीसीसी और वीएस के अलावा अन्य संकलक मौजूद हैं। उदाहरण के लिए QNX और GHS के मन में आते हैं (हालांकि मुझे संदेह है कि QNX का GCC के समान बिल्ड-टाइम परिभाषित है)। इसके अलावा आप अपने GCC चेक में MIPS64 और IA64 आर्किटेक्चर को भूल गए
रोम

14
@ रॉम, निश्चित रूप से 2 से अधिक कंपाइलर और आर्किटेक्चर। इसका मतलब सिर्फ यह है कि इस समस्या से कैसे निपटा जाए, इसका एक नमूना है न कि पूर्ण समाधान।
JaredPar

2
मैं कहता हूं "आमतौर पर"। "आदर्श रूप से" शायद अधिक यथार्थवादी है।
स्टीव जेसप

7
मुझे लगता है कि आपको "#if परिभाषित ( WIN32 ) || परिभाषित (_WIN64)" आदि का उपयोग करना चाहिए
KindDragon

3
#if _WIN32 || _WIN64... #elif __GNUC__... #else # error "Missing feature-test macro for 32/64-bit on this compiler."?
डेविसलर

100
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;
}

2
अगर size_t न तो 4 है और न ही 8 है तो क्या होगा?
जेसपर

16
@ जेस्पर, तो आपको ऊपर के नमूने में लिंक त्रुटि मिलेगी। या आप उस मामले के लिए DoMyOperation को लागू कर सकते हैं
Kirill V. Lyadvinsky

1
एक सहसंबंधी के बजाय क्या मायने रखता है (कुछ विशेष प्रकार के आकार) के परीक्षण के लिए टेम्प्लेट, और यश का चालाक उपयोग।
फिल मिलर

2
इसके लिए size_t का उपयोग करने में सावधानी बरतें। आपके पास ऐसे मुद्दे हो सकते हैं जहां यह सूचक आकार के अनुरूप नहीं है (उदाहरण के लिए एक से अधिक सूचक आकार वाले प्लेटफार्मों पर)।
लोगान कैपल्डो 12

8
मानक कहते हैं कि size_tसिस्टम में किसी भी आवंटित वस्तु के आकार को धारण करने के लिए आकार काफी बड़ा है। आमतौर पर यह वही है जो आप सशर्त संकलन करते समय जानना चाहते हैं। यदि यह वह नहीं है जो आप चाहते हैं, तो आप इस स्निपेट का उपयोग किसी अन्य प्रकार के साथ कर सकते हैं size_t। उदाहरण के लिए, यह हो सकता है void*
किरिल वी। ल्याडविंस्की

44

दुर्भाग्य से, एक क्रॉस प्लेटफॉर्म, क्रॉस कंपाइलर वातावरण में, संकलित समय पर इसे शुद्ध रूप से करने के लिए कोई विश्वसनीय तरीका नहीं है।

  • _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 महीने पहले था)।


sizeof(void*)क्या इसे संकलन समय या रन-टाइम पर हल किया जाता है? यदि यह संकलन समय पर है, तो रन-टाइम पर चेक हमेशा रहेगा if(8!=8){...}
अमीन

@ यह रन-टाइम पर हल हो गया है। इस चेक का उद्देश्य यह सुनिश्चित करना है कि यदि बिटनेस अपेक्षित नहीं है तो प्रोग्राम एक उचित त्रुटि के साथ बाहर निकलता है। इसका मतलब यह है कि डेवलपर इस त्रुटि को तुरंत ठीक कर सकता है, न कि बाद में पॉप अप करने वाले सूक्ष्म कीड़ों का निदान करने की कोशिश कर रहा है।
कंटैंगो

3
4 साल बाद (अगर यह पहले संभव था पता नहीं है) आप संकलन समय के लिए एक स्थिर ज़ोर का उपयोग कर चलाने के समय जांच में बदल सकते हैं: static_assert(sizeof(void*) == 4);। अब यह सब संकलन समय पर किया जाता है :)
Al.G.

1
static_assert(sizeof(void*) * CHAR_BIT == 32)अधिक अभिव्यंजक और तकनीकी रूप से सही है (हालांकि मुझे कोई भी वास्तुकला नहीं पता है जहां बाइट्स में 8 की तुलना में बिट्स की अलग-अलग मात्रा होती है)
Xeverous

1
नीचे मेरा जवाब भी देखें जो धाराप्रवाह सी ++ से " बेहतर मैक्रोज़, बेहतर झंडे " के साथ इस उत्कृष्ट उत्तर को जोड़ता है ।
धातु

30

आप में परिभाषित मैक्रोज़ का उपयोग करने में सक्षम होना चाहिए 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

Microsoft के संकलक के कुछ (सभी?) संस्करण नहीं आते हैं stdint.h। निश्चित नहीं कि क्यों, क्योंकि यह एक मानक फ़ाइल है। यहाँ एक संस्करण है जिसका आप उपयोग कर सकते हैं:http://msinttypes.googlecode.com/svn/trunk/stdint.h


4
Microsoft के लिए कोई stdint.h क्यों नहीं? क्योंकि इसे C99 मानक के साथ पेश किया गया था, और लगता है कि Microsoft C99 से सबसे आसान सामान को कार्यान्वित करने के लिए एक सक्रिय विरोधाभास है। यहां तक ​​कि आसान पुस्तकालय सामान जिसमें बिना संकलक परिवर्तन की आवश्यकता होती है। यहां तक ​​कि सी ++ के लिए संकलन करते समय सामान जो पहले से ही किया जा रहा है (जैसे बयानों के बाद घोषणाएं)। मुझे पता है कि इसे परीक्षण आदि की आवश्यकता है, लेकिन मुझे यह भी पता है कि एमएस को (या एक बार मिल गया) अपने पुस्तकालय का एक अच्छा हिस्सा डिनकुमवेयर / प्लॉजर से मिला, और डिंकमवेयर के पास C99 लाइब्रेरी का सामान था।
माइकल बूर

2
VC ++ 2010 (बीटा 1, वैसे भी) <stdint.h>और है <cstdint>। वर्तमान स्थिति के अनुसार - VC ++ लाइब्रेरी की उत्पत्ति Dinkumware से हुई है (फिर भी - TR1 को वहां से भी लिया गया था), लेकिन जो मुझे VCBlog पर पढ़ना याद आता है, वह /clrसभी MSVC के साथ काम करने के लिए स्वच्छ संकलन करने के लिए काफी महत्वपूर्ण रिफैक्टिंग से गुजरता है। गैर-मानक प्रकार जैसे __int64और इतने पर - यही कारण है कि यह सिर्फ इसे लेने और अगले संकलक संस्करण में डालने के रूप में सरल नहीं है।
पावेल मिनाएव

2
इससे मुझे सही उत्तर मिला, लेकिन मुझे लगता है कि आपको UINT64_MAX की तुलना INT64_MAX से नहीं करनी चाहिए। मैंने SIZE_MAX == UINT64_MAX - समान का उपयोग किया
Arno Duvenhage

15

यह एक शुरुआत के लिए विंडोज पर काम नहीं करेगा। Longs और ints दोनों 32 बिट हैं चाहे आप 32 बिट या 64 बिट विंडो के लिए संकलन कर रहे हैं। मुझे लगता है कि अगर पॉइंटर का आकार 8 बाइट्स है, तो यह जांचना संभव है कि यह अधिक विश्वसनीय मार्ग है।


2
दुर्भाग्य से साइज़ोफ #if निर्देश में निषिद्ध है (यदि आप इसके बारे में सोचते हैं कि प्रीप्रोसेसर के पास बताने का कोई तरीका नहीं है)
EFraim

हां, इसीलिए मैंने इसे साइज़ोफ का उपयोग करने के बजाय एक पॉइंटर के आकार की जांच करने के सुझाव पर छोड़ दिया - मैं इसे अपने सिर के ऊपर से करने के लिए एक पोर्टेबल तरीके के बारे में नहीं सोच सकता ...
18

3
प्रश्न (अभी तक) कहते हैं कि यह करता है पूर्व प्रोसेसर समय में किया जाना चाहिए। पर अनुकूलन के साथ कई / सबसे संकलक मृत कोड को समाप्त करने का एक सभ्य काम करेंगे, भले ही आप इसे "रन टाइम तक छोड़ दें" जैसे टेस्ट के साथ sizeof(void*) == 8 ? Do64Bit() : Do32Bit();। यह अभी भी बाइनरी में अप्रयुक्त फ़ंक्शन को छोड़ सकता है, लेकिन अभिव्यक्ति को "सही" फ़ंक्शन के लिए कॉल करने के लिए संकलित किया जाता है।
स्टीव जेसप

1
@onebyone जो फंक्शन कॉल्स की समस्या को हल करता है, लेकिन क्या होगा अगर मैं एक वैरिएबल को प्लेटफ़ॉर्म पर आधारित एक अलग प्रकार की घोषणा करना चाहता हूं, जिसे प्रीप्रोसेसर पर करना होगा, जब तक कि आप एक से अधिक वेरिएबल्स को घोषित नहीं करना चाहते और एक स्टेटमेंट के आधार पर उनका उपयोग कर सकते हैं अगर वे अप्रयुक्त हैं, तो उन्हें बाहर भी अनुकूलित किया जाएगा, लेकिन कोड में बहुत सुखद नहीं होगा)
फालनाऑन

1
फिर आप सही हैं, एक सशर्त में एक निरंतर अभिव्यक्ति अच्छा नहीं है। किरिल का दृष्टिकोण वही कर सकता है जो आप चाहते हैं, हालांकि:template<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;
स्टीव जेसप

9

आप ऐसा कर सकते हैं:

#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif

1
64-बिट मशीनों पर सी और सी-व्युत्पन्न भाषाओं के लिए कई प्रोग्रामिंग वातावरणों में, "इंट" चर अभी भी 32 बिट्स चौड़े हैं, लेकिन लंबे पूर्णांक और संकेत 64 बिट्स चौड़े हैं। इन्हें LP64 डेटा मॉडल के रूप में वर्णित किया गया है। unix.org/version2/whatsnew/lp64_wp.html
हेमीज़

6
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

7
यह कोड सही नहीं है। 64-बिट पर _WIN32 और _WIN64 दोनों को परिभाषित किया गया है। यदि आप इसे चारों ओर घुमाते हैं (_WIN64 के लिए पहले जांच) तो यह निश्चित रूप से काम करता है।
बर्ट्र

4

"64 बिट में संकलित" C ++ में अच्छी तरह से परिभाषित नहीं है।

C ++ इंट, लॉन्ग और जैसे साइज के लिए केवल निम्न सीमा निर्धारित करता है void *। इस बात की कोई गारंटी नहीं है कि 64 बिट प्लेटफॉर्म के लिए संकलित होने पर भी इंट 64 बिट है। मॉडल उदाहरण के लिए अनुमति देता है 23 बिट intऔरsizeof(int *) != sizeof(char *)

64 बिट प्लेटफार्मों के लिए विभिन्न प्रोग्रामिंग मॉडल हैं

आपका सर्वश्रेष्ठ दांव एक मंच विशिष्ट परीक्षण है। आपका दूसरा सबसे अच्छा, पोर्टेबल निर्णय में और अधिक विशिष्ट होना चाहिए क्या 64 बिट है।


3

आपका दृष्टिकोण बहुत दूर बंद नहीं था, लेकिन आप केवल जाँच कर रहे हैं कि क्या 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

सिद्धांत रूप में, आप इसे किसी भी प्रकार के लिए कर सकते हैं जिसके लिए आपके पास अधिकतम मान के साथ एक सिस्टम परिभाषित मैक्रो है।

ध्यान दें, कि मानक को long long32 बिट सिस्टम पर भी कम से कम 64 बिट होना चाहिए ।


UINT_MAX और ULONG_MAX को परिभाषित करने के लिए एक बात ध्यान रखने योग्य है, आप शायद #include <limits.h>अपने #ifपरीक्षणों से पहले कहीं होना चाहते हैं ।
एलेक्सिस विल्के

3

लोगों ने पहले से ही तरीकों का सुझाव दिया है जो यह निर्धारित करने की कोशिश करेंगे कि क्या कार्यक्रम में संकलित किया जा रहा है 32-bitया नहीं 64-bit

और मैं यह जोड़ना चाहता हूं कि आप static_assertयह सुनिश्चित करने के लिए c ++ 11 सुविधा का उपयोग कर सकते हैं कि वास्तुकला वह है जो आप सोचते हैं कि यह ("आराम करने के लिए") है।

तो जिस स्थान पर आप मैक्रोज़ को परिभाषित करते हैं:

#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

static_assert(sizeof(void*) * CHAR_BIT == 32)अधिक अभिव्यंजक और तकनीकी रूप से सही है (हालांकि मुझे कोई भी वास्तुकला नहीं पता है जहां बाइट्स में 8 की तुलना में बिट्स की अलग-अलग मात्रा होती है)
Xeverous

2

नीचे कोड अधिकांश वर्तमान वातावरणों के लिए ठीक काम करता है:

  #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

3
ध्यान दें कि _WIN64आपको पहले से ही शामिल करना आवश्यक है <windows.h>। : विजुअल C ++ के साथ, यह अंतर्निहित संकलक परिभाषित करता है उपयोग करने के लिए बेहतर है _M_IX86, _M_X64, _M_ARM, _M_ARM64, आदि
चक Walbourn

PowerPC के लिए, मैं आप के लिए जांच करने की जरूरत का मानना है कि __ppc64__, __powerpc64__, और _ARCH_PPC64। वह AIX और अन्य प्लेटफार्मों को भी पकड़ता है।
jww

1

यदि आप अपने सभी वातावरणों में प्रोजेक्ट कॉन्फ़िगरेशन का उपयोग कर सकते हैं, तो यह 64- और 32-बिट प्रतीक को परिभाषित करना आसान बना देगा। तो आप इस तरह परियोजना विन्यास होगा:

32-बिट डीबग
32-बिट रिलीज़
64-बिट डीबग
64-बिट रिलीज़

संपादित करें: ये सामान्य कॉन्फ़िगरेशन हैं, लक्षित कॉन्फ़िगरेशन नहीं। उन्हें जो चाहो बुला लो।

यदि आप ऐसा नहीं कर सकते, तो मुझे जेरेड का विचार पसंद है।


या दो को मिलाएं: आपके द्वारा जाने वाले कंपाइलरों पर कॉन्फ़िगरेशन का ऑटो-डिटेक्ट करें, लेकिन प्रोजेक्ट / कमांड-लाइन / जो कि बिना पहचाने गए कंपाइलरों में निर्दिष्ट #define को देखने के लिए वापस आते हैं।
स्टीव जेसप

4
ओपी के क्रॉस प्लेटफॉर्म सवाल के साथ मदद करने के लिए आपका विज़ुअलस्टडियो-विशिष्ट समाधान कैसे हो रहा है ??
एलेक्स टिंगल

3
@ जॉन: हम्म। वे परिभाषा के आधार पर किसी भी प्रकार के क्रॉस-प्लेटफॉर्म वातावरण में समर्थित नहीं हैं । जब तक यह एमएस के क्रॉस-प्लेटफॉर्म की परिभाषा नहीं है - विंडोज के नए स्वादों पर काम करता है।
19

1
@ एफ़रिम: हाँ, आप 32- या 64-बिट वीएस का उपयोग कर सकते हैं, लेकिन यह वह नहीं है जिसके बारे में मैं बात कर रहा हूं। जेनेरिक प्रोजेक्ट कॉन्फ़िगरेशन, और जो नाम मैंने उन्हें असाइन किए हैं, उनका प्लेटफ़ॉर्म से कोई लेना-देना नहीं है। यदि प्रोजेक्ट कॉन्फ़िगरेशन वीएस-विशिष्ट हैं, तो यह शर्म की बात है क्योंकि वे बहुत काम कर रहे हैं।
जॉन सिगेल

1
मुझे लगता है कि यह सही उत्तर है। यह ऑटोडेटेक्ट चीजों की कोशिश करने से ज्यादा विश्वसनीय है। सभी आईडीई जो मैंने कभी किसी रूप में इस सुविधा का समर्थन करते देखा है, और मैंने शर्त लगाई है कि मैंने कभी भी इसका समर्थन नहीं देखा है। यदि आप मेक, या जैम का उपयोग करते हैं, तो आप कमांड लाइन से वेरिएबल सेट कर सकते हैं, जब सामान्य तरीके से, इनवॉच किया जाता है।

1

मैं 32-बिट और 64-बिट स्रोतों को विभिन्न फ़ाइलों में रखूँगा और फिर बिल्ड सिस्टम का उपयोग करके उपयुक्त स्रोत फ़ाइलों का चयन करूँगा।


2
यह बिल्ड सिस्टम के समान होगा जो आपको एक झंडा देगा जैसे कि -DBUILD_64BIT। अक्सर, कुछ चीजें 32 और 64 बिट दोनों के समान होती हैं, इसलिए इसे एक ही फाइल में रखना काफी व्यावहारिक हो सकता है।
अलेक्सिस विलके

जुड़वां स्रोत फ़ाइलों को बनाए रखना त्रुटि प्रवण है। IMO यहां तक ​​कि एक बहुत बड़ा #if bit64 .. सभी कोड, 64 बिट #else के लिए .. सभी कोड, 32bit #endif के लिए बेहतर है। (# अगर मेरे विचार से लाइन-बाय-लाइन आदर्श है)
शराब बनाने वाला

1

कॉन्टैंगो के उत्कृष्ट उत्तर के ऊपर उधार लेना और धाराप्रवाह सी ++ से " बेहतर मैक्रो, बेहतर झंडे " के साथ संयोजन करना , आप कर सकते हैं:

// 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://stackoverflow.com/a/12338526/201787
#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() );

0

मैं इस उत्तर को उपयोग के मामले के रूप में जोड़ रहा हूं और एक अन्य उत्तर में वर्णित रनटाइम-चेक के लिए पूर्ण उदाहरण ।

यह वह दृष्टिकोण है जो मैं अंत-उपयोगकर्ता को बताने के लिए ले रहा हूं कि क्या कार्यक्रम 64-बिट या 32-बिट (या अन्य, उस मामले के लिए) के रूप में संकलित किया गया था:

version.h

#ifndef MY_VERSION
#define MY_VERSION

#include <string>

const std::string version = "0.09";
const std::string arch = (std::to_string(sizeof(void*) * 8) + "-bit");

#endif

test.cc

#include <iostream>
#include "version.h"

int main()
{
    std::cerr << "My App v" << version << " [" << arch << "]" << std::endl;
}

संकलन और परीक्षण

g++ -g test.cc
./a.out
My App v0.09 [64-bit]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.