केस स्टेटमेंट में {} का उपयोग करना। क्यों?


101

उपयोग करने के साथ बात क्या है {और }एक में caseबयान? आम तौर पर, एक caseबयान में कितनी लाइनें हैं , सभी लाइनों को निष्पादित किया जाता है। क्या यह सिर्फ पुराने / नए संकलक के बारे में एक नियम है या इसके पीछे कुछ है?

int a = 0;
switch (a) {
  case 0:{
    std::cout << "line1\n";
    std::cout << "line2\n";
    break;
  }
}

तथा

int a = 0;
switch (a) {
  case 0:
    std::cout << "line1\n";
    std::cout << "line2\n";
    break;
}

57
एक उपयोग केस स्टेटमेंट में घोषित चर के दायरे को सीमित करने के लिए हो सकता है।
अभिषेक बंसल


1
बहुत ज्यादा आक्रोश, भी। मामले केवल स्विच स्टेटमेंट के ब्लॉक के भीतर लेबल होते हैं: वे अतिरिक्त घोंसले के शिकार का परिचय नहीं देते हैं, इसलिए उन्हें switchकीवर्ड के साथ संरेखित करना चाहिए , और दूसरे उदाहरण में, संलग्न बयान केवल एक बार इंडेंट करते हैं। ध्यान दें कि आप के बाद एक अजीब चार अंतरिक्ष डी-इंडेंट कैसे है break;
काज

ध्यान दें, स्वीकृत उत्तर केवल आंशिक रूप से सही है क्योंकि जैक की टिप्पणी इंगित करती है और कुछ सूक्ष्मताओं को याद करती है, जिसे मैं अपने उत्तर में संबोधित करता हूं।
शफीक याघमौर 14

एक FYI के रूप में: C ++ के बजाय C (यहां तक ​​कि C11) में, आप एक घोषणा को लेबल नहीं कर सकते हैं; वे वाक्यात्मक श्रेणी में नहीं हैं statement। C ++ में, आप कर सकते हैं (वाक्यात्मक श्रेणी statementका एक घटक है declaration statement)।
जोनाथन लेफ़लर

जवाबों:


195

{}का एक नया खंड को दर्शाता गुंजाइश

निम्नलिखित बहुत ही महत्वपूर्ण उदाहरण पर विचार करें:

switch (a)
{
    case 42:
        int x = GetSomeValue();
        return a * x;
    case 1337:
        int x = GetSomeOtherValue(); //ERROR
        return a * x;
}

आपको संकलक त्रुटि मिलेगी क्योंकि xपहले से ही दायरे में परिभाषित किया गया है।

इन्हें अपने स्वयं के उप-दायरे में अलग करने से xस्विच स्टेटमेंट के बाहर घोषित करने की आवश्यकता समाप्त हो जाएगी ।

switch (a)
{
    case 42: {
        int x = GetSomeValue();
        return a * x; 
    }
    case 1337: {
        int x = GetSomeOtherValue(); //OK
        return a * x; 
    }
}

11
वास्तव में IMO आपको चर x की दूसरी घोषणा को छोड़ देने पर भी आपको एक कंपाइलर त्रुटि मिलेगी।
अभिषेक बंसल

1
हालांकि इस शैली का उपयोग करने और स्विच स्टेटमेंट के अंदर बड़े ब्लॉक लगाने से मामलों का पालन करना अपठनीय हो जाएगा। मैं बयानों को छोटा रखना पसंद करता हूं।
मसूद

2
@MatthieuM। मैं एक तथ्य के लिए जानता हूं कि एमएस विज़ुअल स्टूडियो 2010 में व्यवहार होगा अभिषेक इंगित करता है: यह एक मामले के अंदर किसी भी चर घोषणा को संकलित नहीं करेगा (जब तक आप उस मामले के भीतर एक नए दायरे को दर्शाने के लिए घुंघराले कोष्ठक का उपयोग नहीं करते हैं)। क्या यह मानकों से मेल खाता है, मुझे नहीं पता।
KRyan

1
@KRyan: यह नहीं है, लेकिन यह इतना सुरक्षित विकल्प है कि मैं शायद ही इसे लागू करने के लिए उन्हें दोष दे सकता हूं।
मैथ्यू एम।

6
मानक की धारा 6.7 (3) (2005 के मसौदे के लिए नंबरिंग) निर्दिष्ट करती है कि आप एक आरंभिक छलांग नहीं लगा सकते हैं, इसलिए आप किसी मामले के खंड में आरंभीकरण नहीं कर सकते।
जैक एदले

23

टी एल; डॉ

एकमात्र तरीका यह है कि आप किसी मामले के अंदर एक इंटेस्टाइज़र या कुछ गैर-तुच्छ वस्तु के साथ एक चर घोषित कर सकते हैं एक ब्लॉक स्कोप का उपयोग करके {}या अन्य नियंत्रण संरचना का परिचय दे सकता है जिसमें लूप या यदि स्टेटमेंट की तरह खुद का स्कोप है ।

Gory विवरण

हम देख सकते हैं कि केस सिर्फ लेबल स्टेटमेंट हैं जैसे कि किसी गोटो स्टेटमेंट के साथ इस्तेमाल किए गए लेबल ( यह C ++ ड्राफ्ट स्टैंडर्ड सेक्शन 6.1 लेबल स्टेटमेंट में कवर किया गया है ) और हम सेक्शन पैराग्राफ 3 से देख सकते हैं कि जम्पिंग पास एक घोषणा कई मामलों में अनुमति नहीं है। , जिनमें एक आरंभीकरण शामिल है:6.7

