একটি সি ++ প্রোগ্রামে প্রোগ্রামিয়ালি এন্ডিয়েনেস সনাক্তকরণ


211

আপনি কোনও বড়-এন্ডিয়ান বা লিটল-এন্ডিয়ান আর্কিটেকচারে রয়েছেন কিনা তা সনাক্ত করার কোনও প্রোগ্রামিক উপায় আছে? আমার এমন কোড লিখতে সক্ষম হতে হবে যা কোনও ইন্টেল বা পিপিসি সিস্টেমে কার্যকর হবে এবং ঠিক একই কোডটি ব্যবহার করবে (অর্থাত্ শর্তসাপেক্ষ সংকলন নেই)।


4
পরিপূর্ণতার স্বার্থে, এন্ডিয়নেসনেস (সংকলনের সময়) গজানোর চেষ্টা করার বিষয়ে অন্য কারও প্রশ্নের লিঙ্ক এখানে রয়েছে: স্ট্যাকওভারফ্লো
ফয়সাল ভালি

14
সংকলন সময়ে অন্তর্নিহিতা নির্ধারণ করবেন না কেন? এটি রানটাইমে সম্ভবত পরিবর্তন করতে পারে না।
এপ্রিমেট

3
আফাইক, এটি করার কোনও নির্ভরযোগ্য এবং সর্বজনীন উপায় নেই। gcc.gnu.org/ML/gcc-help/2007-07/msg00342.html
ব্যবহারকারী 48956

উত্তর:


174

টাইপ পেনিংয়ের উপর ভিত্তি করে পদ্ধতিটি আমি পছন্দ করি না - এটি প্রায়শই সংকলক দ্বারা সতর্ক করা হবে। ইউনিয়নের পক্ষে ঠিক এটাই!

bool is_big_endian(void)
{
    union {
        uint32_t i;
        char c[4];
    } bint = {0x01020304};

    return bint.c[0] == 1; 
}

নীতিটি অন্যের পরামর্শ অনুসারে টাইপ মামলার সমতুল্য, তবে এটি আরও পরিষ্কার - এবং সি 99 অনুসারে, সঠিক হওয়ার নিশ্চয়তা রয়েছে। সরাসরি পয়েন্টার কাস্টের তুলনায় জিসিসি এটি পছন্দ করে।

সংকলনের সময় এন্ডিয়ানাটি ঠিক করার চেয়ে এটি আরও অনেক ভাল - ওএসের জন্য যা মাল্টি-আর্কিটেকচার সমর্থন করে (উদাহরণস্বরূপ ম্যাক ওএস এক্সে ফ্যাট বাইনারি), এটি পিপিসি / আই 386 উভয়ের জন্যই কাজ করবে, অন্যথায় জিনিসগুলিকে গণ্ডগোল করা খুব সহজ whereas ।


51
আমি একটি পরিবর্তনশীল "বিন্ট" নামকরণ করার প্রস্তাব দিই না :)
এম কে বি

42
আপনি কি নিশ্চিত যে এটি ভালভাবে সংজ্ঞায়িত হয়েছে? সি ++ এ ইউনিয়নের কেবলমাত্র একজন সদস্য একসাথে সক্রিয় হতে পারে - যেমন আপনি এক সদস্যের নাম ব্যবহার করে নিয়োগ করতে পারবেন না এবং অন্যজনকে ব্যবহার করে পড়তে পারবেন না (যদিও লেআউট সামঞ্জস্যপূর্ণ স্ট্রাক্টগুলির ব্যতিক্রম রয়েছে)
ফয়সাল ভালি

27
@ ম্যাট: আমি গুগল দেখেছি এবং মনে হচ্ছে ইংরাজীতে এমন একটি অর্থ রয়েছে যা আমি জানতাম না :)
ডেভিড কর্নিপউ

17
আমি এটি পরীক্ষা করেছি এবং জিসিসি ৪.০.১ এবং জিসিসি ৪.৪.১ উভয় ক্ষেত্রেই এই ফাংশনের ফলাফল সংকলন সময়ে নির্ধারণ করা যেতে পারে এবং একটি ধ্রুবক হিসাবে বিবেচনা করা যেতে পারে। এর অর্থ এই যে এই শাখাগুলি যা কেবলমাত্র এই ফাংশনের ফলাফলের উপর নির্ভর করে এবং কখনও প্ল্যাটফর্মের প্রশ্নে নেওয়া হবে না এমন সংস্থাগুলি হ্রাস পাবে। এটি সম্ভবত htonl এর অনেকগুলি বাস্তবায়নের ক্ষেত্রে সত্য নয়।
সর্বময়

6
এই সমাধানটি কি আসলে বহনযোগ্য? তাহলে কি CHAR_BIT != 8?
জোরজিট

80

আপনি এটি কোনও ইনট সেট করে এবং বিটগুলি মাস্কিংয়ের মাধ্যমে করতে পারেন তবে সম্ভবত সবচেয়ে সহজ উপায় হ'ল বিল্ট ইন নেটওয়ার্ক বাইট কনভার্সন অপস ব্যবহার করা (যেহেতু নেটওয়ার্ক বাইট ক্রম সর্বদা বড় এন্ডিয়ান)।

if ( htonl(47) == 47 ) {
  // Big endian
} else {
  // Little endian.
}

বিট ফিডলিং দ্রুততর হতে পারে তবে এই উপায়টি সহজ, সোজা এবং গণ্ডগোলের পক্ষে অসম্ভব অসম্ভব।


1
নেটওয়ার্ক রূপান্তর অপ্সকে সবকিছুকে বড় এন্ডিয়ান রূপান্তর করতেও ব্যবহার করা যেতে পারে, ফলে জেয়ের অন্যান্য সমস্যাগুলির সমাধান করতে পারে।
ব্রায়ান

