सी

2012-09-14 22 views
12

में 1 पर सेट किए गए कम से कम महत्व बिट्स के साथ मास्क कैसे बनाएं, क्या कोई मुझे इस फ़ंक्शन को समझा सकता है?सी

कम से कम महत्वपूर्ण n बिट्स 1.

पूर्व सेट के साथ एक मुखौटा:

n = 6 -> 0x2F, एन = 17 -> 0x1FFFF // मैं इन नहीं मिलता सब, विशेष रूप से कैसे एन = 6 -> 0x2F

इसके अलावा, मास्क क्या है?

+3

* एक मुखौटा है भी क्या * [कैसे विकिपीडिया के बारे में?] (http://en.wikipedia.org/wiki/Mask_? (कंप्यूटिंग)) – chris

+1

0x2F रास्ते से गलत है, यह 0x3f – wich

+1

@chris विकी बहुत भ्रम है ... – sebi

उत्तर

22

सामान्य तरीका 1 लेना है, और इसे n बिट्स को छोड़ दें। इससे आपको कुछ ऐसा मिलेगा: 00100000। फिर उस से एक घटाएं, जो सेट की गई बिट को साफ़ कर देगा, और सभी कम महत्वपूर्ण बिट्स सेट करेगा, इसलिए इस मामले में हम प्राप्त करेंगे: 00011111

एक मुखौटा आमतौर पर बिटवाई ऑपरेशंस के साथ उपयोग किया जाता है, खासकर and। आप उपरोक्त मुखौटा का उपयोग अपने आप से कम से कम 5 कम महत्वपूर्ण बिट्स प्राप्त करने के लिए करेंगे, जो मौजूद हो सकता है। यह विशेष रूप से आम है जब हार्डवेयर से निपटने में अक्सर एक हार्डवेयर रजिस्टर होता है जिसमें कई अलग-अलग, असंबद्ध मात्रा और/या झंडे का प्रतिनिधित्व करने वाले बिट्स होते हैं।

+2

ध्यान रखें कि '1 << w-1' जा रहा है, जहां' w' की चौड़ाई है डेटा प्रकार, बिट्स में से एक को सेट करने के लिए, यूबी है। – chris

+0

बिल्कुल। इसे इंटेल पर दोष दें, लेकिन यह इसे मानक में बना दिया। – wildplasser

+0

इस विधि में यूबी से समान रूप से पुनर्प्राप्त करने के लिए, नीचे मेरा उत्तर देखें। – user13972

0

मुझे विश्वास है कि आपका पहला उदाहरण 0x3f होना चाहिए। ताकि पिछले 6 बिट्स (कम से कम महत्वपूर्ण 6 बिट्स) 1 की तैयारी में हैं

0x3f, संख्या 63 जो बाइनरी में 111111 है के लिए हेक्साडेसिमल नोटेशन है।

निम्नलिखित थोड़ा सी कार्यक्रम सही मुखौटा की गणना करेगा:

#include <stdarg.h> 
#include <stdio.h> 

int mask_for_n_bits(int n) 
{ 
    int mask = 0; 

    for (int i = 0; i < n; ++i) 
     mask |= 1 << i; 

    return mask; 
} 

int main (int argc, char const *argv[]) 
{ 
    printf("6: 0x%x\n17: 0x%x\n", mask_for_n_bits(6), mask_for_n_bits(17)); 
    return 0; 
} 
0

0x2F बाइनरी में 0010 1111 है - इस 0x3f, जो बाइनरी में 0011 1111 है और जो 6 से कम-महत्वपूर्ण बिट सेट किया जाना चाहिए।

इसी प्रकार, 0x1FFFF0001 1111 1111 1111 1111 बाइनरी में है, जिसमें 17 कम-से-कम महत्वपूर्ण बिट सेट हैं।

ए 'मुखौटा' कि &, | या ^ की तरह एक बिटवाइज़ ऑपरेटर का उपयोग व्यक्तिगत रूप से, स्थापित करने के लिए सेट नहीं, कि अन्य मूल्य में फ्लिप या बिट्स अपरिवर्तित छोड़ एक और मूल्य के साथ जोड़ा जा करने का इरादा है एक मूल्य है।

उदाहरण के लिए, यदि आप कुछ मूल्य n& ऑपरेटर का उपयोग के साथ मुखौटा 0x2F गठबंधन, परिणाम सभी में शून्य लेकिन 6 कम से कम महत्वपूर्ण बिट होगा, और उन 6 बिट मूल्य n से अपरिवर्तित कॉपी किया जायेगा।

एक & मुखौटा के मामले में, एक द्विआधारी 0 नकाब में अर्थ है "बिना शर्त 0 परिणाम बिट सेट" और एक 1 का अर्थ है "इनपुट मूल्य बिट के लिए परिणाम बिट सेट"। एक | मुखौटा के लिए, नकाब में एक 0 इनपुट बिट के लिए परिणाम बिट सेट और एक 1 बिना शर्त 1 लिए परिणाम बिट सेट, और एक ^ मुखौटा के लिए, एक 0 इनपुट बिट के लिए परिणाम बिट सेट और एक 1 सेट इनपुट बिट के पूरक के लिए परिणाम बिट।

+0

ओपीएस। आपके अपडेट के बाद गलत संपादन मिला, लेकिन मैंने रोलबैक किया। माफ़ कीजिये! – jweyrich

5

एक मुखौटा एक पूर्णांक मान के लिए एक सामान्य शब्द है जो बिट-वार एंडेड, ऑर्ड, एक्सओआरड, आदि एक और पूर्णांक मान के साथ है।

उदाहरण के लिए, यदि आप एक int चर के 8 कम से कम महत्वपूर्ण अंक निकालना चाहते हैं, तो आप variable & 0xFF करते हैं। 0xFF एक मुखौटा है।

इसी तरह यदि आप बिट्स 0 और 8 सेट करना चाहते हैं, तो आप variable | 0x101 करते हैं, जहां 0x101 एक मुखौटा है।

या यदि आप एक ही बिट्स को उलटा करना चाहते हैं, तो आप variable^0x101 करते हैं, जहां 0x101 एक मुखौटा है।

अपने मामले के लिए एक मुखौटा उत्पन्न करने के लिए आपको सरल गणितीय तथ्य का फायदा उठाना चाहिए कि यदि आप अपने मुखौटा में 1 जोड़ते हैं (मास्क में इसकी सभी कम से कम महत्वपूर्ण बिट्स 1 और शेष 0 पर सेट होती हैं), तो आपको एक मान मिलता है 2.

की शक्ति है, इसलिए यदि आप 2 की सबसे नज़दीकी शक्ति उत्पन्न करते हैं, तो आप मास्क प्राप्त करने के लिए 1 से घटा सकते हैं।

2 के सकारात्मक शक्तियों आसानी से

सी

में बाईं पारी << ऑपरेटर के साथ उत्पन्न कर रहे हैं इसलिए, 1 << n पैदावार 2 n। बाइनरी में यह 10 ...0s के साथ है।

(1 << n) - 1n सबसे कम बिट्स 1.

करने के लिए सेट अब साथ एक मुखौटा का उत्पादन करेगा, आप बाईं पाली में अतिप्रवाह के लिए बाहर देखने की जरूरत है। सी (और सी ++ में) आप वैरिएबल के रूप में कई बिट पोजिशन द्वारा कानूनी रूप से बायीं तरफ स्थानांतरित नहीं कर सकते हैं, इसलिए यदि इनट्स 32-बिट हैं, 1<<32 परिणाम undefined behavior में हैं। हस्ताक्षरित पूर्णांक ओवरफ़्लो से बचा जाना चाहिए, इसलिए आपको हस्ताक्षरित मानों का उपयोग करना चाहिए, उदा। 1u << 31

7

दोनों शुद्धता और प्रदर्शन दोनों के लिए, इसे पूरा करने का सबसे अच्छा तरीका बदल गया है क्योंकि 2012 में इस प्रश्न को आधुनिक x86 प्रोसेसर, विशेष रूप से बीएलएसएमएसके में बीएमआई निर्देशों के आगमन के कारण वापस पूछा गया था।

पुराने प्रोसेसर के साथ पिछड़ा संगतता बनाए रखते हुए, इस समस्या के करीब आने का एक अच्छा तरीका है।

यह विधि सही है, जबकि वर्तमान शीर्ष उत्तरों किनारे के मामलों में अपरिभाषित व्यवहार का उत्पादन करते हैं।

क्लैंग और जीसीसी, जब बीएमआई निर्देशों का उपयोग करके अनुकूलित करने की अनुमति दी जाती है, तो gen_mask() को केवल दो ऑप्स में जोड़ देगा। हार्डवेयर समर्थन के साथ, बीएमआई निर्देश के लिए संकलक झंडे जोड़ना सुनिश्चित करें: -mbmi -mbmi2

#include <inttypes.h> 
#include <stdio.h> 

uint64_t gen_mask(const uint_fast8_t msb) { 
    const uint64_t src = (uint64_t)1 << msb; 
    return (src - 1)^src; 
} 

int main() { 
    uint_fast8_t msb; 
    for (msb = 0; msb < 64; ++msb) { 
    printf("%016" PRIx64 "\n", gen_mask(msb)); 
    } 
    return 0; 
} 
+0

आपके पास एक-एक-एक त्रुटि है, AFAICT। –

+1

क्षमा करें, यह एक गलतफहमी है: मैंने चौड़ाई को पैरामीटर के रूप में उपयोग किया होगा (जैसे ओपी ने उल्लिखित एन), लेकिन चूंकि आप एमएसबी की अनुक्रमणिका का उपयोग करते हैं, यह वास्तव में संगत है। –

+0

इस मामले में क्या करना है? –