c - for - संरचना का सी-आकार जब बिट फ़ील्ड का उपयोग किया जाता है और यह कैसे स्मृति में संग्रहीत होता है



struct (2)

कैसे बिट-फ़ील्ड मेमोरी में संग्रहीत है कार्यान्वयन निर्भर है।

एक संभावित कारण यह है कि बिट-फ़ील्ड में 17 बिट्स हैं, को कम से कम 3 बाइट्स रखना चाहिए, लेकिन कंपाइलर इसे 4 बाइट्स में पैड करना चुनता है।

दोबारा, बिट-फील्ड के बारे में लगभग सब कुछ कार्यान्वयन पर निर्भर है, जिसमें उनका आकार और स्मृति लेआउट शामिल है

अंतिम, void main उपयोग न करें, हमेशा int main साथ रहें

void main()
{
  struct bitfield
  {
    signed int a :3;
    unsigned int b :13;
    unsigned int c :1;
  };

  struct bitfield bit1 = { 2, 14, 1 };
  clrscr();
  printf("%d", sizeof(bit1));
  getch();
}

आकार यहाँ 4 बाइट्स क्यों है? और इन तत्वों को स्मृति में कैसे ठीक किया जाता है?


Answer #1

बिट क्षेत्रों का लगभग हर पहलू क्रियान्वयन को परिभाषित किया गया है यहां तक ​​कि 'सादे int बिट' क्षेत्र के हस्ताक्षर को परिभाषित किया गया है; यह हस्ताक्षरित या हस्ताक्षरित हो सकता है खेतों का लेआउट - चाहे वे सबसे महत्वपूर्ण बिट से कम-से-कम महत्वपूर्ण बिट को 'यूनिट' (मानक में प्रयुक्त शब्द) या कम से कम सबसे महत्वपूर्ण में परिभाषित किया गया है। सबसे बड़ा स्वीकार्य बिट फील्ड का आकार; जब एक बिट क्षेत्र को एक नई इकाई में संग्रहित किया जाता है; ये सभी क्रियान्वयन परिभाषित हैं

उदाहरण के लिए, मैक ओएस एक्स 10.8.4 जीसीसी 4.8.1 का उपयोग करते हुए, यह प्रदर्शित करना संभव है कि प्रश्न में struct bitfield को 3 कम महत्वपूर्ण बिट्स (बिट्स 0-2) पर कब्जा कर लिया गया है, b अगले स्थान पर कब्जा कर रहा है 13 बिट (3-15), और c अगले 1 बिट (16) पर कब्जा कर रहा है:

#include <stdio.h>

static void print_info(int v);

int main(void)
{
    int values[] =
    {
        0x55555555, 0xAAAAAAAA, 0x87654321, 0xFEDCBA98,
        0xFEDCBA90, 0xFEDCBA91, 0xFEDCBA92, 0xFEDCBA93,
        0xFEDCBA94, 0xFEDCBA95, 0xFEDCBA96, 0xFEDCBA97,
        0xFEDCBA98, 0xFEDCBAA0, 0xFEDCBAA8, 0x0000BAA0,
        0x0001BAA0, 0x00000008, 0x00000010, 0x00000018,
        0x0000FFF0, 0x0000FFF8,
    };

    for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); i++)
        print_info(values[i]);
    return 0;
}

static void print_info(int v)
{
    union
    {
        unsigned int x;
        struct bitfield
        {
            signed int   a:3;
            unsigned int b:13;
            unsigned int c:1;
        } y;
    } u;
    u.x = v;
    printf("0x%.8X => %2d 0x%.4X %1X\n", u.x, u.y.a, u.y.b, u.y.c);
}

नमूना आउटपुट:

0x55555555 => -3 0x0AAA 1
0xAAAAAAAA =>  2 0x1555 0
0x87654321 =>  1 0x0864 1
0xFEDCBA98 =>  0 0x1753 0
0xFEDCBA90 =>  0 0x1752 0
0xFEDCBA91 =>  1 0x1752 0
0xFEDCBA92 =>  2 0x1752 0
0xFEDCBA93 =>  3 0x1752 0
0xFEDCBA94 => -4 0x1752 0
0xFEDCBA95 => -3 0x1752 0
0xFEDCBA96 => -2 0x1752 0
0xFEDCBA97 => -1 0x1752 0
0xFEDCBA98 =>  0 0x1753 0
0xFEDCBAA0 =>  0 0x1754 0
0xFEDCBAA8 =>  0 0x1755 0
0x0000BAA0 =>  0 0x1754 0
0x0001BAA0 =>  0 0x1754 1
0x00000008 =>  0 0x0001 0
0x00000010 =>  0 0x0002 0
0x00000018 =>  0 0x0003 0
0x0000FFF0 =>  0 0x1FFE 0
0x0000FFF8 =>  0 0x1FFF 0

परीक्षण मान पूरी तरह यादृच्छिक पर नहीं चुना जाता है। परीक्षण मानों से 0xFEDCBA90 से 0xFECBA97, हम देख सकते हैं कि कम से कम महत्वपूर्ण 3 बिट्स में a । परीक्षा मान 0x0000BAA0 और 0x0001BAA0 से, हम देख सकते हैं कि 17 वीं बिट (या बिट 16) में c और परीक्षण मानों से 0x00000008 से 0x0000FFF8, हम देख सकते हैं कि बिट्स 3-15 में b

हालांकि, यह बताया जाना चाहिए कि कोड सिद्धांत में बहस योग्य पोर्टेबल है; क्योंकि कोड ux को लिखता है और फिर ux और uya , uya और uya पढ़ता है, यह उस यूनियन के सदस्य तक पहुंच नहीं रहा है जो पिछले लिखा गया है, जो कड़ाई से अपरिभाषित व्यवहार है। व्यवहार में, यह 'हमेशा' काम करता है (मैंने एक सिस्टम के बारे में नहीं सुना है, जहां यह काम नहीं करता है - यह संभावना नहीं है, लेकिन तकनीकी रूप से असंभव नहीं है कि ऐसा सिस्टम है जहां यह काम नहीं करता है)।

यह लेआउट केवल कल्पना के किसी भी माध्यम से संभव लेआउट नहीं है। हालांकि, मेरे पास संकलक या सिस्टम तक पहुंच नहीं है जो वैकल्पिक लेआउट प्रदर्शित करते हैं।

आईएसओ / आईईसी 9899: 2011 में, खंड §6.7.2.1 संरचना और संघ विनिर्देशक कहते हैं:

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

¶12 कोई घोषणाकर्ता के साथ एक बिट-फील्ड घोषणा, लेकिन केवल एक बृहदान्त्र और चौड़ाई, एक अनाम बिट-फ़ील्ड इंगित करता है 126) विशेष मामले के रूप में, 0 की चौड़ाई वाले बिट-फील्ड मैनेजमेंट सदस्य इंगित करता है कि उस इकाई में कोई और बिट-फील्ड पैक नहीं किया जाता है जिसमें पिछले बिटफ़ील्ड, यदि कोई हो, तो रखा गया था।

126) एक अज्ञात बिट-फील्ड संरचना सदस्य बाह्य रूप से लगाए गए लेआउट के अनुकूल होने के लिए पैडिंग के लिए उपयोगी है।

सवाल में संरचना का मामूली प्रकार है:

struct exegesis
{
    signed int   a:3;
    unsigned int  :0;
    unsigned int b:13;
    unsigned int  :0;
    unsigned int c:1;
};

इस संरचना का आकार 12 (पहले के रूप में एक ही संकलक / मंच पर है)। इस प्लेटफॉर्म पर बिट फ़ील्ड के लिए स्टोरेज यूनिट 4 बाइट्स है, इसलिए गुमनाम शून्य-चौड़ाई वाले फ़ील्ड एक नया स्टोरेज यूनिट शुरू करते हैं। a को पहले 4-बाइट यूनिट के कम से कम 3 बिट में संग्रहीत किया जाता है; b में 4 बिट बाइट यूनिट के कम से कम 13 बिट्स; और तीसरे 4-बाइट यूनिट के कम से कम महत्वपूर्ण बिट में c । जैसा कि मानक से उद्धरण में उल्लेख किया गया है, आप अज्ञात बिट फ़ील्ड जो 0 से भी बड़ी हैं, हो सकते हैं।





struct