6
@ শার্পতুথ - ধীর একটি আপেক্ষিক শব্দ, তবে হ্যাঁ, গতি যদি সত্যিই একটি সমস্যা হয় তবে প্রোগ্রামের শুরুতে এটি একবার ব্যবহার করুন এবং এন্ডিয়েনেসের সাথে একটি বৈশ্বিক পরিবর্তনশীল সেট করুন।
এরিক পেট্রোলেজে

5
এইচটিএনএলের আরও একটি সমস্যা রয়েছে: কিছু প্ল্যাটফর্মগুলিতে (উইন্ডোজ?), এটি সি রানটাইম লাইব্রেরিতে যথাযথভাবে থাকে না, তবে অতিরিক্ত, নেটওয়ার্ক সম্পর্কিত লাইব্রেরি (সকেট, ইত্যাদি ...) থাকে। আপনার যদি অন্যথায় লাইব্রেরির প্রয়োজন না হয় তবে এটি কেবল একটি ফাংশনের ক্ষেত্রে বেশ বাধা।
ডেভিড কর্নিপাউ

7
নোট করুন যে লিনাক্স (জিসিসি) এ, htonl সংকলনের সময় ধ্রুবক ভাঁজ সাপেক্ষে, সুতরাং এই ফর্মটির একটি এক্সপ্রেসনের কোনও রানটাইম ওভারহেড একেবারেই নেই (যেমন এটি ধ্রুবকভাবে 1 বা 0 তে ভাঁজ করা থাকে, এবং তারপরে ডেড-কোড নির্মূলকরণটি মুছে ফেলে
ইফ

2
এছাড়াও, x86 htonl এ ইনলাইন এসেম্ব্লার ব্যবহার করে খুব কার্যকরভাবে প্রয়োগ করা যেতে পারে (এবং এটি লিনাক্স / জিসিসি তে) হতে পারে, বিশেষত যদি আপনি BSWAPঅপারেশনের জন্য সমর্থন সহ কোনও মাইক্রো-আর্কিটেকচার লক্ষ্য করে থাকেন।
বিডনলান

61

দয়া করে এই নিবন্ধটি দেখুন :

আপনার মেশিনের ধরণ কী তা নির্ধারণ করার জন্য এখানে কিছু কোড দেওয়া আছে

int num = 1;
if(*(char *)&num == 1)
{
    printf("\nLittle-Endian\n");
}
else
{
    printf("Big-Endian\n");
}

25
মনে রাখবেন যে এটি অন্তর্নিহিত এবং চরের বিভিন্ন দৈর্ঘ্যের উপর নির্ভর করে, যা প্রায়শই ক্ষেত্রে থাকে তবে গ্যারান্টিযুক্ত নয়।
ডেভিড থর্নলে

10
আমি এমবেডড সিস্টেমে কাজ করেছি যেখানে শর্ট ইন্ট এবং চর একই আকার ছিল ... আমি মনে করতে পারি না যে নিয়মিত ইন্টের আকারও ছিল (2 বাইট) না।
রোমেডোর

2
কেন এই উত্তরটি কেবলমাত্র উত্তরই আমাকে উত্তর দিচ্ছে না যে "
বধূ, ডাব্লুটিএফ

2
@ শিলার্ড ইন্ট অবশ্যই কমপক্ষে বড় হতে হবে তবে চরের জন্য কম সীমাবদ্ধ থাকার জন্য স্ট্যান্ডার্ডের কোনও প্রয়োজন নেই! আপনার যদি টিআই F280x পরিবারের দিকে নজর থাকে তবে আপনি আবিষ্কার করতে পারবেন যে CHAR_BIT 16 এবং আকার (int) == আকারের (চর) যখন আপনি উল্লেখ করেছেন সীমাটি একেবারে ঠিক রাখা হয়েছে ...
Aconcagua

5
Uint8_t এবং uint16_t ব্যবহার করবেন না কেন?
রদ্রিগো

58

আপনি std::endianযদি জিসিসি 8+ বা কলঙ্ক 7+ এর মতো সি ++ 20 সংকলকটিতে অ্যাক্সেস পেয়ে থাকেন তবে আপনি ব্যবহার করতে পারেন ।

নোট: std::endianসালে শুরু <type_traits>কিন্তু সরিয়ে নেওয়া হয়েছে থেকে <bit>2019 সুগন্ধিবিশেষ সভায়। জিসিসি 8, কলং 7, 8 এবং 9 এর মধ্যে রয়েছে <type_traits>জিসি 9+ এবং ক্ল্যাং 10+ এর মধ্যে রয়েছে <bit>

#include <bit>

if constexpr (std::endian::native == std::endian::big)
{
    // Big endian system
}
else if constexpr (std::endian::native == std::endian::little)
{
    // Little endian system
}
else
{
    // Something else
}

5
প্রত্যেকের মতো আমার কাছে সি ++ 17 এবং 20 খসড়া / প্রস্তাবসমূহ অ্যাক্সেস রয়েছে তবে এখন পর্যন্ত কোনও সি ++ 20 সংকলকটি কি কখনও বিদ্যমান?
Xeverous

@ Xeverous এটির জন্য কেবল স্কোপযুক্ত গণনা প্রয়োজন তাই আমার সন্দেহ হয় যে বেশিরভাগ বিক্রেতারা এটি তাদের পূর্ববর্তী পরিবর্তনগুলির হিসাবে তাদের স্টাডলিব বাস্তবায়নে যুক্ত করবে।
ফারাপ

@ Xverous GCC 8 প্রকাশিত হয়েছিল এবং এটি সমর্থন করে supports
লাইবার্টা

প্রশ্নের 30+ উত্তরগুলির মধ্যে, এটি কেবলমাত্র একমাত্র বলে মনে হয়, এটি সম্পূর্ণ নির্ভুল (অন্য উত্তরের সাথে যা অন্তত অংশে কমপক্ষে সঠিক)।
IInspectable

40

এটি সাধারণত সংকলনের সময় করা হয় (বিশেষত পারফরম্যান্সের কারণে) সংকলক থেকে উপলব্ধ হেডার ফাইলগুলি ব্যবহার করে বা নিজের তৈরি করে। লিনাক্সে আপনার কাছে "/usr/incolve/endian.h" শীর্ষক ফাইল রয়েছে


8
আমি বিশ্বাস করতে পারি না এটির চেয়ে বেশি ভোট হয়নি। এটি কোনও সংকলিত প্রোগ্রামের অধীনে শেষের দিকটি পরিবর্তিত হতে চলেছে তাই রানটাইম পরীক্ষার কোনও দরকার নেই।
Dolda2000

@ ডলডা 2000 এটি সম্ভাব্যভাবে এআরএম এন্ডিয়ান মোডগুলি দেখতে পেত।
টাইজয়েড

10
@ টাইজয়েড: না, প্রসেসরের কোনওটি সক্ষম হলেও এমনটি একটি সংকলিত প্রোগ্রামটি সর্বদা এন্ডিয়ান মোডের অধীনে চলবে it
দোলডা 2000

16

আমি অবাক করে দিয়েছি যে কেউ প্রাক-প্রসেসরটি ডিফল্টরূপে সংজ্ঞায়িত করে এমন ম্যাক্রোগুলির উল্লেখ করেনি। যদিও এগুলি আপনার প্ল্যাটফর্মের উপর নির্ভর করে পরিবর্তিত হবে; আপনার নিজের ইন্ডিয়ান-চেকটি লেখার চেয়ে এগুলি বেশ পরিষ্কার are

উদাহরণ স্বরূপ; যদি আমরা অন্তর্নির্মিত ম্যাক্রোগুলি দেখে থাকি যা জিসিসি সংজ্ঞায়িত করে (একটি এক্স 86-64 মেশিনে):

:| gcc -dM -E -x c - |grep -i endian
#define __LITTLE_ENDIAN__ 1

একটি পিপিসি মেশিনে আমি পাই:

:| gcc -dM -E -x c - |grep -i endian
#define __BIG_ENDIAN__ 1
#define _BIG_ENDIAN 1

( :| gcc -dM -E -x c -যাদুটি সমস্ত অন্তর্নির্মিত ম্যাক্রোগুলি ছাপায়)।


7
এই ম্যাক্রোগুলি মোটেও ধারাবাহিকভাবে প্রদর্শিত হয় না। উদাহরণস্বরূপ, রেডাহাট 6 রেপো থেকে জিসিসি ৪.৪.৫-তে, চলমান echo "\n" | gcc -x c -E -dM - |& grep -i 'endian'কিছুই দেয় না, /usr/sfw/binসোলারিসের জিসিসি ৩.৪.৩ ( যাইহোক থেকে ) এই লাইনগুলির সাথে একটি সংজ্ঞা রয়েছে। আমি ভক্স ওয়ার্কস টর্নেডো (জিসিসি ২.৯৯) -ভিএস- ভিএক্স ওয়ার্কস ওয়ার্কবেঞ্চ (জিসিসি ৩.৪.৪) এ একই রকম সমস্যা দেখেছি।
ব্রায়ান ভ্যান্ডেনবার্গ

15

এহম ... এটি আমাকে অবাক করে দেয় যে নুন বুঝতে পেরেছেন যে সংকলকটি কেবল পরীক্ষাকেই অনুকূলিত করবে এবং প্রত্যাবর্তনের মান হিসাবে একটি স্থির ফলাফল দেবে। এটি উপরের সমস্ত কোড উদাহরণগুলি কার্যকরভাবে অকেজো করে তোলে। ফিরে আসবে যে একমাত্র জিনিস সংকলন সময়ে অন্তিমতা! এবং হ্যাঁ, আমি উপরের সমস্ত উদাহরণ পরীক্ষা করেছি। এখানে এমএসভিসি 9.0 (ভিজ্যুয়াল স্টুডিও 2008) এর একটি উদাহরণ রয়েছে।

খাঁটি সি কোড

int32 DNA_GetEndianness(void)
{
    union 
    {
        uint8  c[4];
        uint32 i;
    } u;

    u.i = 0x01020304;

    if (0x04 == u.c[0])
        return DNA_ENDIAN_LITTLE;
    else if (0x01 == u.c[0])
        return DNA_ENDIAN_BIG;
    else
        return DNA_ENDIAN_UNKNOWN;
}

disassembly

PUBLIC  _DNA_GetEndianness
; Function compile flags: /Ogtpy
; File c:\development\dna\source\libraries\dna\endian.c
;   COMDAT _DNA_GetEndianness
_TEXT   SEGMENT
_DNA_GetEndianness PROC                 ; COMDAT

; 11   :     union 
; 12   :     {
; 13   :         uint8  c[4];
; 14   :         uint32 i;
; 15   :     } u;
; 16   : 
; 17   :     u.i = 1;
; 18   : 
; 19   :     if (1 == u.c[0])
; 20   :         return DNA_ENDIAN_LITTLE;

    mov eax, 1

; 21   :     else if (1 == u.c[3])
; 22   :         return DNA_ENDIAN_BIG;
; 23   :     else
; 24   :        return DNA_ENDIAN_UNKNOWN;
; 25   : }

    ret
