সি ++ এ 32 বনাম 64 বিট নির্ধারণ করা হচ্ছে


136

আমি 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আপনার বন্ধু হতে পারে, বা আপনার নিজের কিছু উপযুক্ত টাইপডেফ বিকাশ করতে পারে।
ফিল মিলার

এই পরীক্ষাটি ভিজ্যুয়াল স্টুডিও 2008 এসপি 1 তে কাজ করছে বলে মনে হচ্ছে না। এটি 32-বিট এবং 64-বিট উভয়ের জন্য "IS64BIT" এ আটকে যায়।
কনটাঙ্গো

উত্তর:


99

দুর্ভাগ্যক্রমে এমন কোনও ক্রস প্ল্যাটফর্ম ম্যাক্রো নেই যা বড় সংকলকগুলিতে 32/64 বিট সংজ্ঞায়িত করে। আমি এটি করার সবচেয়ে কার্যকর উপায়টি খুঁজে পেয়েছি।

প্রথমে আমি নিজের উপস্থাপনাটি বেছে নিই। আমি ENVIRONMENT64 / এনভায়রনমেন্ট 32 পছন্দ করি। তারপরে আমি জানতে পারি যে সমস্ত বড় সংকলক এটি 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 এর অনুরূপ বিল্ড-টাইম জিসিসিতে সংজ্ঞায়িত হয়েছে)। এছাড়াও আপনি আপনার জিসিসি চেক MIPS64 এবং ia64 আর্কিটেকচারের ভুলে গেছি
যাযাবর

14
@ রোম, অবশ্যই 2 টিরও বেশি সংকলক এবং আর্কিটেকচার। এটি কেবলমাত্র কোনও সমস্যার সমাধান না করে কীভাবে এই সমস্যার দিকে যাওয়া যায় তার একটি নমুনা বোঝানো।
জারেডপাড়

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
সাইজ_টি 4 বা 8 না হলে কী হবে?
জেস্পার

16
@ জেস্পার, তারপরে আপনি উপরের নমুনায় লিঙ্ক ত্রুটি পাবেন। বা আপনি সেই মামলার জন্য ডোমাইঅপারেশন বাস্তবায়ন করতে পারেন
কিরিল ভি লিয়াডভিনস্কি

1
কোন বিষয় সম্পর্কিত (কিছু নির্দিষ্ট ধরণের আকার) যা সম্পর্কিত তা পরীক্ষা করার জন্য টেমপ্লেটগুলির ধীরে ধীরে ব্যবহার এবং কুডোস corre
ফিল মিলার

2
এর জন্য সাইজ_টি ব্যবহার করে যত্নশীল। আপনার কাছে সমস্যা থাকতে পারে যেখানে এটি পয়েন্টার আকারের সাথে উদাহরণস্বরূপ নয় (যেমন একাধিক পয়েন্টার আকারের প্ল্যাটফর্মগুলিতে)।
লোগান ক্যাপাল্ডো

8
স্ট্যান্ডার্ড বলছে যে আকারে size_tসিস্টেমের মধ্যে যে কোনও বরাদ্দকৃত বস্তুর আকার ধরে রাখতে যথেষ্ট বড়। শর্তসাপেক্ষ সংকলনের সময় সাধারণত এটিই আপনি জানতে চান। যদি এটি আপনি না চান তবে আপনি এই স্নিপেটটি পরিবর্তে অন্য কোনও ধরণের ব্যবহার করতে পারেন size_t। উদাহরণস্বরূপ, এটি হতে পারে void*
কিরিল ভি। লায়াডভিনস্কি

44

দুর্ভাগ্যক্রমে, ক্রস প্ল্যাটফর্মে, ক্রস সংকলক পরিবেশে, সংকলনের সময় বিশুদ্ধভাবে এটি করার কোনও একক নির্ভরযোগ্য পদ্ধতি নেই।

  • _WIN32 এবং _WIN64 উভয়ই মাঝে মাঝে উভয়ই করতে পারে পারে, যদি প্রকল্পের সেটিংসটি ত্রুটিযুক্ত বা দূষিত হয় (বিশেষত ভিজ্যুয়াল স্টুডিও 2008 এসপি 1 তে)।
  • একটি প্রকল্প কনফিগারেশন ত্রুটির কারণে "উইন 32" লেবেলযুক্ত একটি প্রকল্প 64-বিটে সেট করা যেতে পারে।
  • ভিজ্যুয়াল স্টুডিও ২০০৮ এসপি 1-তে, অনেক সময় ইন্টেলিসেন্স বর্তমান # ডিফাইন অনুসারে কোডের সঠিক অংশগুলি ধূসর করে না। এটি সংকলনের সময় # ডিফাইনটি ঠিক কীভাবে ব্যবহৃত হচ্ছে তা দেখতে অসুবিধা হয়।

