क्या एक वैरिएबल इनिशियलाइज़ेशन पर कूदना बीमार-निर्मित है या क्या यह अपरिभाषित व्यवहार का कारण बनता है?


17

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

void foo()
{
    goto bar;
    int x = 0;
    bar: ;
}

जीसीसी और क्लैंग इसे अस्वीकार करते हैं , क्योंकि कूदने से bar:चर आरंभीकरण को दरकिनार कर देता है। MSVC बिल्कुल भी शिकायत नहीं करता ( चेतावनी के xबाद उपयोग करने के अलावा bar:)।

हम एक के साथ एक समान काम कर सकते हैं switch:

void foo()
{
    switch (0)
    {
        int x = 0;
        case 0: ;
    }
}

अब सभी तीन संकलक त्रुटियों का उत्सर्जन करते हैं

क्या वे स्निपेट्स बीमार हैं? या वे यूबी का कारण बनते हैं?

मुझे लगता था कि दोनों बीमार थे, लेकिन मैं मानक के नए हिस्सों को नहीं खोज सकता। [stmt.goto] इस बारे में कुछ नहीं कहता, और न ही [stmt.select]


1
यदि आप xछलांग के बाद उपयोग करते हैं तो मुद्दा अधिक तुच्छ होगा ।
Jarod42

1
मानक नहीं, लेकिन यहां कोई इस पर कुछ जानकारी पा सकता है: en.cppreference.com/w/cpp/language/goto विशेष रूप से: "यदि नियंत्रण का हस्तांतरण किसी भी स्वचालित चर के दायरे में प्रवेश करता है (जैसे कि एक घोषणा पर आगे कूदकर बयान), यह कार्यक्रम बीमार है (संकलित नहीं किया जा सकता है), जब तक कि ... "
idclev 463035818

/permissive-ध्वज को MSVC में जोड़ें और यह शिकायत भी करेगा। मैं नहीं जानता कि क्या उस ध्वज के बिना MSVC का व्यवहार अच्छी तरह से परिभाषित है (मैं ऐसा मानूंगा, अन्यथा वे इसे अनुमति क्यों देंगे?)।
अखरोट

@walnut "अन्यथा वे इसे" पिछड़े सम्प्रभुता के लिए संभवतः अनुमति देते हैं , या क्योंकि वे मानक के बारे में बहुत ज्यादा परवाह नहीं करते हैं। सभी प्रमुख कंपाइलर डिफ़ॉल्ट सेटिंग्स के तहत मानक के अनुरूप नहीं हैं।
होलीब्लैककट

जवाबों:


20

जब गैर-रिक्त है, तो यह बीमार है।

[Stmt.dcl]

3 यह एक ब्लॉक में स्थानांतरित करना संभव है, लेकिन एक तरह से नहीं है कि प्रारंभिककरण के साथ घोषणाओं को दरकिनार किया जाता है (शर्तों और init-बयानों में लोगों सहित)। एक प्रोग्राम जो उस बिंदु से कूदता है जहां एक स्वचालित भंडारण अवधि वाला चर उस बिंदु के दायरे में नहीं होता है जहां वह दायरे में होता है, जब तक कि वैरिएबल में वैरिअलाइज़ेशन ([basic.life]) नहीं होता है। ऐसे मामले में, रिक्त आरंभीकरण वाले चर उनकी घोषणा के क्रम में निर्मित होते हैं।

इनिशियलाइज़र इनिशियलाइज़ेशन को गैर-रिक्त बनाता है। इसके विपरीत, यह

void foo()
{
    goto bar;
    int x; // no initializer
    bar: ;
}

अच्छी तरह से बनेगा। हालांकि xएक अनिश्चित मूल्य के साथ उपयोग करने के बारे में सामान्य कैविट्स लागू होंगे।


क्या चर घोषणाओं के दायरे में पहली बात नहीं है?
क्रंचर

4
@ क्रंचर - C89 को इसकी आवश्यकता थी। C ++ ने कभी नहीं किया, और न ही आधुनिक C अब और नहीं करता है।
स्टोरीटेलर - अनसलैंडर मोनिका

3

से गोटो बयान :

यदि नियंत्रण का हस्तांतरण किसी भी स्वचालित चर के दायरे में आता है (जैसे कि एक घोषणा बयान पर आगे कूदकर), ​​तो कार्यक्रम बीमार है (संकलित नहीं किया जा सकता है), जब तक कि सभी चर जिनके दायरे में प्रवेश नहीं किया जाता है

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