2010-08-16 16 views
16

मैं एक सी प्रोग्राम लिख रहा हूँ। मैं एक चर चाहता हूं कि मैं एक char के रूप में उपयोग कर सकता हूं लेकिन मैं विशिष्ट बिट्स तक पहुंच भी सकता हूं। मैं सोच रहा था कि मैं इस तरह एक संघ का उपयोग कर सकता हूं ...क्या यूनियन के साथ व्यक्तिगत बिट्स तक पहुंचने का कोई तरीका है?

typedef union 
{ 
    unsigned char status; 
    bit bits[8]; 
}DeviceStatus; 

लेकिन संकलक इसे पसंद नहीं करता है। जाहिर है आप एक संरचना में बिट्स का उपयोग नहीं कर सकते हैं। तो मैं इसके बजाय क्या कर सकता हूं?

उत्तर

18

अवश्य, लेकिन आप वास्तव में तो फिर तुम DeviceStatus ds; के लिए उपयोग कर सकते हैं आप ds.u.bit1 उपयोग कर सकते हैं इस

typedef union 
{ 
    struct 
    { 
    unsigned char bit1 : 1; 
    unsigned char bit2 : 1; 
    unsigned char bit3 : 1; 
    unsigned char bit4 : 1; 
    unsigned char bit5 : 1; 
    unsigned char bit6 : 1; 
    unsigned char bit7 : 1; 
    unsigned char bit8 : 1; 
    }u; 
    unsigned char status; 
}DeviceStatus; 

तरह बिट्स परिभाषित करने के लिए एक struct उपयोग करना चाहते हैं। इसके अलावा, कुछ कंपाइलर्स वास्तव में आपको एक संघ के भीतर अज्ञात संरचनाएं करने की अनुमति देंगे, जैसे कि आप टाइप किए गए से आपको छोड़कर ds.bit1 तक पहुंच सकते हैं।

+0

सी 99 6.7.2.1/10: "एक कार्यान्वयन किसी भी एड्रेसेबल स्टोरेज इकाई को आवंटित कर सकता है जो थोड़ा सा क्षेत्र पकड़ने के लिए पर्याप्त है।" केवल एक 'char' आवंटित करने की आवश्यकता नहीं है, इसलिए यह संभव है कि कोई अलियासिंग न हो। इसके अलावा, यूनियन के भीतर अज्ञात संरचना मानक द्वारा आवश्यक है। – Potatoswatter

+0

क्या आपको संरचना का नाम देना है? – jjxtra

1
typedef union 
{ 
    unsigned char status; 
    struct bitFields 
    { 
    _Bool bit0 : 1; 
    _Bool bit1 : 1; 
    _Bool bit2 : 1; 
    _Bool bit3 : 1; 
    _Bool bit4 : 1; 
    _Bool bit5 : 1; 
    _Bool bit6 : 1; 
    _Bool bit7 : 1; 
    } bits; 
}DeviceStatus; 
+0

क्या सी 99 स्पेक _Bool प्रकार के लिए आकार परिभाषित करता है? मैंने एक त्वरित रूप देखा और कुछ भी स्पष्ट नहीं देखा। – torak

+0

@torak: परिभाषा के अनुसार, किसी भी प्रकार कम से कम 'char' के रूप में चौड़ा है। लेकिन यह यहां बिंदु नहीं है क्योंकि ये बिटकफील्ड हैं। संकलक वास्तव में * स्थिति के बिट्स पर फ़ील्ड 'बिटएक्स' रख सकता है, लेकिन इसके लिए कोई गारंटी नहीं है। –

+0

आप बिट-फ़ील्ड के प्रकार के लिए _Bool के किसी भी अभिन्न प्रकार का उपयोग कर सकते हैं जब तक कि कम से कम बिट्स की संख्या हो। चूंकि यहां उपयोग किया जाने वाला आकार 1 बिट है, वहां कोई बिट-फील्ड-स्वीकृत प्रकार नहीं है जो सेवा नहीं करेगा। –

3

आपके पास कुछ संभावनाएं हैं।

int bit0 = 1; 
int bit1 = 2; 
int bit2 = 4; 
int bit3 = 8; 
int bit4 = 16; 
int bit5 = 32; 
int bit6 = 64; 
int bit7 = 128; 

if (status & bit1) 
    // whatever... 

एक और है bitfields उपयोग करने के लिए:: एक बस बिट्स पर प्राप्त करने के लिए बूलियन गणित का उपयोग किया जाएगा

