संरचना के सरणी के अंत में खाली ब्रेसेस '{}' की क्या आवश्यकता है?


59

मैंने लिनक्स कर्नेल में कुछ कोड मारा :

static struct ctl_table ip_ct_sysctl_table[] = {
    {
        .procname   = "ip_conntrack_max",
        .maxlen     = sizeof(int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec,
    },
    // ...
    {
        .procname   = "ip_conntrack_log_invalid",
        .maxlen     = sizeof(unsigned int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec_minmax,
        .extra1     = &log_invalid_proto_min,
        .extra2     = &log_invalid_proto_max,
    },
    { }
};

यहाँ एक संरचना का सार समाप्त होता है { }। किस उद्देश्य से इसे जोड़ा गया था?
वैसे, इस कोड के थोड़ा ऊपर एक और सरणी है , लेकिन अंत में खाली ब्रेसिज़ के बिना।

मुझे एक सरणी के अंत में खाली ब्रेसिज़ का उपयोग कब करना चाहिए?


1
हम्म अगर यह सरणी के अंत को इंगित करने के लिए जोड़ा जाता है जैसे 0 स्ट्रिंग के अंत का संकेत देता है? सिर्फ अनुमान।
एरकलन

4
यह कुछ गैर-मानक जीसीसी विस्तार है। और इस तरह, यह बहुत कम या कोई प्रलेखन के साथ आता है ... मैं सिर्फ सभी डॉक्स पढ़ता हूं और मुझे खाली संरचना आरंभीक सूचियों के बारे में कुछ भी नहीं मिल रहा है। फिर भी यह संकलित करता है, जब तक कि आप सख्त आईएसओ के साथ मजबूर न करें -pedantic
लुंडिन

9
वैसे भी, यह एक "प्रहरी" मूल्य है, जो एक वस्तु है जो सरणी के अंत को चिह्नित करने के लिए शून्य / NULL पर सेट है।
लुंडिन

CPython एक्सटेंशन मॉड्यूल में प्रहरी भी आम हैं ।
मैक्सपावर

जवाबों:


38

यह विशेष रूप से परिवर्तन का हिस्सा था sysctl शुद्ध: अप्रयुक्त द्विआधारी sysctl कोड निकालें एरिक डब्ल्यू Biederman द्वारा प्रतिबद्ध, के अंतिम तत्व के प्रारंभ को बदलने ip_ct_sysctl_tableसे सरणी {0}के लिए {}(और कई अन्य सरणी initializations के समान परिवर्तन प्रदर्शन)।

ऐसा {0}लगता है कि पैटर्न बहुत लंबे समय तक रहा है, और दोनों {0}या {}अंतिम तत्व-आरंभीकरण आमतौर पर (लिनक्स स्रोत कोड में) स्पष्ट रूप से संदर्भित होता है Terminating entry, इसलिए संभवतः यह एक पैटर्न है जो इन सरणियों का उपभोग करने की अनुमति देता है बिना उनकी लंबाई जाने। शून्य-आरंभिक समाप्ति प्रविष्टि से टकराने पर उपभोग समाप्त करना। उदाहरण के लिए sound/aoa/fabrics/snd-aoa-fabric-layout.cशून्य-आरंभीकरण के इरादे में समान सरणियों के लिए भी एक टिप्पणी में स्पष्ट रूप से उल्लेख किया गया है, उदाहरण के लिए:

static struct codec_connection toonie_connections[] = {
  {
      .connected = CC_SPEAKERS | CC_HEADPHONE,
      .codec_bit = 0,
  },
  {} /* terminate array by .connected == 0 */
};

11
यह दिलचस्प होगा कि जीसीसी विस्तार के पक्ष में मानक सी को छोड़ने के लिए उनके औचित्य को जानना कार्यक्षमता के मामले में 100% के बराबर है। यह सब कोड को मानक C संकलक पर संकलन करने से रोक रहा है। है यही कारण है, माना जाता है कि 100% के बराबर है क्योंकि जीसीसी इस सुविधा दस्तावेज़ के लिए प्रतीत नहीं होता ... यह वह जगह है नहीं , एक शून्य लंबाई सरणी यह एक खाली प्रारंभकर्ता सूची है।
लुंडिन

@ लुंडिन नहीं देंगे int arr[] = {}(यह देखते हुए कि हम GNU खाली इनिशियलाइज़र एक्सटेंशन का उपयोग कर रहे हैं) परिणाम एक खाली सरणी में है; यानी, के आकार arrजा रहा है 0?
16

1
@ लुंडिन: cppreference पेज आईएसओ / IEC 9899: 2011 के शब्दों के साथ संघर्ष में है, जो इसके लिए अनुमति देता है (§6.7.9 (21))। कुल मिलाकर सदस्यों की तुलना में कोई भी शुरुआती लोग निस्संदेह "कम" नहीं हैं। तो यह एक कतार संकलक विस्तार नहीं है, लेकिन वैध सी।
डेमन

2
@ डैमोन यह मान्य सी नहीं है और यह अच्छी तरह से जाना जाता है ... जीसीसी-त्रुटि-त्रुटियों के साथ संकलन। यह समझने के लिए कि, आपको शुरुआती सूची के लिए वास्तविक वाक्यविन्यास को पढ़ने की आवश्यकता है, 6.7.9 के शीर्ष पर। कम से कम एक इनिशियलाइज़र होना चाहिए। यहां बताया गया है: stackoverflow.com/questions/17589533/… । विशेष रूप से { initializer-list }तब इनिशियलाइज़र सूची: designation(opt) initializerयाinitializer-list , designation(opt) initializer
लुंडिन

2
@ लुंडिन इस विशिष्ट उदाहरण में, कोई विचार नहीं है। लेकिन लिनक्स एक्सटेंशन में बड़े पैमाने पर gcc एक्सटेंशन का उपयोग किया जाता है।
बोब्सबर्नर

20

आप शायद शून्य-समाप्त स्ट्रिंग्स से परिचित हैं। ctl_table ip_ct_sysctl_table[]एक शून्य-समाप्त सरणी है, अर्थात अंतिम सरणी प्रविष्टि में सभी-शून्य सदस्य हैं।


1
तो सरणी के माध्यम से जा रहा है, आप जानते हैं कि आप अंत तक पहुँच चुके हैं जब उदा procnameशून्य है, या maxlenशून्य है।
पॉल ओगिलवी

1
@PaulOgilvie: खैर, उदाहरण अधूरा है। procnameएक char[100]मामले में यह ""शून्य नहीं हो सकता है । लेकिन नहीं तो हाँ।
MSalters

13

संरचना के सरणी के अंत में खाली ब्रेसेस '{}' की क्या आवश्यकता है?

स्पष्ट होने के लिए: सी सिंटैक्स आवश्यकताओं को पूरा करने के लिए "खाली ब्रेसेस '{} संरचना के अंत में" की आवश्यकता नहीं है।

मुझे एक सरणी के अंत में खाली ब्रेसिज़ का उपयोग कब करना चाहिए?

जब कोड संतरी मूल्य चाहता है ।

यह कार्यक्रम के लिए कभी-कभी सभी शून्य के अंतिम सरणी तत्व के लिए उपयोगी होता है - निश्चित रूप से अंत का पता लगाने के लिए। जरूरत सरणी के आवेदन के उपयोग से आता है ctl_table ip_ct_sysctl_table[]एक सी भाषा की जरूरत से नहीं,।


9

यह सरणी के अंत में एक शून्य आरंभीकृत तत्व है, ताकि सरणी के तत्वों की संख्या एक से बढ़ सके।

इस छोटे डेमो पर विचार करें:

#include <stdio.h>

struct Test
{
  int x;
  int y;
} arr[] =
{
    {1,2},
    {3,4},
//  {}
};

int main(void) {
    printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}

arrयदि आप {}सरणी आरंभीकरण सूची के अंत में असुविधा करते हैं , तो सरणी का आकार बदल जाएगा ।

आउटपुट:

साथ // {}(सरणी 2 तत्व है)

2

साथ {}(सरणी 3 तत्व है)

3

आगे की व्याख्या:

ip_ct_sysctl_tableसरणी केवल एक ही जगह है, यहाँ है कि कम से प्रयोग किया जाता है:

in->ctl_table = kmemdup(ip_ct_sysctl_table,
                sizeof(ip_ct_sysctl_table),
                GFP_KERNEL);

अतिरिक्त {}कुल आकार को बढ़ाता है ip_ct_sysctl_table


1
यह "सरणी के तत्वों की संख्या बढ़ाने के लिए" नहीं है, बल्कि सरणी के अंत को इंगित करने के लिए है।
पॉल ओगिलवी

6
लॉल नहीं। विचार यह है कि अब तक कोई भी इसे पूरी तरह से समझाने में सक्षम नहीं हुआ है, पूर्ण निश्चितता के साथ। निश्चितता का निकटतम कथन बस यही है { }कि एक इनिशियलाइज़र है। लेकिन क्यों अभी भी स्पष्ट नहीं है। इस प्रकार, अब वैसे भी के लिए, शब्द शायद शायद एक अच्छा विचार है। :)
ryyker
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.