_DNA_GetEndianness ENDP
END

কেবলমাত্র এই ফাংশনের জন্য কোনও সংকলন-সময় অপ্টিমাইজেশন বন্ধ করা সম্ভব, তবে আমি জানি না। অন্যথায় এটি সমাবেশে হার্ডকোড করা সম্ভব, যদিও এটি বহনযোগ্য নয়। এবং তারপরেও এটি অপ্টিমাইজড হতে পারে। এটি আমাকে ভাবায় যে আমার কিছু সত্যই ক্রেপি এসেমব্লার দরকার, সমস্ত বিদ্যমান সিপিইউ / নির্দেশাবলী সেটগুলির জন্য একই কোডটি প্রয়োগ করুন এবং ভাল .... কিছু মনে করবেন না।

এছাড়াও, এখানে কেউ বলেছিলেন যে রান-টাইমের সময় শেষের দিকটি পরিবর্তন হয় না। ভুল। বাইরে দ্বি-এন্ডিয়ান মেশিন রয়েছে। তাদের পরিণতি সুস্পষ্টভাবে কার্যকর হতে পারে execution এছাড়াও, এখানে কেবল লিটল এন্ডিয়ান এবং বিগ এন্ডিয়ানই নয়, অন্যান্য প্রান্তিকতা (কী শব্দ)।