एक ब्लॉक में स्थानांतरित करना संभव है, लेकिन इस तरह से नहीं कि प्रारंभिककरण के साथ घोषणाओं को बायपास करें। एक प्रोग्राम जो 87 से एक बिंदु पर कूदता है जहां एक स्वचालित भंडारण अवधि वाला चर एक बिंदु के दायरे में नहीं होता है, जहां यह स्कोप होता है, जब तक कि चर स्केलर प्रकार नहीं होता है, वर्ग प्रकार एक तुच्छ डिफ़ॉल्ट निर्माता और एक तुच्छ डिस्ट्रक्टर के साथ होता है। इन प्रकारों में से एक का एक cv- योग्य संस्करण, या पूर्ववर्ती प्रकारों में से एक का एक सरणी और एक इनिशलाइज़र (8.5) के बिना घोषित किया गया है।

और यह उदाहरण प्रदान करता है:

void f() {
 // ...
 goto lx; // ill-formed: jump into scope of a

 ly:
  X a = 1;
 // ...
 lx:
  goto ly; // OK, jump implies destructor
          // call for a followed by construction
          // again immediately following label ly
}

ध्यान दें, यहां कुछ सूक्ष्मताएं हैं, आपको एक स्केलर घोषणा को पिछले करने की अनुमति दी गई है जिसमें एक आरंभीकरण नहीं है, उदाहरण के लिए:

switch( n ) 
{
    int x ;
    //int x  = 10 ; 
    case 0:
      x = 0 ;
      break;
    case 1:
      x = 1 ;
      break;
    default:
      x = 100 ;
      break ;
}

पूरी तरह से मान्य है ( लाइव उदाहरण )। बेशक, यदि आप प्रत्येक मामले में एक ही चर घोषित करना चाहते हैं, तो उन्हें प्रत्येक को अपने स्वयं के दायरे की आवश्यकता होगी लेकिन यह स्विच स्टेटमेंट के बाहर भी उसी तरह से काम करता है , ताकि कोई बड़ा आश्चर्य न हो।

छलांग लगाने की अनुमति नहीं देने के लिए औचित्य के अनुसार , दोष रिपोर्ट 467 हालांकि थोड़ा अलग मुद्दे को कवर करने के लिए स्वचालित चर के लिए एक उचित मामला प्रदान करता है :

[...] स्वचालित चर, यदि स्पष्ट रूप से आरंभिक नहीं हैं, तो ट्रैप अभ्यावेदन सहित अनिश्चित ("कचरा") मान हो सकते हैं, [...]

इस मामले को देखने के लिए शायद अधिक दिलचस्प है जहां आप कई मामलों में एक स्विच के भीतर एक गुंजाइश का विस्तार करते हैं, इसका सबसे प्रसिद्ध उदाहरण संभवतः डफ का उपकरण है जो कुछ इस तरह दिखाई देगा:

void send( int *to, const int *from, int  count)
{
        int n = (count + 7) / 8;
        switch(count % 8) 
        {
            case 0: do {    *to = *from++;   // <- Scope start
            case 7:         *to = *from++;
            case 6:         *to = *from++;
            case 5:         *to = *from++;
            case 4:         *to = *from++;
            case 3:         *to = *from++;
            case 2:         *to = *from++;
            case 1:         *to = *from++;
                        } while(--n > 0);    // <- Scope end
        }
}

6

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


4

यह एक बुनियादी संकलक प्रतिबंध की जाँच करें और आप सोच रहे होंगे कि क्या हो रहा है:

int c;
c=1;

switch(c)
{
    case 1:
    //{
        int *i = new int;
        *i =1;
        cout<<*i;
        break;
    //}

    default : cout<<"def";
}

यह आपको एक त्रुटि देगा:

error: jump to case label [-fpermissive]
error:   crosses initialization of int* i

जबकि यह एक नहीं होगा:

int c;
c=1;

switch(c)
{
    case 1:
    {
        int *i = new int;
        *i =1;
        cout<<*i;
        break;
    }

    default : cout<<"def";
}

1

रोकेट द्वारा कहा गया है कि स्विच में कोष्ठक का उपयोग गुंजाइश के एक नए ब्लॉक को दर्शाता है।

लेकिन यह स्पष्टता के लिए भी हो सकता है जब आप पढ़ते हैं। यह जानने के लिए कि मामला कहाँ रुकता है क्योंकि आपके पास इसमें सशर्त विराम हो सकता है।


0

कारण हो सकते हैं:

  1. पठनीयता, यह प्रत्येक मामले को स्कूप्ड सेक्शन के रूप में बढ़ाती है।
  2. कई स्विच मामलों के लिए एक ही नाम के साथ एक अलग चर घोषित करना।
  3. माइक्रो ऑप्टिमाइज़ेशन- वास्तव में महंगे संसाधन आवंटित चर के लिए गुंजाइश जो आप केस के दायरे को छोड़ते ही नष्ट करना चाहते हैं, या "GOTO" कमांड के उपयोग का स्पैगेटी परिदृश्य भी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.