অতএব, একমাত্র নির্ভরযোগ্য পদ্ধতি হ'ল 3 টি সহজ চেক একত্রিত করা :

  • 1) সংকলন সময় সেট , এবং;
  • 2) রানটাইম চেক , এবং;
  • 3) দৃust় সংকলন সময় চেক

সাধারণ চেক ১/৩: সময় নির্ধারণ করুন

প্রয়োজনীয় # ডিফাইন ভেরিয়েবল সেট করতে যে কোনও পদ্ধতি বেছে নিন । আমি @ জারেডপাড় থেকে পদ্ধতিটি পরামর্শ দিচ্ছি:

// 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 বছর পরে (এটি আগে সম্ভব ছিল কিনা তা জানেন না) আপনি স্ট্যাটিক প্রতিস্থাপন ব্যবহার করে রান-টাইম চেকটি সংকলন-সময়কে রূপান্তর করতে পারেন: স্ট্যাটিক_সেসার্ট (মাপের (অকার্যকর *) == 4) ;. এখন এটি সমস্ত সংকলন সময়ে সম্পন্ন হয়েছে :)

অ্যাপেন্ডিক্স এ

অজ্ঞাতসারে, উপরের নিয়মগুলি আপনার পুরো কোডবেসটিকে আরও নির্ভরযোগ্য করে তুলতে অভিযোজিত হতে পারে:

  • প্রতি যদি () বিবৃতিটি "অন্য" -এ শেষ হয় যা সতর্কতা বা ত্রুটি উত্পন্ন করে।
  • প্রতিটি সুইচ () বিবৃতি একটি "ডিফল্ট:" এ শেষ হয় যা সতর্কতা বা ত্রুটি উত্পন্ন করে।

এটি ভালভাবে কাজ করার কারণটি হ'ল এটি আপনাকে প্রতি একক কেসটি আগে থেকেই ভাবতে বাধ্য করে এবং সঠিক কোডটি কার্যকর করতে "অন্য" অংশে (কখনও কখনও ত্রুটিযুক্ত) যুক্তির উপর নির্ভর না করে।

আমি এই কৌশলটি ব্যবহার করেছি (অনেকের মধ্যে) একটি 30,000 লাইনের প্রকল্পটি লিখতে যা প্রথম প্রযোজনায় স্থাপনের দিন থেকেই নির্দোষভাবে কাজ করেছিল (এটি ছিল 12 মাস আগে)।


sizeof(void*)এটি সংকলন সময় বা রান-টাইমে সমাধান করা হয়? যদি এটি সংকলন সময়ে হয় তবে রান-টাইমে চেক সর্বদা থাকবে if(8!=8){...}
আমিন

@ameen এটি রান-টাইমে সমাধান করা হয়েছে। এই চেকটির উদ্দেশ্যটি নিশ্চিত করা হয় যে যদি সাক্ষ্য প্রত্যাশিত হয় না, তবে প্রোগ্রামটি উপযুক্ত ত্রুটির সাথে উপস্থিত হয়। এর অর্থ হ'ল বিকাশকারী পরবর্তী সময়ে পপ আপ হওয়া সূক্ষ্ম বাগগুলি সনাক্ত করার চেষ্টা না করে এই ত্রুটিটি তত্ক্ষণাত্ ঠিক করতে পারে।
কনটাঙ্গো

3
4 বছর পর (যদি এটা আগে সম্ভব ছিল জানি না) আপনি কম্পাইল-টাইম এক স্ট্যাটিক জাহির ব্যবহার রান-টাইম চেক রূপান্তর করতে পারেন: static_assert(sizeof(void*) == 4);। সংকলনের সময় এখন এটি শেষ হয়েছে :)
আল.জি.

1
static_assert(sizeof(void*) * CHAR_BIT == 32)আরও অভিব্যক্তিপূর্ণ এবং প্রযুক্তিগতভাবে সঠিক (যদিও আমি এমন কোনও আর্কিটেকচার জানি না যেখানে 8 এর চেয়ে বাইটের বিট আলাদা পরিমাণে রয়েছে)
জেরভেরাস

1
আরও দেখুন নীচের আমার উত্তর যে সম্মিলন "এর সাথে এই চমৎকার উত্তর বেটার ম্যাক্রো, ভাল পতাকা সাবলীল C থেকে" ++,।
ধাতব

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