আমি ঘৃণা করি এবং একই সাথে কোডিং ভালবাসি ...


11
যাইহোক, আপনাকে কি অন্য কোনও প্ল্যাটফর্মে চালানোর জন্য পুনরায় কম্পাইল করতে হবে না?
বোবোবোবো

2
যদিও এটি এমএসভিসির পক্ষে ভাল কাজ করে, এটি সমস্ত পরিস্থিতিতে সমস্ত জিসিসি সংস্করণের জন্য নয়। অতএব, একটি সমালোচনামূলক লুপের ভিতরে একটি "রান-টাইম চেক" সংকলন-সময়ে সঠিকভাবে আন-ব্রাঞ্চ হতে পারে, না। এখানে 100% গ্যারান্টি নেই।
সায়ান

21
বিগ-এন্ডিয়ান x86 প্রসেসরের মতো জিনিস নেই। এমনকি আপনি যদি একটি বিয়ানডিয়ান প্রসেসরে (এআরএম বা এমআইপিএস এর মতো) উবুন্টু চালান তবে ইএলএফ এক্সিকিউটেবলগুলি সর্বদা হয় বড় (এমএসবি) বা সামান্য (এলএসবি) এন্ডিয়ান হয়। কোনও বাইন্ডিয়ান এক্সিকিউটেবল তৈরি করা যায় না তাই রানটাইম চেকের প্রয়োজন হয় না।
Fabel

4
এই পদ্ধতিতে অপ্টিমাইজেশন বন্ধ করতে 'উদ্বায়ী ইউনিয়ন ...' ব্যবহার করুন এটি সংকলককে বলে যে 'ইউ' অন্য কোথাও পরিবর্তন করা যেতে পারে এবং ডেটা লোড করা উচিত
মিশ্মশ্রু

1
এই ফাংশনটির জন্য রানটাইমের সময় আলাদা মানটি অপ্টিমাইজারের তুলনায় গণনা করা হচ্ছে যে এটি বোঝায় যে অপটিমাইজারটি বাগড হয়েছে। আপনি কি বলছেন যে সংকলিত অপ্টিমাইজড বাইনারি কোডের উদাহরণ রয়েছে যা সংকলনের সময় অপ্টিমাইজার (প্রোগ্রাম জুড়ে) দ্বারা করা সুস্পষ্ট অনুমানগুলি সত্ত্বেও কমপক্ষে সেগুলির মধ্যে একটির সাথে অসম্পূর্ণ বলে মনে হচ্ছে এমন দুটি পৃথক আর্কিটেকচারের উপর বহনযোগ্যভাবে চলতে পারে port আর্কিটেকচারের?
স্কট

13

কোন int ভেরিয়েবল ঘোষণা করুন:

int variable = 0xFF;

এখন এর বিভিন্ন অংশে চর * পয়েন্টার ব্যবহার করুন এবং সেই অংশগুলিতে কী আছে তা পরীক্ষা করুন।

char* startPart = reinterpret_cast<char*>( &variable );
char* endPart = reinterpret_cast<char*>( &variable ) + sizeof( int ) - 1;

কোনটি 0xFF বাইটে নির্দেশ করে তার উপর নির্ভর করে এখন আপনি আধ্যাত্মিকতা সনাক্ত করতে পারবেন। এর জন্য আকারের (ইনট)> মাপের (চর) প্রয়োজন তবে আলোচিত প্ল্যাটফর্মগুলির জন্য এটি অবশ্যই সত্য।


8

আরও তথ্যের জন্য, আপনি এই কোডেপ্রজেক্ট নিবন্ধটি এন্ডিয়ানিয়েন্স সম্পর্কিত প্রাথমিক ধারণাগুলি পরীক্ষা করে দেখতে চাইতে পারেন :

রান টাইমে এন্ডিয়ান ধরণের পরীক্ষা করতে কীভাবে?

কম্পিউটার অ্যানিমেশন এফএকিউতে বর্ণিত হিসাবে, আপনার কোডটি সামান্য- বা বিগ-এন্ডিয়ান সিস্টেমে চলছে কিনা তা দেখতে আপনি নীচের ফাংশনটি ব্যবহার করতে পারেন: সঙ্কুচিত