struct bits { 
    unsigned bit0 : 1; 
    unsigned bit1 : 1; 
    unsigned bit2 : 1; 
// ... 
}; 

typedef union { 
    unsigned char status; 
    struct bits bits; 
} status_byte; 

some_status_byte.status = whatever; 
if (status_byte.bits.bit2) 
    // whatever... 

पहला है (कम से कम यकीनन) अधिक पोर्टेबल है, लेकिन जब आप कर रहे हैं स्थिति बिट्स से निपटने, संभावना है कि कोड भी थोड़ा पोर्टेबल नहीं है, इसलिए आप इसके बारे में ज्यादा परवाह नहीं कर सकते हैं ...

+0

'हस्ताक्षर नहीं' 'char' की तुलना में एक बड़े डेटा प्रकार से मेल खाता है? यह 'sizeof (char) torak

+1

@ जेरी ताबूत: केवल आपके पहले संस्करण की स्थिति के बिट्स का उपयोग करने की गारंटी है। 'यूनियन' में, व्यक्तिगत 'बिटएक्स' फ़ील्ड को कंपाइलर को प्रसन्नता के रूप में जोड़ा जा सकता है। –

+0

@ टोरक: हाँ, हो सकता है। यदि यह आपके लिए एक समस्या है, तो आप संभवतः फ़ील्ड को सभी 'हस्ताक्षरित char' बनाना चाहते हैं। –

0

सी में संबोधित करने वाली सबसे छोटी इकाई हमेशा एक बाइट है (जिसे char कहा जाता है)। आप सीधे थोड़ा सा नहीं पहुंच सकते हैं। निकटतम रास्ता बिट्स तक पहुँचने के लिए प्राप्त करने bitpointer नामक एक डेटा प्रकार को परिभाषित करने और इसके लिए कुछ कार्य या मैक्रो निर्धारित करने का होगा:

#include <stdbool.h> 

typedef struct bitpointer { 
    unsigned char *pb; /* pointer to the byte */ 
    unsigned int bit; /* bit number inside the byte */ 
} bitpointer; 

static inline bool bitpointer_isset(const bitpointer *bp) { 
    return (bp->pb & (1 << bp->bit)) != 0; 
} 

static inline void bitpointer_set(const bitpointer *bp, bool value) { 
    unsigned char shifted = (value ? 1 : 0) << bp->bit; 
    unsigned char cleared = *bp->pb &~ (1 << bp->bit); 
    *(bp->pb) = cleared | shifted; 
} 

मैं यूनियनों के खिलाफ की सलाह देते हैं, क्योंकि यह कार्यान्वयन से परिभाषित कि क्या वे भर रहे हैं MSB है -to-lsb या lsb-to-msb (आईएसओ सी 99, 6.7.2.1p10 देखें)।

0

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

आपकी स्थिति में सामान्य तकनीक बिटवाई ऑपरेशंस का उपयोग करना है। बिट्स, जैसे के अर्थ के नाम पर स्थिरांक को परिभाषित करें,

#define FLAG_BUSY 0x01 
#define FLAG_DATA_AVAILABLE 0x02 
#define FLAG_TRANSMISSION_IN_PROGRESS 0x04 
... 
#define FLAG_ERROR 0x80 

तो पढ़ सकते हैं और अलग-अलग बिट्स लिखने के लिए:

if (status & FLAG_BUSY) ... /* test if the device is busy */ 
status &= ~FLAG_ERROR; /* turn off error flag */ 
status |= FLAG_TRANSMISSION_IN_PROGRESS /* turn on transmission-in-progress flag */ 
2

जैसा कि पहले ही कहा गया है, तो आप स्मृति छोटे समाधान नहीं कर सकते एक बाइट से सी में मैं एक मैक्रो लिखूंगा:

#define BIT(n) (1 << n) 

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

if (status & BIT(1)) { 
    // Do something if bit 1 is set 
} elseif (~status | BIT(2) { 
    // Do something else if bit 2 is cleared 
} else { 
    // Set bits 1 and 2 
    status |= BIT(1) | BIT(2) 
    // Clear bits 0 and 4 
    status &= ~(BIT(0) | BIT(4)) 
    // Toggle bit 5 
    status ^= BIT(5) 
} 

यह हो जाता है तो आप अपने प्रस्तावित प्रणाली के करीब पहुंच सकते हैं, जो प्रयोग करेंगे [बजाय() के]: के रूप में आप अपने कोड लिखने होगा।