মাইক্রোসফ্ট সংকলকের কিছু (সমস্ত?) সংস্করণ আসে না stdint.h । নিশ্চিত নয় কেন, কারণ এটি একটি স্ট্যান্ডার্ড ফাইল। আপনি ব্যবহার করতে পারেন এমন একটি সংস্করণ এখানে:http://msinttypes.googlecode.com/svn/trunk/stdint.h


4
মাইক্রোসফ্টের জন্য কেন কোনও স্ট্যান্ডিন্টহ? কারণ এটি সি 99 স্ট্যান্ডার্ডের সাথে প্রবর্তিত হয়েছিল, এবং মাইক্রোসফ্টের মনে হচ্ছে সি 99 এর থেকে সহজতম স্টাফ প্রয়োগ করার ক্ষেত্রে একটি সক্রিয় বিদ্বেষ রয়েছে। এমনকি সহজ লাইব্রেরি স্টাফ যাতে কোন সংকলক পরিবর্তন প্রয়োজন। এমনকি সি ++ (বিবৃতি দেওয়ার পরে ঘোষণার মতো) সংকলনের সময় ইতিমধ্যে যে জিনিসগুলি সম্পন্ন করা হচ্ছে তাও। আমি জানি যে এটির পরীক্ষার দরকার আছে ইত্যাদি but
মাইকেল বুড় 19

2
ভিসি ++ ২০১০ (বিটা ১, যাইহোক) রয়েছে <stdint.h>এবং আছে <cstdint>। বর্তমান পরিস্থিতি হিসাবে - ভিসি ++ গ্রন্থাগারটি ডিনকামওয়্যার থেকে উদ্ভূত হয়েছে (এখনও করে - টিআর 1 সেখান থেকেও নেওয়া হয়েছিল) তবে ভিসিবিগ-এ আমি যে পড়াটি স্মরণ করি তা থেকে, এটি /clrএমএসভিসির সাথে সম্পূর্ণরূপে সংকলন করার জন্য যথেষ্ট উল্লেখযোগ্য রিফ্যাক্টরিংয়ের মধ্য দিয়ে যায় MS মানহীন প্রকারের মতো __int64, এবং এই জাতীয় - যে কারণে এটি নেওয়া এবং এটি পরবর্তী সংকলক সংস্করণে রাখার মতো সহজ নয়।
পাভেল মিনায়েভ

2
এটি আমাকে সঠিক উত্তরের দিকে নিয়ে গেছে, তবে আমি মনে করি আপনার তুলনা করা উচিত UINT64_MAX INT64_MAX নয়। আমি SIZE_MAX == UINT64_MAX ব্যবহার করেছি - সম্ভবত একই
আর্নো দুভেনহেজ

15

এটি আরম্ভের জন্য উইন্ডোজে কাজ করবে না। লং এবং ইনস উভয়ই 32 বিট যা আপনি 32 বিট বা 64 বিট উইন্ডোর জন্য সংকলন করছেন কিনা। আমি মনে করব একটি পয়েন্টারের আকার 8 বাইট কিনা সম্ভবত পরীক্ষা করা আরও নির্ভরযোগ্য একটি রুট।


2
দুর্ভাগ্যক্রমে # টি নির্দেশিকায় আকারটি নিষিদ্ধ করা হয়েছে (যদি আপনি এটির বিষয়ে চিন্তা করেন তবে
প্রিপ্রোসেসরটি

হ্যাঁ, এ কারণেই আমি আকারটি ব্যবহারের চেয়ে পয়েন্টারের আকার পরীক্ষা করার পরামর্শ দিয়েছিলাম - আমি আমার মাথার উপরের দিক থেকে এটি করার কোনও পোর্টেবল উপায় ভাবতে পারি না ...
ম্যাটনিউপোর্ট

3
প্রশ্ন না (এখনও) বলে নেই হয়েছে প্রাক প্রসেসর সময়ে কাজ করতে হবে। উপর অপ্টিমাইজেশান সঙ্গে অনেক / সবচেয়ে কম্পাইলার এমনকি যদি তোমার মত একটি পরীক্ষা সঙ্গে "এটি চালানোর সময় পর্যন্ত ছেড়ে" মৃত কোড দূর একটি শালীন কাজ করবে sizeof(void*) == 8 ? Do64Bit() : Do32Bit();। এটি বাইনারিটিতে একটি অব্যবহৃত ফাংশনটি এখনও ছেড়ে দিতে পারে, তবে অভিব্যক্তিটি সম্ভবত "ডান" ফাংশনের একটি কলটিতে সংকলিত হয়েছে।
স্টিভ জেসপ