#define BIG_ENDIAN      0
#define LITTLE_ENDIAN   1
int TestByteOrder()
{
   short int word = 0x0001;
   char *byte = (char *) &word;
   return(byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
}

এই কোডটি 161-বিট পূর্ণসংখ্যার জন্য 0001h মান নির্ধারণ করে। তারপরে একটি সংক্ষিপ্ত পয়েন্টারটি পূর্বে পূর্ণসংখ্য মানের প্রথম (সর্বনিম্ন-তাত্পর্যপূর্ণ) বাইটে নির্দেশিত হয়। যদি পূর্ণসংখ্যার প্রথম বাইট 0x01h হয়, তবে সিস্টেমটি লিটল-এন্ডিয়ান (0x01h সর্বনিম্ন, বা সর্বনিম্ন-উল্লেখযোগ্য, ঠিকানাতে থাকে) address যদি এটি 0x00 ঘন্টা হয় তবে সিস্টেমটি বিগ-এন্ডিয়ান।


6

সি ++ উপায়টি বুস্ট ব্যবহার করা হয়েছে পন্থাটি , যেখানে প্রিপ্রোসেসর চেক এবং ক্যাসেটগুলি খুব ভাল-পরীক্ষিত লাইব্রেরির ভিতরেই বগিযুক্ত করা হয়।

প্রিডেফ লাইব্রেরি (বুস্ট / প্রিডিএফ।) চারটি ভিন্ন ধরণের এডিয়েননেসকে স্বীকৃতি দেয়

Endian লাইব্রেরী সি ++ মান জমা দিতে হবে পরিকল্পিত, এবং endian সংবেদনশীল ডেটা অপারেশনের বিভিন্ন ধরণের সমর্থন করা হয়।

উপরের উত্তরে বর্ণিত হিসাবে, এন্ডিয়ানসনেস সি ++ ২০ এর একটি অংশ হবে।


1
এফওয়াইআই, "চার ধরণের বিভিন্ন প্রকারের অন্তর্নিহিততা" লিঙ্কটি নষ্ট হয়ে গেছে,
রেমি লিউউ

স্থির এবং উইকি তৈরি
fuzzyTew

5

আপনি যদি এমন কোনও ফ্রেমওয়ার্ক ব্যবহার করেন না যা পিপিসি এবং ইন্টেল প্রসেসরগুলিতে পোর্ট করা হয়েছে, আপনাকে শর্তযুক্ত সংকলন করতে হবে, যেহেতু পিপিসি এবং ইন্টেল প্ল্যাটফর্মগুলিতে সম্পূর্ণরূপে আলাদা আলাদা হার্ডওয়্যার আর্কিটেকচার, পাইপলাইন, বাস ইত্যাদি রয়েছে। এটি সমাবেশ কোডটি সম্পূর্ণরূপে আলাদা করে দেয় nd দুই.

পরিণতি সন্ধানের জন্য, নিম্নলিখিতগুলি করুন:

short temp = 0x1234;
char* tempChar = (char*)&temp;

আপনি হয় 0x12 বা 0x34 হতে টেম্পচার পাবেন, যা থেকে আপনি শেষের বিষয়টি জানতে পারবেন।


3
এটি সংক্ষিপ্ত হওয়ার উপর নির্ভর করে ঠিক 2 বাইট যা গ্যারান্টিযুক্ত নয়।
শার্পথুথ

3
যদিও এই প্রশ্নে দেওয়া দুটি আর্কিটেকচারের উপর ভিত্তি করে এটি বেশ নিরাপদ বাজি লাগবে।
দেমিন

8
অন্য প্ল্যাটফর্মে সংক্ষিপ্ত হওয়ার চেয়ে পৃথক হওয়ার বিরুদ্ধে ভবিষ্যতের প্রমাণ অন্তর্ভুক্ত করুন stdint.hএবং ব্যবহার করুন int16_t
ডেনিস স্কিডমোর

4

আমি এরকম কিছু করব:

bool isBigEndian() {
    static unsigned long x(1);
    static bool result(reinterpret_cast<unsigned char*>(&x)[0] == 0);
    return result;
}

এই লাইনের পাশাপাশি, আপনি একটি সময় দক্ষ কার্য পাবেন যা কেবল একবার গণনা করে।


আপনি এটি ইনলাইন করতে পারেন? নিশ্চিত নয় যে ইনলাইন স্থিতিশীল ভেরিয়েবলগুলির একাধিক মেমরি ব্লক সৃষ্টি করে
aah134

4

উপরে উল্লিখিত হিসাবে, ইউনিয়ন কৌশল ব্যবহার করুন।

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

নিছক এন্ডিয়ান পরীক্ষা বোরিং হওয়ার কারণে, এখানে (টেমপ্লেট) ফাংশন যায় যা হোস্ট আর্কিটেকচার নির্বিশেষে আপনার স্পেস অনুযায়ী সালিশী পূর্ণসংখ্যার ইনপুট / আউটপুটকে ফ্লিপ করবে।

#include <stdint.h>

#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0

template <typename T>
T endian(T w, uint32_t endian)
{
    // this gets optimized out into if (endian == host_endian) return w;
    union { uint64_t quad; uint32_t islittle; } t;
    t.quad = 1;
    if (t.islittle ^ endian) return w;
    T r = 0;

    // decent compilers will unroll this (gcc)
    // or even convert straight into single bswap (clang)
    for (int i = 0; i < sizeof(r); i++) {
        r <<= 8;
        r |= w & 0xff;
        w >>= 8;
    }
    return r;
};

ব্যবহার:

প্রদত্ত এন্ডিয়ান থেকে হোস্টে রূপান্তর করতে, ব্যবহার করুন:

host = endian(source, endian_of_source)

হোস্ট এন্ডিয়ান থেকে প্রদত্ত এন্ডিয়ানে রূপান্তর করতে, ব্যবহার করুন:

output = endian(hostsource, endian_you_want_to_output)

ফলস্বরূপ কোডটি ঝাঁকুনিতে হাত সমাবেশ হিসাবে তত দ্রুত, জিসিসিতে এটি বাবার ধীর (নিবন্ধভুক্ত &, <<, >>, | প্রতিটি বাইটের জন্য) তবে এখনও শালীন।



4

একটি ব্যবহার করবেন না union!

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

আরও তথ্যের জন্য এই উত্তর দেখুন:

https://stackoverflow.com/a/11996970


কেবল দুটি বৈধ উত্তর রয়েছে যা পোর্টেবল হওয়ার গ্যারান্টিযুক্ত।

প্রথম উত্তর, আপনি একটি সিস্টেমে অ্যাক্সেস আছে যদি যে সমর্থন সি ++ 20,
ব্যবহার করা std::endianথেকে <type_traits>হেডার।

(লেখার সময়, সি ++ 20 এখনও প্রকাশিত হয়নি, তবে কিছু প্রভাবিত হওয়ার আগ পর্যন্ত std::endian অন্তর্ভুক্তিকে সি ++ 20 এর পরে সংকলনের সময় এন্ডিয়েন্সিটি পরীক্ষা করার এটি পছন্দনীয় উপায় হবে))

