C में पूर्णांक मान से मुझे बिट-बाय-बिट डेटा कैसे मिलता है?


99

मैं एक दशमलव संख्या के बिट्स निकालना चाहता हूं।

उदाहरण के लिए, 7 बाइनरी 0111 है, और मैं बूल में संग्रहीत 0 1 1 1 सभी बिट्स प्राप्त करना चाहता हूं। ऐसा मैं किस प्रकार करूं?

ठीक है, एक लूप अच्छा विकल्प नहीं है, क्या मैं इसके लिए कुछ और कर सकता हूं?

जवाबों:


154

यदि आप k-th बिट n चाहते हैं, तो करें

(n & ( 1 << k )) >> k

यहां हम एक मुखौटा बनाते हैं, मास्क को n पर लागू करते हैं, और उसके बाद बस उस बिट को प्राप्त करने के लिए मास्क किए गए मान को सही तरीके से स्थानांतरित करते हैं। हम इसे और अधिक पूरी तरह से लिख सकते हैं:

    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;

आप यहां बिट-मास्किंग के बारे में अधिक पढ़ सकते हैं ।

यहाँ एक कार्यक्रम है:

#include <stdio.h>
#include <stdlib.h>

int *get_bits(int n, int bitswanted){
  int *bits = malloc(sizeof(int) * bitswanted);

  int k;
  for(k=0; k<bitswanted; k++){
    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;
    bits[k] = thebit;
  }

  return bits;
}

int main(){
  int n=7;

  int  bitswanted = 5;

  int *bits = get_bits(n, bitswanted);

  printf("%d = ", n);

  int i;
  for(i=bitswanted-1; i>=0;i--){
    printf("%d ", bits[i]);
  }

  printf("\n");
}

70
(n >> k) & 1समान रूप से मान्य है और मास्क लगाने की आवश्यकता नहीं है क्योंकि मास्किंग स्थिर होने के कारण मास्किंग से पहले के बजाय अन्य तरीके से चारों ओर घूम रहा है।
जो

@ जो आप समझा सकते हैं, शायद एक जवाब में, कृपया?
दान रोसेनस्टार्क

1
@Yar मेरी टिप्पणी एक छोटे से बढ़ा है और अनुरोध किया के रूप में एक नया उत्तर जोड़ा
जो

जानकारी के लिए ज्ञात बिट्स का उपयोग करते समय (जैसे नेटवर्क प्रोटोकॉल के लिए, जैसे कि वेबसोकेट्स), डेटा को कैन पर डालना structउपयोगी भी हो सकता है, क्योंकि आपको एक ही ऑपरेशन के साथ सभी आवश्यक डेटा मिलते हैं।
मिस्ट्री

@ affinger, क्या आप कृपया कोड का एक उदाहरण आउटपुट पोस्ट कर सकते हैं।
आशीष आहूजा

83

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

कम से कम महत्वपूर्ण बिट स्थिति में वांछित बिट को सही ढंग से स्थानांतरित करके, मास्किंग के साथ किया जा सकता है 1। प्रत्येक बिट के लिए एक नया मुखौटा मान की गणना करने की आवश्यकता नहीं है।

(n >> k) & 1

एक पूर्ण कार्यक्रम के रूप में, कंप्यूटिंग (और बाद में मुद्रण) एकल बिट मूल्यों की एक सरणी:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    unsigned
        input = 0b0111u,
        n_bits = 4u,
        *bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
        bit = 0;

    for(bit = 0; bit < n_bits; ++bit)
        bits[bit] = (input >> bit) & 1;

    for(bit = n_bits; bit--;)
        printf("%u", bits[bit]);
    printf("\n");

    free(bits);
}

यह मानते हुए कि आप इस मामले में सभी बिट्स की गणना करना चाहते हैं, और एक विशिष्ट नहीं, लूप को आगे बदल दिया जा सकता है

for(bit = 0; bit < n_bits; ++bit, input >>= 1)
    bits[bit] = input & 1;

यह inputजगह में संशोधन करता है और इस तरह एक निरंतर चौड़ाई, सिंगल-बिट शिफ्ट के उपयोग की अनुमति देता है, जो कुछ आर्किटेक्चर पर अधिक कुशल हो सकता है।


5

यह करने का एक तरीका है - कई अन्य हैं:

bool b[4];
int v = 7;  // number to dissect

for (int j = 0;  j < 4;  ++j)
   b [j] =  0 != (v & (1 << j));

यह समझना कठिन है कि लूप का उपयोग वांछित क्यों नहीं है, लेकिन लूप को अनियंत्रित करना काफी आसान है:

bool b[4];
int v = 7;  // number to dissect

b [0] =  0 != (v & (1 << 0));
b [1] =  0 != (v & (1 << 1));
b [2] =  0 != (v & (1 << 2));
b [3] =  0 != (v & (1 << 3));

या पिछले चार बयानों में निरंतर भावों का मूल्यांकन:

b [0] =  0 != (v & 1);
b [1] =  0 != (v & 2);
b [2] =  0 != (v & 4);
b [3] =  0 != (v & 8);

3

यहाँ यह करने के लिए एक बहुत ही सरल तरीका है;

int main()
{
    int s=7,l=1;
    vector <bool> v;
    v.clear();
    while (l <= 4)
    {
        v.push_back(s%2);
        s /= 2;
        l++;
    }
    for (l=(v.size()-1); l >= 0; l--)
    {
        cout<<v[l]<<" ";
    }
    return 0;
}

1

@prateek आपकी मदद के लिए धन्यवाद। मैं एक कार्यक्रम में उपयोग के लिए टिप्पणियों के साथ फ़ंक्शन को फिर से लिखता हूं। अधिक बिट्स के लिए 8 बढ़ाएं (पूर्णांक के लिए 32 तक)।

std::vector <bool> bits_from_int (int integer)    // discern which bits of PLC codes are true
{
    std::vector <bool> bool_bits;

    // continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
    for (int i = 0; i < 8; i++)
    {
        bool_bits.push_back (integer%2);    // remainder of dividing by 2
        integer /= 2;    // integer equals itself divided by 2
    }

    return bool_bits;
}

1

यदि आप कोई लूप नहीं चाहते हैं, तो आपको इसे लिखना होगा:

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    int num = 7;

    #if 0
        bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
    #else
        #define BTB(v,i) ((v) & (1u << (i))) ? true : false
        bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
        #undef BTB
    #endif

    printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);

    return 0;
}

जैसा कि यहां दिखाया गया है, यह एक इनिलाइज़र में भी काम करता है।


0
#include <stdio.h>

int main(void)
{
    int number = 7; /* signed */
    int vbool[8 * sizeof(int)];
    int i;
        for (i = 0; i < 8 * sizeof(int); i++)
        {
            vbool[i] = number<<i < 0;   
            printf("%d", vbool[i]);
        }
    return 0;
}

0

का उपयोग करते हुए std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();

यह एक उपयोगी तरीका है, लेकिन उदाहरण में कुछ गड़बड़ है। बिटसेट <n>, n बिट की संख्या है, इसलिए आकार (int) का उपयोग गलत है।
जेरी चाउ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.