खोज…
टिप्पणियों
सभी प्रोसेसर आर्किटेक्चर में बिट शिफ्ट ऑपरेशन पोर्टेबल नहीं हैं, विभिन्न प्रोसेसर में अलग-अलग बिट-चौड़ाई हो सकती हैं। दूसरे शब्दों में, अगर आपने लिखा है
int a = ~0;
int b = a << 1;
यह मान 64 बिट मशीन बनाम 32 बिट मशीन पर या x86 आधारित प्रोसेसर से PIC आधारित प्रोसेसर पर अलग होगा।
एंडियन-नेस को थोड़ा सा बुद्धिमान संचालन के लिए खुद को ध्यान में रखने की आवश्यकता नहीं है, अर्थात, सही बदलाव ( >>
) बिट्स को कम से कम महत्वपूर्ण बिट की ओर शिफ्ट करेगा और एक्सओआर एक विशेष या बिट्स पर प्रदर्शन करेगा। एंडियन-नेस को केवल डेटा के साथ ही ध्यान में रखना होगा, अगर एंडियन-नेस आपके आवेदन के लिए एक चिंता का विषय है, तो यह बिट वार ऑपरेशन की परवाह किए बिना एक चिंता है।
& - बिटवाइज़ और
int a = 6; // 0110b (0x06)
int b = 10; // 1010b (0x0A)
int c = a & b; // 0010b (0x02)
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
उत्पादन
a = 6, b = 10, c = 2
क्यों
थोड़ा बुद्धिमान AND
बिट स्तर पर काम करता है और निम्नलिखित बुलियन सत्य तालिका का उपयोग करता है:
TRUE AND TRUE = TRUE
TRUE AND FALSE = FALSE
FALSE AND FALSE = FALSE
जब a
( 0110
) के लिए द्विआधारी मूल्य और b
( 1010
) के लिए द्विआधारी मूल्य हैं AND
एक साथ हमें 0010
का द्विआधारी मूल्य मिलता है:
int a = 0 1 1 0
int b = 1 0 1 0 &
---------
int c = 0 0 1 0
जब तक विशेष रूप से बिट वार असाइनमेंट कंपाउंड ऑपरेटर &=
का उपयोग करने के लिए असाइन नहीं किया जाता है, तब तक बिट बुद्धिमान और मूल मूल्यों का परिवर्तन नहीं करता है:
int a = 5; // 0101b (0x05)
a &= 10; // a = 0101b & 1010b
| - बिटवाइज़ OR
int a = 5; // 0101b (0x05)
int b = 12; // 1100b (0x0C)
int c = a | b; // 1101b (0x0D)
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
उत्पादन
a = 5, b = 12, c = 13
क्यों
थोड़ा बुद्धिमान OR
बिट स्तर पर काम करता है और निम्नलिखित बुलियन सत्य तालिका का उपयोग करता है:
true OR true = true
true OR false = true
false OR false = false
जब के लिए बाइनरी मान a
( 0101
) और के लिए बाइनरी मान b
( 1100
) कर रहे हैं OR
'एक साथ एड हम की बाइनरी मूल्य प्राप्त 1101
:
int a = 0 1 0 1
int b = 1 1 0 0 |
---------
int c = 1 1 0 1
जब तक विशेष रूप से बिट वार असाइनमेंट कंपाउंड ऑपरेटर का उपयोग करने के लिए निर्दिष्ट नहीं किया जाता है तब तक बिट बुद्धिमान या मूल मूल्यों के परिवर्तन नहीं करता है |=
:
int a = 5; // 0101b (0x05)
a |= 12; // a = 0101b | 1101b
^ - बिटवाइज़ XOR (एक्सक्लूसिव OR)
int a = 5; // 0101b (0x05)
int b = 9; // 1001b (0x09)
int c = a ^ b; // 1100b (0x0C)
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
उत्पादन
a = 5, b = 9, c = 12
क्यों
थोड़ा बुद्धिमान XOR
(अनन्य या) बिट स्तर पर संचालित होता है और निम्नलिखित बूलियन सत्य तालिका का उपयोग करता है:
true OR true = false
true OR false = true
false OR false = false
ध्यान दें कि एक XOR ऑपरेशन के साथ true OR true = false
जहां ऑपरेशन true AND/OR true = true
, इसलिए XOR ऑपरेशन की अनन्य प्रकृति।
इस का उपयोग करना, जब के लिए बाइनरी मान a
( 0101
) और के लिए बाइनरी मान b
( 1001
) हैं XOR
'ED एक साथ हम की बाइनरी मूल्य प्राप्त 1100
:
int a = 0 1 0 1
int b = 1 0 0 1 ^
---------
int c = 1 1 0 0
जब तक विशेष रूप से बिट वार असाइनमेंट कंपाउंड ऑपरेटर का उपयोग करने के लिए असाइन नहीं किया जाता है, तब तक बिट बुद्धिमान XOR मूल मानों का मूल्य नहीं बदलता है: ^=
:
int a = 5; // 0101b (0x05)
a ^= 9; // a = 0101b ^ 1001b
बिट वार एक्सओआर का उपयोग कई तरीकों से किया जा सकता है और अक्सर एन्क्रिप्शन और संपीड़न के लिए बिट मास्क संचालन में उपयोग किया जाता है।
नोट: निम्नलिखित उदाहरण अक्सर एक अच्छी चाल के उदाहरण के रूप में दिखाया जाता है। लेकिन उत्पादन कोड में उपयोग नहीं किया जाना चाहिए std::swap()
एक ही परिणाम प्राप्त करने के लिए बेहतर तरीके std::swap()
)।
आप एक अस्थायी के बिना दो चर स्वैप करने के लिए एक XOR ऑपरेशन का उपयोग कर सकते हैं:
int a = 42;
int b = 64;
// XOR swap
a ^= b;
b ^= a;
a ^= b;
std::cout << "a = " << a << ", b = " << b << "\n";
इसे उपयोगी बनाने के लिए आपको यह सुनिश्चित करने के लिए एक चेक जोड़ना होगा कि इसका उपयोग किया जा सकता है।
void doXORSwap(int& a, int& b)
{
// Need to add a check to make sure you are not swapping the same
// variable with itself. Otherwise it will zero the value.
if (&a != &b)
{
// XOR swap
a ^= b;
b ^= a;
a ^= b;
}
}
तो हालांकि यह अलगाव में एक अच्छी चाल की तरह दिखता है लेकिन यह वास्तविक कोड में उपयोगी नहीं है। xor आधार लॉजिकल ऑपरेशन नहीं है, बल्कि दूसरों का एक संयोजन है: a ^ c = ~ (a (c) और (a | c) |
2015 में भी + संकलक चर को बाइनरी के रूप में सौंपा जा सकता है:
int cn=0b0111;
~ - बिटवाइज़ नहीं (अनुपूरक पूरक)
unsigned char a = 234; // 1110 1010b (0xEA)
unsigned char b = ~a; // 0001 0101b (0x15)
std::cout << "a = " << static_cast<int>(a) <<
", b = " << static_cast<int>(b) << std::endl;
उत्पादन
a = 234, b = 21
क्यों
एक बिट वार NOT
(एकतरफा पूरक) बिट स्तर पर काम करता है और बस प्रत्येक बिट को फ़्लिप करता है। यदि यह एक है 1
, यह एक करने के लिए बदल गया है 0
, अगर यह एक है 0
, यह एक करने के लिए बदल गया है 1
। बिट वार का एक ही प्रकार का प्रभाव नहीं है जैसे कि XOR'ing का किसी विशिष्ट प्रकार के अधिकतम मूल्य के विरुद्ध मूल्य:
unsigned char a = 234; // 1110 1010b (0xEA)
unsigned char b = ~a; // 0001 0101b (0x15)
unsigned char c = a ^ ~0;
एक विशिष्ट अभिन्न प्रकार के अधिकतम मूल्य की जांच करने के लिए बिट वार भी एक सुविधाजनक तरीका नहीं हो सकता है:
unsigned int i = ~0;
unsigned char c = ~0;
std::cout << "max uint = " << i << std::endl <<
"max uchar = " << static_cast<short>(c) << std::endl;
थोड़ा बुद्धिमान मूल मूल्य को नहीं बदलता है और इसमें एक कंपाउंड असाइनमेंट ऑपरेटर नहीं होता है, इसलिए आप उदाहरण के लिए a ~= 10
नहीं कर सकते।
बिट वार नहीं ( ~
) तार्किक NOT ( !
) के साथ भ्रमित नहीं होना चाहिए; जहां एक बिट बुद्धिमान प्रत्येक बिट को फ्लिप नहीं करेगा, एक तार्किक अपने ऑपरेशन को करने के लिए पूरे मूल्य का उपयोग नहीं करेगा, दूसरे शब्दों में (!1) != (~1)
<< - बाईं पारी
int a = 1; // 0001b
int b = a << 1; // 0010b
std::cout << "a = " << a << ", b = " << b << std::endl;
उत्पादन
a = 1, b = 2
क्यों
बाएं बिट वार शिफ्ट बाएं हाथ मूल्य ( a
) के बिट्स को दाईं ओर निर्दिष्ट करेगा ( 1
), अनिवार्य रूप से 0 के साथ कम से कम महत्वपूर्ण बिट्स को पैडिंग करना, इसलिए बाईं ओर 5
(बाइनरी 0000 0101
) के मूल्य को शिफ्ट करना 4 बार (उदाहरण के लिए 5 << 4
) 80
(बाइनरी 0101 0000
) के मूल्य का उत्पादन करेगा। आप ध्यान दें कि मान को बाईं ओर 1 बार शिफ्ट करना भी मान को 2 से गुणा करना है, उदाहरण:
int a = 7;
while (a < 200) {
std::cout << "a = " << a << std::endl;
a <<= 1;
}
a = 7;
while (a < 200) {
std::cout << "a = " << a << std::endl;
a *= 2;
}
लेकिन यह ध्यान दिया जाना चाहिए कि बाएं शिफ्ट ऑपरेशन साइन बिट, उदाहरण सहित सभी बिट्स को बाईं ओर स्थानांतरित कर देगा:
int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1; // 1111 1111 1111 1111 1111 1111 1111 1110
std::cout << "a = " << a << ", b = " << b << std::endl;
संभावित आउटपुट: a = 2147483647, b = -2
हालांकि कुछ संकलक परिणाम प्राप्त करेंगे जो अपेक्षित प्रतीत होते हैं, यह ध्यान दिया जाना चाहिए कि यदि आपने हस्ताक्षरित संख्या को छोड़ दिया है ताकि साइन बिट प्रभावित हो, तो परिणाम अपरिभाषित है । यह भी अपरिभाषित है यदि आप जितने बिट्स को शिफ्ट करना चाहते हैं वह एक ऋणात्मक संख्या है या बिट्स की संख्या से बड़ा है जिस पर बाईं ओर का प्रकार पकड़ सकता है, उदाहरण:
int a = 1;
int b = a << -1; // undefined behavior
char c = a << 20; // undefined behavior
बिट वार छोड़ पारी मूल मूल्यों के मूल्य में परिवर्तन नहीं होता जब तक कि विशेष बिट बुद्धिमान काम यौगिक ऑपरेटर का उपयोग करने के लिए आवंटित <<=
:
int a = 5; // 0101b
a <<= 1; // a = a << 1;
>> - सही बदलाव
int a = 2; // 0010b
int b = a >> 1; // 0001b
std::cout << "a = " << a << ", b = " << b << std::endl;
उत्पादन
a = 2, b = 1
क्यों
दाएं बिट वार शिफ्ट बाएं हाथ के मूल्य के बिट्स को स्थानांतरित कर देगा ( a
) दाईं ओर निर्दिष्ट संख्या ( 1
); यह ध्यान दिया जाना चाहिए कि जब एक सही पारी का संचालन मानक होता है, तो हस्ताक्षरित नकारात्मक संख्या पर एक सही बदलाव के बिट्स के साथ क्या होता है, कार्यान्वयन को परिभाषित किया जाता है और इस प्रकार पोर्टेबल होने की गारंटी नहीं दी जा सकती है, उदाहरण:
int a = -2;
int b = a >> 1; // the value of b will be depend on the compiler
यह भी अपरिभाषित है यदि आप जितने बिट्स को शिफ्ट करना चाहते हैं वह एक नकारात्मक संख्या है, उदाहरण:
int a = 1;
int b = a >> -1; // undefined behavior
जब तक विशेष रूप से बिट वार असाइनमेंट कंपाउंड ऑपरेटर का उपयोग करने के लिए असाइन नहीं किया जाता है, तब तक बिट वार राइट शिफ्ट मूल मानों का मूल्य नहीं बदलता है: >>=
:
int a = 2; // 0010b
a >>= 1; // a = a >> 1;