সি ++ 20 এর পরে

constexpr bool is_little_endian = (std::endian::native == std::endian::little);

সি ++ 20 এর আগে, একমাত্র বৈধ উত্তরটি হ'ল একটি পূর্ণসংখ্যা সঞ্চয় করা এবং তারপরে টাইপ পেনিংয়ের মাধ্যমে এর প্রথম বাইটটি পরীক্ষা করা।
এর ব্যবহারের মতো নয়union , এটি সি ++ এর টাইপ সিস্টেমের দ্বারা স্পষ্টভাবে অনুমোদিত।

এটিও মনে রাখা গুরুত্বপূর্ণ যে সর্বোত্তম পোর্টেবিলিটিটির জন্য static_castব্যবহার করা উচিত,
কারণ reinterpret_castএটি বাস্তবায়িত সংজ্ঞায়িত।

যদি কোনও প্রোগ্রাম নিম্নলিখিত ধরণের একটি ব্যতীত অন্য কোনও গ্লুভের মাধ্যমে কোনও অবজেক্টের সঞ্চিত মান অ্যাক্সেস করার চেষ্টা করে তবে আচরণটি সংজ্ঞায়িত: ... একটি charবা unsigned charটাইপ।

সি ++ 11 এর পরে

enum class endianness
{
    little = 0,
    big = 1,
};

inline endianness get_system_endianness()
{
    const int value { 0x01 };
    const void * address = static_cast<const void *>(&value);
    const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
    return (*least_significant_address == 0x01) ? endianness::little : endianness::big;
}

সি ++ 11 এর পরে (এনাম ছাড়াই)

inline bool is_system_little_endian()
{
    const int value { 0x01 };
    const void * address = static_cast<const void *>(&value);
    const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
    return (*least_significant_address == 0x01);
}

সি ++ 98 / সি ++ 03

inline bool is_system_little_endian()
{
    const int value = 0x01;
    const void * address = static_cast<const void *>(&value);
    const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
    return (*least_significant_address == 0x01);
}

3
union {
    int i;
    char c[sizeof(int)];
} x;
x.i = 1;
if(x.c[0] == 1)
    printf("little-endian\n");
else    printf("big-endian\n");

এটি অন্য একটি সমাধান। অ্যান্ড্রু হারের সমাধানের মতো।


3

অরক্ষিত, কিন্তু আমার মনে, এই কাজ করা উচিত? এটি ছোট এন্ডিয়ানে 0x01 এবং বড় এন্ডিয়ানতে 0x00 হবে?

bool runtimeIsLittleEndian(void)
{
 volatile uint16_t i=1;
 return  ((uint8_t*)&i)[0]==0x01;//0x01=little, 0x00=big
}

3

ঘোষণা:

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

সংকলন সময়, নন-ম্যাক্রো, সি ++ 11 কনটেক্সপ্রস সমাধান:

union {
  uint16_t s;
  unsigned char c[2];
} constexpr static  d {1};

constexpr bool is_little_endian() {
  return d.c[0] == 1;
}

2
Uint8_t এর উপর আপনি স্বাক্ষরবিহীন চরটি ব্যবহার করার কোনও কারণ রয়েছে কি?
কেভিন

0 রানটাইম ওভারহেড ... আমি এটি পছন্দ করি!
hanshenrik

আমার ধারণা, এটি বিল্ড মেশিনের এন্ডিয়ানস সনাক্ত করে, লক্ষ্য নয়?
হাটর্নি

2
এই ইউবি কি সি ++ এ নেই?
rr-

6
কনটেক্সপ্রপেক্টে এটি আইনী নয়। আপনি সরাসরি এমন কোনও ইউনিয়নের সদস্যকে অ্যাক্সেস করতে পারবেন না যা সরাসরি শুরু করা হয়নি। প্রিপ্রোসেসর যাদু ছাড়াই সংকলন সময়ে আইনীভাবে শেষের দিকটি সনাক্ত করার কোনও উপায় নেই।
রিচার্ড হোজেস

2

আপনি বুস্ট হেডার ফাইলের মতো কিছু ব্যবহার করে প্রিপ্রসেসরের মাধ্যমে এটিও করতে পারেন যা বুস্ট এন্ডিয়ান খুঁজে পাওয়া যায়


