2013-03-07 7 views
16

-5 से फिर से सवाल उठाया!स्विच-कथन के बारे में सोचने वाला कंपाइलर क्या है?

मैं [this comment] @Quartermeister की और चकित कर दिया गया पढ़ें!

तो क्यों इस

switch(1) { 
    case 2: 
} 

संकलित लेकिन यह नहीं करता है।

int i; 

switch(i=1) { 
    case 2: // Control cannot fall through from one case label ('case 2:') to another 
} 

न तो इस

switch(2) { 
    case 2: // Control cannot fall through from one case label ('case 2:') to another 
} 

अद्यतन:

-5 सवाल -3 बन गया।

+1

यह संभव है कि संकलक पहले को अनुकूलित कर सके, लेकिन असाइनमेंट के कारण दूसरे को हटा नहीं सकता है। –

+0

मेरा अनुमान है कि '1' एक स्थिर अभिव्यक्ति है जिसे संकलन समय पर जाना जाता है, जिससे संकलक पूरे स्विच को अनुकूलित कर देता है, जबकि 'i = 1' एक गैर-निरंतर अभिव्यक्ति है (यद्यपि संकलक को विशिष्ट मान उत्पन्न करने के लिए भी जाना जाता है) तो संकलक स्विच रखने की कोशिश करता है। – dasblinkenlight

+0

एक आदर्श दुनिया में, संकलक शायद इन दोनों को स्वीकार या अस्वीकार कर देना चाहिए। यह निश्चित रूप से उनके लिए कोई कोड उत्पन्न नहीं करना चाहिए। लेकिन इस दुनिया में, मुझे लगता है कि यह "फोरेस्ट गंप प्रभाव:" का एक और उदाहरण है: बेवकूफ बेवकूफ है ":) प्रश्न: समय/मस्तिष्क को बर्बाद क्यों करते हैं? – paulsm4

उत्तर

21

उनमें से कोई भी संकलित होना चाहिए। सी # विनिर्देश के लिए एक स्विच खंड में कम से कम एक कथन है। पार्सर इसे अस्वीकार कर देना चाहिए।

चलिए इस तथ्य को अनदेखा करते हैं कि पार्सर खाली कथन सूची की अनुमति देता है; यह प्रासंगिक नहीं है। विनिर्देश कहता है कि स्विच खंड के अंत में एक पहुंच योग्य अंत बिंदु नहीं होना चाहिए; यह प्रासंगिक बिट है।

void M(int x) { switch(2) { case 2: ; } } 

तो यह एक त्रुटि होना चाहिए:

अपने पिछले उदाहरण में, स्विच खंड एक से पहुंचा जा सकता अंत बिंदु है।

यदि आप था:

void M(int x) { switch(x) { case 2: ; } } 

तो संकलक अगर एक्स कभी 2. हो जाएगा यह परंपरागत ढंग से मान लिया गया है कि यह कर सकते थे, और कहता है कि खंड एक से पहुंचा जा सकता अंत बिंदु है पता नहीं है, क्योंकि स्विच मामले लेबल पहुंच योग्य है।

यदि आप

void M(int x) { switch(1) { case 2: ; } } 

था तब संकलक कारण सकता है कि अंत बिंदु पहुंच योग्य नहीं है क्योंकि मामला लेबल पहुंच योग्य नहीं है। संकलक जानता है कि लगातार 1 यदि आप था निरंतर 2.

के बराबर नहीं है:

void M(int x) { switch(x = 1) { case 2: ; } } 

या

void M(int x) { x = 1; switch(x) { case 2: ; } } 

तो आप जानते हैं और मुझे पता है कि अंत बिंदु नहीं है पहुंचने योग्य, लेकिन संकलक उसे नहीं जानता है। विनिर्देशन में नियम यह है कि पहुंच क्षमता केवल निरंतर अभिव्यक्तियों का विश्लेषण करके निर्धारित की जाती है। कोई भी अभिव्यक्ति जिसमें एक चर शामिल है, भले ही आप किसी अन्य माध्यम से अपना मान जानते हों, निरंतर अभिव्यक्ति नहीं है।

अतीत में सी # कंपाइलर में ऐसी चीजें थीं जहां यह मामला नहीं था। आप जैसी चीजों कह सकते हैं:

void M(int x) { switch(x * 0) { case 2: ; } } 

और संकलक कारण होता है कि एक्स * 0 0 होना ही था, इसलिए मामले लेबल पहुंच योग्य नहीं है। वह एक बग था, जिसे मैंने सी # 3.0 में तय किया था। विनिर्देश कहता है कि केवल स्थिरांक का उपयोग उस विश्लेषण के लिए किया जाता है, और x एक चर है, स्थिर नहीं है।

