क्या बिट-शिफ्ट एंडियननेस पर निर्भर करता है?


156

मान लीजिए कि मेरे पास संख्या का 'numb'=1025 [00000000 00000000 00000100 00000001]प्रतिनिधित्व है:

लिटिल-एंडियन मशीन पर:

00000001 00000100 00000000 00000000

बिग-एंडियन मशीन पर:

00000000 00000000 00000100 00000001

अब, अगर मैं 10 बिट्स पर लेफ्ट शिफ्ट लागू करता हूं (यानी: numb << = 10), मेरे पास होना चाहिए:

[ए] लिटिल-एंडियन मशीन पर:

जैसा कि मैंने GDB में देखा, लिटिल एंडियन 3 चरणों में वाम शिफ्ट करता है: [मैंने प्रसंस्करण प्रक्रियाओं को बेहतर ढंग से समझने के लिए '3' चरण दिखाए हैं]

  1. सं। बिग-एंडियन कन्वेंशन में:

    00000000        00000000        00000100    00000001
  2. वाम-शिफ्ट लागू करें:

    00000000        00010000        00000100        00000000
  3. लिटिल-एंडियन में फिर से परिणाम का प्रतिनिधित्व करें:

    00000000        00000100        00010000        00000000 

[बी]। बिग-एंडियन मशीन पर:

00000000        00010000        00000100        00000000

मेरा सवाल यह है कि:

अगर मैं लिटिल एंडियन कन्वेंशन पर सीधे लेफ्ट शिफ्ट लागू करता हूं, तो यह देना चाहिए:

numb:

00000001 00000100 00000000 00000000

numb << 10:

00010000 00000000 00000000 00000000

लेकिन वास्तव में, यह देता है:

00000000        00000100        00010000        00000000 

केवल दूसरा परिणाम प्राप्त करने के लिए, मैंने ऊपर तीन काल्पनिक चरण दिखाए हैं।

कृपया मुझे समझाएं कि उपरोक्त दो परिणाम अलग क्यों हैं: वास्तविक परिणाम numb << 10अपेक्षित परिणाम से अलग है।

जवाबों:


194

अंतःकरण वह तरीका है जो मानों को स्मृति में संग्रहीत किया जाता है। जब एंडियनस की परवाह किए बिना प्रोसेसर में लोड किया जाता है, तो बिट शिफ्ट इंस्ट्रक्शन प्रोसेसर के रजिस्टर में मूल्य पर काम कर रहा है। इसलिए, मेमोरी से प्रोसेसर तक लोड करना बड़े एंडियन में कनवर्ट करने के बराबर है, शिफ्टिंग ऑपरेशन आगे आता है और फिर नए मूल्य को मेमोरी में वापस संग्रहीत किया जाता है, जो कि जहां थोड़ा एंडियन बाइट ऑर्डर फिर से लागू होता है।

अपडेट, @jww के लिए धन्यवाद: पावरपीसी पर वेक्टर शिफ्ट और रोटेट एंडियन संवेदनशील हैं। आप एक वेक्टर रजिस्टर में एक मूल्य रख सकते हैं और एक बदलाव छोटे-एंडियन और बड़े-एंडियन पर अलग-अलग परिणाम देगा


4
स्पष्टीकरण के लिए धन्यवाद। क्या आप कृपया कुछ संदर्भ सुझा सकते हैं जहां मुझे इस तरह की पेचीदगियों के बारे में बेहतर जानकारी मिल सकती है।
संदीप सिंह

4
धीरज को समझने के लिए सबसे अच्छी बात यह है कि वास्तव में इसका उपयोग विभिन्न स्तरों पर विभिन्न स्तरों पर किया जाना चाहिए। हालाँकि, मैं आपको इन दो लेखों का उल्लेख कर सकता हूं: codeproject.com/KB/cpp/endianness.aspx और ibm.com/developerworks/aix/library/au-endianc/…
कार्ल

3
तो मेरा कोड एंडियन की परवाह किए बिना काम करेगा ?! यह महान है! मुझे बहुत चिंता हो रही है कि मुझे अपने कोड को नरक और वापस हैक करना होगा!
माक्र्सज

2
@MarcusJ: जरूरी नहीं। उदाहरण के लिए, यदि आप 32-बिट पूर्णांक का प्रतिनिधित्व करने वाली फ़ाइल से 4 बाइट्स पढ़ रहे हैं, तो आपको उस डेटा की समाप्ति पर विचार करने की आवश्यकता है जिसे आप सिस्टम के अंतरण के साथ पढ़ रहे हैं ताकि डेटा को ठीक से व्याख्या करने के लिए प्राप्त किया जा सके आँकड़े।
कार्ल