1

এন্ডিয়ানিয়ান শিরোনামটি কেবলমাত্র জিসিসি না হলে এটি আপনার ব্যবহার করতে পারেন এমন ম্যাক্রোগুলি সরবরাহ করে।

#include "endian.h"
...
if (__BYTE_ORDER == __LITTLE_ENDIAN) { ... }
else if (__BYTE_ORDER == __BIG_ENDIAN) { ... }
else { throw std::runtime_error("Sorry, this version does not support PDP Endian!");
...

এগুলি কি না __BYTE_ORDER__, __ORDER_LITTLE_ENDIAN__এবং __ORDER_BIG_ENDIAN__?
জেভেরিয়াস

1

আপনি যদি শর্তসাপেক্ষ সংকলনটি না চান তবে আপনি কেবল এরিডিয়ান স্বাধীন কোড লিখতে পারেন write এখানে একটি উদাহরণ ( রব পাইক থেকে নেওয়া ):

ডিস্কে লিটল-এন্ডিয়ানতে সঞ্চিত একটি পূর্ণসংখ্যা পড়া, একটি এন্ডিয়ান স্বতন্ত্র পদ্ধতিতে:

i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);

একই কোড, মেশিনের পরিণতি বিবেচনার চেষ্টা করছে:

i = *((int*)data);
#ifdef BIG_ENDIAN
/* swap the bytes */
i = ((i&0xFF)<<24) | (((i>>8)&0xFF)<<16) | (((i>>16)&0xFF)<<8) | (((i>>24)&0xFF)<<0);
#endif

কি সুন্দর ধারণা! এবং এখন নেটওয়ার্ক সংকেতের মাধ্যমে আপনার পূর্ণসংখ্যা অজানা ডিভাইসে স্থানান্তর করি।
ম্যাকসিম গ্যানেনকো

@ ম্যাক্সেমগ্যানেনকো আমি আপনার মন্তব্যটি পাই না। এটা কি বিড়ম্বনা? আমি সিরিয়ালযুক্ত ডেটাটির অন্তর্নিহিতা নির্দিষ্ট না করার পরামর্শ দিচ্ছি না । আমি ডেটা গ্রহণের মেশিনের শেষের উপর নির্ভর করে কোড না লিখার পরামর্শ দিচ্ছি।
fjardon

@ ম্যাক্সেমগানেনকো আপনি যদি নিম্নচাটন করেন তবে উত্তরটি কেন ভুল তা আপনি ব্যাখ্যা করতে পারেন। কমপক্ষে সম্ভাব্য পাঠকদের বুঝতে কেন তাদের আমার উত্তর অনুসরণ করা উচিত নয়।
fjardon


0

এ কেমন?

#include <cstdio>

int main()
{
    unsigned int n = 1;
    char *p = 0;

    p = (char*)&n;
    if (*p == 1)
        std::printf("Little Endian\n");
    else 
        if (*(p + sizeof(int) - 1) == 1)
            std::printf("Big Endian\n");
        else
            std::printf("What the crap?\n");
    return 0;
}

0

এখানে আরও একটি সি সংস্করণ। এটি wicked_cast()সি 99 ইউনিয়ন আক্ষরিক এবং অ-মানক __typeof__অপারেটরের মাধ্যমে ইনলাইন টাইপ পাপিংয়ের জন্য ডাকা একটি ম্যাক্রো সংজ্ঞায়িত করে ।

#include <limits.h>

#if UCHAR_MAX == UINT_MAX
#error endianness irrelevant as sizeof(int) == 1
#endif

#define wicked_cast(TYPE, VALUE) \
    (((union { __typeof__(VALUE) src; TYPE dest; }){ .src = VALUE }).dest)

_Bool is_little_endian(void)
{
    return wicked_cast(unsigned char, 1u);
}

যদি পূর্ণসংখ্যাগুলি একক-বাইট মান হয়, তবে শেষের কোনও অর্থ হয় না এবং একটি সংকলন-সময় ত্রুটি উত্পন্ন হবে।


0

পথ সি কম্পাইলার (অন্তত সবাই এ আমি জানি) endianness কাজ করেছে কম্পাইল সময়ে নির্ধারণ করবে। এমনকি বাইন্ডিয়ান প্রসেসরের জন্য (যেমন এআরএম ও এমআইপিএস) সংকলনের সময় আপনাকে এন্ডিয়েনেস বেছে নিতে হবে। আরও আরও নির্বাহী (যেমন ELF) এর জন্য সমস্ত সাধারণ ফাইল ফর্ম্যাটে endianness সংজ্ঞায়িত করা হয়। যদিও বাইয়ানিয়ান কোডের একটি বাইনারি ব্লব তৈরি করা সম্ভব (কিছু এআরএম সার্ভারের জন্য সম্ভবত শোষণ করা যেতে পারে?) এটি সম্ভবত সমাবেশে করতে হবে।


-1

কোরিয়ান্ডারের নির্দেশ অনুসারে, এখানে those কোডগুলির বেশিরভাগ (সমস্ত না থাকলে) সংকলনের সময়ে অপ্টিমাইজ করা হবে, সুতরাং উত্পাদিত বাইনারিগুলি রান সময় "" আধ্যাত্মিকতা "পরীক্ষা করবে না।

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

#include <stdint.h>

int* _BE = 0;

int is_big_endian() {
    if (_BE == 0) {
        uint16_t* teste = (uint16_t*)malloc(4);
        *teste = (*teste & 0x01FE) | 0x0100;
        uint8_t teste2 = ((uint8_t*) teste)[0];
        free(teste);
        _BE = (int*)malloc(sizeof(int));
        *_BE = (0x01 == teste2);
    }
    return *_BE;
}