अब, यदि प्रोग्राम कानूनी है तो संकलक इस तरह की उन्नत तकनीकों का उपयोग कर सकते हैं ताकि कोड उत्पन्न हो सके। आप कहते हैं कि कुछ की तरह हैं:

void M(int x) { if (x * 0 == 0) Y(); } 

फिर संकलक है जैसे कि आप

void M(int x) { Y(); } 

लिखा था अगर यह चाहता कोड उत्पन्न कर सकते हैं।लेकिन यह इस तथ्य का उपयोग नहीं कर सकता कि x * 0 == 0 कथन पहुंचने के उद्देश्य के लिए सच है।

अंत में, यदि आप

void M(int x) { if (false) switch(x) { case 2: ; } } 

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

void M(int x) { if (x * 0 != 0) switch(x) { case 2: ; } } 

false रूप x * 0 != 0 का इलाज नहीं है, इसलिए अंत बिंदु पहुंच योग्य माना जाता है।

+0

धन्यवाद। मैंने 'स्विच (एक्स) {} 'के लिए परीक्षण किया, यह संकलित करता है, है ना? –

+0

@ केनकिन: यह कानूनी है; शून्य स्विच खंडों को रखने के लिए एक स्विच की अनुमति है। –

1

ठीक है, तो इस के साथ समस्या यह है कि संकलक पूरी तरह से स्विच दूर का अनुकूलन, और यहाँ है सबूत है:

static void withoutVar() 
{ 
    Console.WriteLine("Before!"); 

    switch (1) 
    { 
     case 2: 
    } 

    Console.WriteLine("After!"); 
} 

कौन सा है, जब ILSpy साथ decompiled, हमें इस आईएल पता चलता है:

.method private hidebysig static 
    void withoutVar() cil managed 
{ 
    // Method begins at RVA 0x2053 
    // Code size 26 (0x1a) 
    .maxstack 8 

    IL_0000: nop 
    IL_0001: ldstr "Before!" 
    IL_0006: call void [mscorlib]System.Console::WriteLine(string) 
    IL_000b: nop 
    IL_000c: br.s IL_000e 

    IL_000e: ldstr "After!" 
    IL_0013: call void [mscorlib]System.Console::WriteLine(string) 
    IL_0018: nop 
    IL_0019: ret 
} // end of method Program::withoutVar 

जिसमें कहीं भी स्विच कथन की कोई याद नहीं है। I सोचें कि कारण यह दूसरे को ऑप्टिमाइज़ नहीं करता है, साथ ही ऑपरेटर ओवरलोडिंग और सॉर्ट के साथ कुछ करने के लिए भी हो सकता है। तो, यह संभव हो सकता है कि मेरे पास एक कस्टम प्रकार है जो 1 को सौंपा गया है, यह 2 में बदल जाता है। हालांकि, मुझे पूरी तरह से यकीन नहीं है, मुझे लगता है कि एक बग रिपोर्ट जमा की जानी चाहिए।

+0

"... लूप को अनुकूलित करता है," ... क्या लूप? मुझे लगता है कि आप स्विच मतलब था। –

+0

@JimMischel अच्छा बिंदु, तय। –

+2

यह एक बग नहीं है; कृपया एक रिपोर्ट जमा न करें। –

2

विजुअल स्टूडियो 2012 में, पहला कारण स्पष्ट है। संकलक निर्धारित करता है कि कोड पहुंच योग्य नहीं है:

switch (1) 
{ 
    case 2: 
} 

चेतावनी: पहुंचने योग्य कोड का पता चला।

अन्य दो मामलों में, कंपाइलर रिपोर्ट करता है "नियंत्रण एक केस लेबल ('केस 2:') से दूसरे में नहीं गिर सकता है"। मैं इसे किसी भी असफल मामलों में "('केस 1')" नहीं कह रहा हूं।

मुझे लगता है कि संकलक निरंतर मूल्यांकन के बारे में आक्रामक नहीं है। जब यह मूल्यांकन करते हैं और तय करते हैं कि आप क्या लिख ​​रहे हैं सकता है,

int i; 
switch(i=1) 
{ 
    case 2: 
} 

और

int i = 1; 
switch(i) 
{ 
    case 2: 
} 

दोनों मामलों में, संकलक कोड उत्पन्न करने के लिए प्रयास करता है: उदाहरण के लिए, निम्नलिखित के बराबर हैं है:

switch (1) 
{ 
    case 2: 
} 

और यह निर्धारित करें कि कोड पहुंच योग्य नहीं है।

मुझे संदेह है कि "यह संकलन क्यों नहीं है" उत्तर होगा "क्योंकि हम जेआईटी कंपाइलर को आक्रामक अनुकूलन को संभालने देते हैं।"

+0

धन्यवाद। मैंने संशोधित किया। –

संबंधित मुद्दे

 संबंधित मुद्दे