3
PowerPC पर वेक्टर शिफ्ट और रोटेट एंडियन संवेदनशील हैं। आप एक वेक्टर रजिस्टर में एक मूल्य रख सकते हैं और एक बदलाव छोटे-एंडियन और बड़े-एंडियन पर अलग-अलग परिणाम देगा।
jww

58

नहीं, बिटशिफ्ट, सी के किसी भी अन्य भाग की तरह, मूल्यों के संदर्भ में परिभाषित किया गया है , प्रतिनिधित्व नहीं। 1 से लेफ्ट-शिफ्ट 2 से म्यूटिलेशन है, राइट-शिफ्ट डिवीजन है। (हमेशा की तरह बिटवाइज़ ऑपरेशंस का उपयोग करते समय, हस्ताक्षर से सावधान रहें। अहस्ताक्षरित अभिन्न प्रकारों के लिए सब कुछ सबसे अच्छी तरह से परिभाषित है)।


1
यह पूर्णांक अंकगणित के लिए मूल रूप से सच है, लेकिन सी प्रतिनिधित्व-निर्भर व्यवहार के बहुत सारे मामले प्रदान करता है।
एडमंड

2
@ एडमंड: एचएम ... सबसे विशेष रूप से हस्ताक्षर के कार्यान्वयन को निर्दिष्ट नहीं किया जाता है, और इसके परिणामस्वरूप बिटवाइज़ ऑपरेशंस (जैसे कि राइट-शिफ्ट) और मॉडुलो और डिवाइड के व्यवहार को नकारात्मक पूर्णांक पर परिभाषित किया जाता है। आपके पास और कौन सी चीजें हैं जो कार्यान्वयन-परिभाषित हैं?
केरेक एसबी

@KerrekSB दुर्भाग्य से वे नकारात्मक पूर्णांक पर परिभाषित नहीं हैं। वे C89 में अनिर्दिष्ट हैं और C99 + में अपरिभाषित हैं, जो एक बहुत बुरा विचार था।
पाओलो बोन्जिनी

@PaoloBonzini: हां, अच्छी बात है। वास्तव में यह और भी बेहतर है, क्योंकि यह इस बिंदु को पुष्ट करता है कि बदलाव के संचालन को मूल्यों के संदर्भ में परिभाषित किया जाता है, संभवतः परिणाम अपरिहार्य होने पर अपरिभाषित होता है, और यह कि अंतर्निहित प्रतिनिधित्व के बारे में अटकलें मदद नहीं करती हैं।
केरेके एसबी

@KerrekSB: बात यह है कि हर किसी को मामले के आधार पर मूल्यों के रूप में और प्रतिनिधित्व के रूप में प्रतिनिधित्व करने के लिए बाएं बदलाव की आवश्यकता है। और अहस्ताक्षरित पूर्णांक का उपयोग करने से अन्य समस्याएं हो सकती हैं, उदाहरण के लिए x &= -1u << 20यदि x64-बिट है और int32-बिट है तो सबसे अधिक संभावना गलत होगी । इस कारण से, जीसीसी ने हस्ताक्षरित पारियों को कभी भी अपरिभाषित या अनिर्दिष्ट नहीं माना है।
पाओलो बोन्जिनी

5

जो भी शिफ्ट इंस्ट्रक्शन पहले उच्च क्रम के बिट्स को शिफ्ट करता है उसे लेफ्ट शिफ्ट माना जाता है। जो भी शिफ्ट इंस्ट्रक्शन निचली क्रम की बिट्स को शिफ्ट करता है, उसे सही शिफ्ट माना जाता है। इस संदर्भ में, के व्यवहार >>और <<के लिए unsignedसंख्या endianness पर निर्भर नहीं होंगे।


4

कंप्यूटर हमारे द्वारा किए गए तरीके से संख्याएँ नहीं लिखते हैं। मूल्य बस बदलाव। यदि आप इसे बाइट-बाय-बाइट देखने पर जोर देते हैं (भले ही यह कंप्यूटर कैसे नहीं करता है), तो आप कह सकते हैं कि थोड़ी-सी एंडियन मशीन पर, पहली बाइट शिफ्ट हो जाती है, अतिरिक्त बाइट दूसरी बाइट में चली जाती है। और इसी तरह।

(वैसे, अगर आप क्षैतिज रूप से शीर्ष पर मौजूद पतों के साथ, बाइट्स को लंबवत लिखने की बजाए लिटिल-एंडियन अधिक अर्थ देते हैं। ऐसा होता है कि आमतौर पर मेमोरी मैप आरेखों को कैसे खींचा जाता है।)