এখানে অন্য কোডগুলি অপ্টিমিটেড করা সত্ত্বেও MinGW এই কোডটি অপ্টিমাইজ করতে সক্ষম হয় নি। আমি বিশ্বাস করি এটি কারণ আমি ছোট বাইট মেমরির ("বিটগুলির কমপক্ষে)) এর মতো" র্যান্ডম "মানটি ছেড়ে দিয়েছিলাম, সুতরাং সংকলকটি জানতে পারে না যে এলোমেলো মানটি কী এবং এটি অপ্টিমাইজ করে না ফাংশন দূরে।

আমি ফাংশনটি কোড করে দিয়েছি যাতে চেকটি কেবল একবার সঞ্চালিত হয়, এবং ফেরতের মান পরবর্তী পরীক্ষাগুলির জন্য সংরক্ষণ করা হয়।


2-বাইট মানের জন্য 4 বাইট কেন বরাদ্দ করা হবে? কেন একটি অনির্দিষ্ট মান মাস্ক 0x7FE? malloc()আদৌ কেন ব্যবহার করবেন ? এটা অপব্যয়। এবং _BEএকটি (ছোট হলেও) মেমরি ফুটো এবং এমন একটি দৌড় শর্ত যা হওয়ার জন্য অপেক্ষা করছে, ফলটি গতিবেগের সাথে ক্যাশে করার সুবিধাগুলি কোনও সমস্যার জন্য উপযুক্ত নয়। পরিবর্তে আমি এর মতো আরও কিছু করব: static const uint16_t teste = 1; int is_little_endian() { return (0x01 == ((uint8_t*)&teste)[0]); } int is_big_endian() { return (0x01 == ((uint8_t*)&teste)[1]); }সহজ এবং কার্যকর এবং রানটাইমে সঞ্চালনের জন্য অনেক কম কাজ।
রেমি লেবুউ

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

@ টেক্সকিলার তাহলে কেন কেবল কোডটির জন্য অপ্টিমাইজেশন অক্ষম করবেন না? ব্যবহার volatile, বা #pragmaইত্যাদি
রেমি লেবউ

@ রেমিলিউউ, আমি সেই সময়গুলিতে এই কীওয়ার্ডগুলি জানতাম না এবং আমি যা জানতাম তার সাথে সংকলক অপ্টিমাইজেশন প্রতিরোধ করার জন্য এটি একটি সামান্য চ্যালেঞ্জ হিসাবে গ্রহণ করেছি।
টেক্স কিলার

-1

এটি নির্ধারণের জন্য কোনও দ্রুত এবং মানক উপায় না থাকলেও এটি এটিকে আউটপুট দেবে:

#include <stdio.h> 
int main()  
{ 
   unsigned int i = 1; 
   char *c = (char*)&i; 
   if (*c)     
       printf("Little endian"); 
   else
       printf("Big endian"); 
   getchar(); 
   return 0; 
} 

-1

এন্ডিয়ানেশন - সি-লেভেল কোড চিত্রণ দেখুন See

// assuming target architecture is 32-bit = 4-Bytes
enum ENDIANNESS{ LITTLEENDIAN , BIGENDIAN , UNHANDLE };


ENDIANNESS CheckArchEndianalityV1( void )
{
    int Endian = 0x00000001; // assuming target architecture is 32-bit    

    // as Endian = 0x00000001 so MSB (Most Significant Byte) = 0x00 and LSB (Least     Significant Byte) = 0x01
    // casting down to a single byte value LSB discarding higher bytes    

    return (*(char *) &Endian == 0x01) ? LITTLEENDIAN : BIGENDIAN;
} 

-2

আমি পাঠ্যপুস্তকটি কম্পিউটার কম্পিউটার: একটি প্রোগ্রামারের দৃষ্টিভঙ্গি দিয়ে যাচ্ছিলাম , এবং সি প্রোগ্রামের মাধ্যমে এটি কোন এন্ডিয়ান হয় তা নির্ধারণ করতে সমস্যা আছে।

আমি নীচের হিসাবে এটি করতে পয়েন্টারের বৈশিষ্ট্যটি ব্যবহার করেছি:

#include <stdio.h>

int main(void){
    int i=1;
    unsigned char* ii = &i;

    printf("This computer is %s endian.\n", ((ii[0]==1) ? "little" : "big"));
    return 0;
}

হিসাবে int- এ 4 বাইট পর্যন্ত সময় নেয়, এবং গৃহস্থালির কাজ মাত্র 1 বাইট পর্যন্ত সময় লাগে। আমরা একটি ব্যবহার করতে পারে গৃহস্থালির কাজ পয়েন্টার নির্দেশ করার int- এ মান 1. সঙ্গে তাই যদি কম্পিউটার সামান্য endian হয় গৃহস্থালির কাজ যে গৃহস্থালির কাজ পয়েন্টার পয়েন্ট মান 1, অন্যথায়, তার মান 0 হতে হবে।


এটি int32t ব্যবহার করে উন্নত হবে।
শাটল 87

1
you আপনি যদি নিটপিক করতে চান, তবে এখানে সেরা 16 ম্যান_ফেষ্ট_টি। এবং @ আর্কিমিডিজ ৫২০ এর বর্তমান কোডটি এমন কোনও খিলানটিতে কাজ করবে না যেখানে ইন্টিটি স্থানীয়ভাবে অন্তর্নিহিত রয়েছে;) (এটি প্রথমে সি মানদণ্ডের বিপরীতে যেতে পারে, যদিও)
হানশেনরিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.