1
@ অণবোন যা ফাংশন কলগুলির সমস্যার সমাধান করে, তবে আমি যদি প্ল্যাটফর্মের ভিত্তিতে কোনও ভেরিয়েবলকে ভিন্ন ধরণের ঘোষণা করতে চাই, তবে আপনি যদি একাধিক ভেরিয়েবল ঘোষণা করতে না চান এবং কোনও if স্টেটমেন্টের ভিত্তিতে সেগুলি ব্যবহার না করেন তবে প্রিপ্রোসেসরে এটি করা দরকার ( এগুলি যদি অব্যবহৃত হয় তবে এটি অপ্টিমাইজড হবে, তবে
কোডটিতে

1
তাহলে আপনি ঠিক বলেছেন, শর্তাধীন একটি ধ্রুবক প্রকাশ ভাল নয় expression কিরিলের দৃষ্টিভঙ্গি আপনি যা চান তা করতে পারে, যদিও: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
-৪-বিট মেশিনে সি এবং সি-প্রাপ্ত ভাষার জন্য অনেক প্রোগ্রামিং এনভায়রনমেন্টে, "ইনট" ভেরিয়েবলগুলি এখনও 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
এই কোডটি সঠিক নয়। -৪-বিটে উভয়ই _WIN32 এবং _WIN64 সংজ্ঞায়িত করা হয়েছে। যদি আপনি এটি ঘুরিয়ে দেন (প্রথমে _WIN64 দেখুন) এটি অবশ্যই কাজ করে।
বার্টআর

4

"Bit৪ বিটের মধ্যে সংকলিত" সি ++ এ ভালভাবে সংজ্ঞায়িত করা হয়নি।

সি ++ কেবলমাত্র int, দীর্ঘ এবং এর মতো আকারের জন্য কম সীমাবদ্ধ করে void *। কোনও 64 গিগাবাইট প্ল্যাটফর্মের জন্য সংকলন করার পরেও intটি 64 বিটের কোনও গ্যারান্টি নেই। মডেলটি উদাহরণস্বরূপ 23 বিট intsizeof(int *) != sizeof(char *)

Bit৪ বিট প্ল্যাটফর্মের জন্য বিভিন্ন প্রোগ্রামিং মডেল রয়েছে

আপনার সেরা বাজি একটি প্ল্যাটফর্ম নির্দিষ্ট পরীক্ষা। তোমার দ্বিতীয় সেরা, পোর্টেবল সিদ্ধান্ত আরও নির্দিষ্ট হতে হবে কি 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 longএমনকি 32 বিট সিস্টেমে মান কমপক্ষে 64৪ বিট হওয়া প্রয়োজন be


একটি বিষয় লক্ষণীয়, UINT_MAX এবং ULONG_MAX সংজ্ঞায়িত করার জন্য, আপনি সম্ভবত #include <limits.h>আপনার #ifপরীক্ষার আগে কোথাও থাকতে চান ।
অ্যালেক্সিস উইলকে

3

মানুষ ইতিমধ্যে পদ্ধতি নির্ধারণ করতে যদি প্রোগ্রামে কম্পাইল করা হচ্ছে চেষ্টা করবে প্রস্তাব 32-bitবা 64-bit

এবং আমি যুক্ত করতে চাই যে আপনি static_assertআর্কিটেকচারটি যা মনে করেন সেটি ("শিথিল করা") এটি নিশ্চিত করতে আপনি সি ++ 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 এর চেয়ে বাইটের বিট আলাদা পরিমাণে রয়েছে)
জেভারিয়াস

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>। : ভিসুয়াল সি ++ সঙ্গে, এটা বিল্ট-ইন কম্পাইলার সংজ্ঞায়িত ব্যবহার করতে ভালো _M_IX86, _M_X64, _M_ARM, _M_ARM64, ইত্যাদি
চাক Walbourn

পাওয়ারপিসি জন্য, আমি তোমার জন্য চেক করতে হবে বিশ্বাস __ppc64__, __powerpc64__এবং _ARCH_PPC64। এটি এআইএক্স এবং অন্যান্য প্ল্যাটফর্মগুলিও ধরা দেয়।
jwww

1

আপনি যদি আপনার সমস্ত পরিবেশে প্রকল্প কনফিগারেশন ব্যবহার করতে পারেন তবে এটি একটি 64- এবং 32-বিট প্রতীককে সংজ্ঞায়িত করা সহজ করে তুলবে। সুতরাং আপনার মতো প্রকল্প কনফিগারেশন থাকতে হবে:

32-বিট ডিবাগ
32-বিট প্রকাশ
64-বিট ডিবাগ
64-বিট রিলিজ

সম্পাদনা: এগুলি জেনেরিক কনফিগারেশন, লক্ষ্যযুক্ত কনফিগারেশন নয়। আপনি যা চান তাদের কল করুন।

যদি আপনি এটি না করতে পারেন তবে আমার জ্যারেডের ধারণাটি পছন্দ হয়েছে।


বা দুটি একত্রিত করুন: আপনার সম্পর্কে জানা সংকলকগুলিতে কনফিগারেশনটি স্বতঃ-সনাক্ত করুন, তবে প্রকল্প / কমান্ড-লাইন / অপরিচিত সনাক্তকারী সংকলকগুলিতে যা কিছু নির্দিষ্ট করা হয়েছে তার জন্য নির্দিষ্ট # ডিফাইনটি দেখতে ফিরে যান।
স্টিভ জেসোপ

4
ওপির ক্রস প্ল্যাটফর্ম প্রশ্নে আপনার ভিজ্যুয়াল স্টুডিও-নির্দিষ্ট সমাধান কীভাবে সহায়তা করবে ??
অ্যালেক্স টিংল

3
@ জন: হুম। তারা ক্রস-প্ল্যাটফর্ম পরিবেশ যে কোন ধরণের সমর্থিত নয় সংজ্ঞা দ্বারা । ক্রস-প্ল্যাটফর্মের এটি এমএসের সংজ্ঞা না থাকলে - উইন্ডোজের নতুন স্বাদে কাজ করে।
EFraim

1
@ ইফ্রাইম: হ্যাঁ, আপনি ভিএস ব্যবহার করে 32- বা 64-বিটকে টার্গেট করতে পারেন, তবে আমি এটি বলছি না। জেনেরিক প্রকল্পের কনফিগারেশন এবং আমি তাদের যে নামগুলি অর্পণ করি, তাদের প্ল্যাটফর্মের সাথে একেবারে কোনও সম্পর্ক নেই। যদি প্রকল্প কনফিগারেশনগুলি ভিএস-নির্দিষ্ট হয়, তবে এটি লজ্জাজনক কারণ তারা খুব সহজ।
জন সেগেল 19

1
আমি মনে করি এটিই সঠিক উত্তর। জিনিসগুলি অটোডেটেক্ট করার চেষ্টা করার চেয়ে এটি আরও নির্ভরযোগ্য। সমস্ত আইডিই আমি এই বৈশিষ্ট্যটি কোনও কোনও আকারে সমর্থন করে দেখেছি এবং আমি এটিকে বাজি দিয়ে দেখি না যে এটি কখনও সমর্থন করে না। আপনি যদি মেক বা জ্যাম ব্যবহার করেন, আপনি সাধারণ ফ্যাশনে ডাকা হলে কমান্ড লাইন থেকে ভেরিয়েবল সেট করতে পারেন।

1

আমি বিভিন্ন ফাইলগুলিতে 32-বিট এবং 64৪-বিট উত্স স্থাপন করব এবং তারপরে বিল্ড সিস্টেমটি ব্যবহার করে উপযুক্ত উত্স ফাইলগুলি নির্বাচন করব।


2
এটি বিল্ড সিস্টেমের মতো আপনাকে একটি পতাকা দেওয়ার মতো হবে -DBUILD_64BIT। প্রায়শই, কিছু জিনিস 32 এবং 64 বিটের উভয়ের সাথে খুব মিল থাকে তাই এটি একই ফাইলে থাকা বেশ ব্যবহারিক হতে পারে।
অ্যালেক্সিস উইলক

দ্বিগুণ উত্স ফাইলগুলি বজায় রাখা ত্রুটি প্রবণ। আইএমও এমনকি একটি বিশাল # বিট 6464 .. সমস্ত কোড, bit৪ বিট # এর জন্য .. সমস্ত কোড, 32 বিবিটের জন্য # এন্ডিফ এর চেয়ে ভাল। (# যদি এর লাইন বাই লাইনটি আমার দৃষ্টিতে আদর্শ)
ব্রিউম্যান্জ 3'18

1

থেকে ধার কন্ট্যাঙ্গো এর উপরে চমৎকার উত্তর এবং "সঙ্গে এটি মিশ্রন বেটার ম্যাক্রো, ভাল পতাকা সাবলীল 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://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]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.