2

हालांकि स्वीकार किए गए उत्तर बताते हैं कि स्मृति दृष्टि से धीरज एक अवधारणा है। लेकिन मुझे नहीं लगता कि सीधे सवाल का जवाब देना।

कुछ जवाब मुझे बताते हैं कि बिटवाइज़ ऑपरेशंस एंडियनस पर निर्भर नहीं करते हैं , और प्रोसेसर किसी अन्य तरीके से बाइट्स का प्रतिनिधित्व कर सकता है। वैसे भी, यह बात हो रही है कि धीरज अस्त हो जाता है।

लेकिन जब हम उदाहरण के लिए कागज पर कुछ बिटवाइज़ कैलकुलेशन करते हैं, तो पहली जगह में एंडियन को स्टेट करने की ज़रूरत नहीं है? ज्यादातर बार हम एक अंतःप्रेरणा का चयन करते हैं।

उदाहरण के लिए, मान लें कि हमारे पास इस तरह कोड की एक पंक्ति है

0x1F & 0xEF

आप एक कागज पर हाथ से परिणाम की गणना कैसे करेंगे?

  MSB   0001 1111  LSB
        1110 1111
result: 0000 1111

तो यहाँ हम गणना करने के लिए एक बिग एंडियन प्रारूप का उपयोग करते हैं। आप उसी परिणाम की गणना करने और प्राप्त करने के लिए लिटिल एंडियन का भी उपयोग कर सकते हैं।

Btw, जब हम कोड में संख्या लिखते हैं, मुझे लगता है कि यह एक बिग एंडियन प्रारूप की तरह है। 123456या 0x1F, सबसे महत्वपूर्ण संख्याएं बाईं ओर से शुरू होती हैं।

दोबारा, जैसे ही हम कागज पर एक मूल्य के कुछ द्विआधारी प्रारूप लिखते हैं, मुझे लगता है कि हमने पहले से ही एक एंडियन चुना है और हम मान को स्मृति से देख रहे हैं।

तो इस सवाल पर, एक बदलाव ऑपरेशन <<को LSB (कम से कम महत्वपूर्ण बाइट) से MSB (सबसे महत्वपूर्ण बाइट) में स्थानांतरित करने के रूप में सोचा जाना चाहिए ।

फिर प्रश्न में उदाहरण के लिए:

numb=1025

छोटा एंडियन

LSB 00000001 00000100 00000000 00000000 MSB

तो LSB से MSB में शिफ्ट << 10हो जाएगा 10bit


<< 10लिटिल एंडियन प्रारूप के लिए कदम से तुलना और संचालन:

MSB                                        LSB
    00000000  00000000  00000100  00000001  numb(1025)
    00000000  00010000  00000100  00000000  << 10

LSB                                        MSB
    00000000  00000100  00010000  00000000 numb(1025) << 10, and put in a Little Endian Format

LSB                                        MSB
    00000001  00000100  00000000  00000000 numb(1205) in Little Endian format
    00000010  00001000  00000000  00000000 << 1 
    00000100  00010000  00000000  00000000 << 2 
    00001000  00100000  00000000  00000000 << 3 
    00010000  01000000  00000000  00000000 << 4
    00100000  10000000  00000000  00000000 << 5
    01000000  00000000  00000001  00000000 << 6
    10000000  00000000  00000010  00000000 << 7
    00000000  00000001  00000100  00000000 << 8
    00000000  00000010  00001000  00000000 << 9
    00000000  00000100  00010000  00000000 << 10 (check this final result!)

वाह! जैसा कि ओपी ने वर्णन किया है मुझे अपेक्षित परिणाम मिलता है!

ओपी को अपेक्षित परिणाम नहीं मिलने की समस्याएँ इस प्रकार हैं:

  1. ऐसा लगता है कि वह LSB से MSB में शिफ्ट नहीं हुए।

  2. लिटिल एंडियन प्रारूप में बिट्स को शिफ्ट करते समय, आपको एहसास होना चाहिए (भगवान का आभार मुझे इसका एहसास होता है):

LSB 10000000 00000000 MSB << 1है
LSB 00000000 00000001 MSB, नहीं LSB 01000000 00000000 MSB

क्योंकि प्रत्येक व्यक्ति के लिए 8bits, हम वास्तव में इसे MSB 00000000 LSBबिग एंडियन प्रारूप में लिख रहे हैं ।

तो ऐसा है

LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB


सारांश में:

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

  2. ओपी को अपेक्षित परिणाम नहीं मिला क्योंकि उसने गलत स्थानांतरण किया था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.