TL; DR: मुझे नहीं लगता कि व्यवहार int a[5]={a[2]=1};
को अच्छी तरह से परिभाषित किया गया है, कम से कम C99 में।
मज़ेदार हिस्सा यह है कि केवल बिट जो मेरे लिए समझ में आता है वह वह हिस्सा है जिसके बारे में आप पूछ रहे हैं: a[0]
यह निर्धारित किया गया है 1
क्योंकि असाइनमेंट ऑपरेटर उस मान को लौटाता है जो असाइन किया गया था। यह सब कुछ है जो अस्पष्ट है।
यदि कोड int a[5] = { [2] = 1 }
होता है, तो सब कुछ आसान हो जाता है: यह एक निर्दिष्ट शुरुआती सेटिंग a[2]
है 1
और बाकी सब कुछ 0
। लेकिन { a[2] = 1 }
हमारे पास असाइनमेंट एक्सप्रेशन वाला एक गैर-नामित इनिशलाइज़र है, और हम एक खरगोश छेद नीचे गिरते हैं।
यहाँ मैंने अभी तक क्या पाया है:
a
स्थानीय चर होना चाहिए।
6.7.8 प्रारंभिक
- किसी ऑब्जेक्ट के लिए इनिशियलाइज़र के सभी भाव जिसमें स्थिर भंडारण अवधि होती है, स्थिर अभिव्यक्ति या स्ट्रिंग शाब्दिक होगा।
a[2] = 1
एक स्थिर अभिव्यक्ति नहीं है, इसलिए a
स्वचालित भंडारण होना चाहिए।
a
अपने स्वयं के प्रारंभ में गुंजाइश है।
6.2.1 पहचानकर्ताओं के स्कोप
- संरचना, संघ और गणना टैग में गुंजाइश होती है जो टैग को घोषित करने वाले टाइप स्पेसियर में टैग की उपस्थिति के ठीक बाद शुरू होती है। प्रत्येक एन्यूमरेशन स्थिरांक में वह गुंजाइश होती है जो किसी एन्यूमरेटर सूची में अपने परिभाषित एन्यूमरेटर की उपस्थिति के ठीक बाद शुरू होती है। किसी अन्य पहचानकर्ता के पास वह गुंजाइश है जो उसके घोषणाकर्ता के पूरा होने के ठीक बाद शुरू होती है।
घोषणाकर्ता है a[5]
, इसलिए वैरिएबल अपने स्वयं के प्रारंभ में दायरे में हैं।
a
अपने स्वयं के प्रारंभ में जीवित है।
6.2.4 वस्तुओं का भंडारण अवधि
एक वस्तु जिसका पहचानकर्ता कोई संबंध के साथ और भंडारण-वर्ग विनिर्देशन के बिना घोषित किया जाता है static
है स्वत: भंडारण अवधि ।
ऐसी वस्तु जिसके लिए एक चर लंबाई सरणी प्रकार नहीं है, उसका जीवनकाल उस ब्लॉक में प्रवेश से फैलता है जिसके साथ यह जुड़ा हुआ है जब तक कि किसी भी तरह से उस ब्लॉक का निष्पादन समाप्त नहीं हो जाता। (एक संलग्न ब्लॉक में प्रवेश करना या किसी फ़ंक्शन को कॉल करना निलंबित करता है, लेकिन समाप्त नहीं होता है, वर्तमान ब्लॉक का निष्पादन।) यदि ब्लॉक को पुनरावर्ती रूप से दर्ज किया जाता है, तो प्रत्येक बार ऑब्जेक्ट का एक नया उदाहरण बनाया जाता है। वस्तु का प्रारंभिक मूल्य अनिश्चित है। यदि ऑब्जेक्ट के लिए एक इनिशियलाइज़ेशन निर्दिष्ट किया जाता है, तो इसे हर बार प्रदर्शन किया जाता है जब घोषणा ब्लॉक के निष्पादन में पहुंच जाती है; अन्यथा, मूल्य हर बार घोषित होने पर अनिश्चित हो जाता है।
के बाद एक अनुक्रम बिंदु है a[2]=1
।
6.8 विवरण और ब्लॉक
- एक पूर्ण अभिव्यक्ति एक अभिव्यक्ति है जो किसी अन्य अभिव्यक्ति या एक घोषणाकर्ता का हिस्सा नहीं है। निम्नलिखित में से प्रत्येक एक पूर्ण अभिव्यक्ति है: एक इनिशियलाइज़र ; एक अभिव्यक्ति बयान में अभिव्यक्ति; चयन कथन (
if
या switch
) की नियंत्रित अभिव्यक्ति ; एक while
या do
बयान की नियंत्रण अभिव्यक्ति ; for
कथन के प्रत्येक (वैकल्पिक) भाव ; एक return
बयान में (वैकल्पिक) अभिव्यक्ति । पूर्ण अभिव्यक्ति का अंत एक अनुक्रम बिंदु है।
ध्यान दें कि में जैसे हिस्सा initializers की एक ब्रेस संलग्न सूची, जिनमें से प्रत्येक के बाद एक दृश्य बिंदु है।int foo[] = { 1, 2, 3 }
{ 1, 2, 3 }
प्रारंभिक सूची क्रम में प्रारंभिक प्रदर्शन किया जाता है।
6.7.8 प्रारंभिक
- प्रत्येक ब्रेस-एनक्लोज़र इनिशियलाइज़र सूची में एक संबद्ध करंट ऑब्जेक्ट होता है । जब कोई पदनाम मौजूद नहीं होता है, तो वर्तमान वस्तु के प्रकार के अनुसार वर्तमान वस्तु के उप-खंडों को आरंभ किया जाता है: उप-क्रम में सरणी तत्व, घोषणा क्रम में संरचना सदस्य, और संघ के पहले नामित सदस्य। [...]
- इनिशियलाइज़र सूची क्रम में हो सकता है, प्रत्येक इनिशियलाइज़र किसी विशेष सबबॉजेक्ट के लिए प्रदान किया जाता है जो उसी सब -जेक्ट के लिए किसी भी पहले सूचीबद्ध इनिशियलाइज़र को ओवरराइड करता है; स्पष्ट रूप से प्रारंभ नहीं किए गए सभी उप-ऑब्जेक्ट्स को प्रारंभिक रूप से समान रूप से समान किया जाएगा, जिसमें स्थिर भंडारण अवधि है।
हालांकि, प्रारंभिक अभिव्यक्तियों का क्रम में मूल्यांकन आवश्यक नहीं है।
6.7.8 प्रारंभिक
- वह क्रम जिसमें आरम्भिक सूची के भावों के बीच कोई दुष्प्रभाव होता है, अनिर्दिष्ट है।
हालाँकि, अभी भी कुछ प्रश्न अनुत्तरित हैं:
अनुक्रम बिंदु भी प्रासंगिक हैं? मूल नियम है:
6.5 भाव
- पिछले और अगले अनुक्रम बिंदु के बीच एक वस्तु का एक अभिव्यक्ति के मूल्यांकन के द्वारा एक बार में इसका संग्रहित मूल्य संशोधित होगा । इसके अलावा, स्टोर किए जाने वाले मूल्य को निर्धारित करने के लिए पूर्व मूल्य केवल पढ़ा जाएगा।
a[2] = 1
एक अभिव्यक्ति है, लेकिन आरंभीकरण नहीं है।
यह अनुबंध जे द्वारा थोड़ा विरोधाभास है:
J.2 अपरिभाषित व्यवहार
- दो अनुक्रम बिंदुओं के बीच, एक वस्तु को एक से अधिक बार संशोधित किया जाता है, या संशोधित किया जाता है और संग्रहीत मूल्य (6.5) निर्धारित करने के अलावा पूर्व मूल्य को पढ़ा जाता है।
एनेक्स जे कहते हैं कि कोई भी संशोधन मायने रखता है, न कि केवल अभिव्यक्ति द्वारा संशोधन। लेकिन यह देखते हुए कि एनेक्स गैर-आदर्श हैं, हम शायद इसे अनदेखा कर सकते हैं।
आरंभिक अभिव्यक्तियों के संबंध में सबोबिज इनिशियलाइज़ेशन को किस प्रकार अनुक्रमित किया जाता है? क्या सभी इनिशियलाइज़र का पहले (किसी क्रम में) मूल्यांकन किया जाता है, फिर सबबॉजेक्ट्स को इनिशियलाइज़ किया जाता है (इनिशियल लिस्ट ऑर्डर में)? या उन्हें इंटरलेव किया जा सकता है?
मुझे लगता int a[5] = { a[2] = 1 }
है कि इस प्रकार निष्पादित किया जाता है:
a
जब इसके ब्लॉक में प्रवेश किया जाता है, तो इसके लिए भंडारण आवंटित किया जाता है। इस बिंदु पर सामग्री अनिश्चित है।
- (केवल) इनिशियलाइज़र को निष्पादित
a[2] = 1
किया जाता है ( ), उसके बाद एक अनुक्रम बिंदु। यह स्टोर करता 1
है a[2]
और लौटता है 1
।
- इसका
1
उपयोग इनिशियलाइज़ करने के लिए किया जाता है a[0]
(पहला इनिलाइज़र पहले सबोबिज को इनिशियलाइज़ करता है)।
लेकिन यहाँ बातें फजी क्योंकि शेष तत्वों (मिल a[1]
, a[2]
, a[3]
, a[4]
) के लिए शुरू किए जाने की अपेक्षा की जाती है 0
, लेकिन यह स्पष्ट नहीं है जब: यह पहले होता है a[2] = 1
मूल्यांकन किया जाता है? यदि ऐसा है, a[2] = 1
तो "जीत" और अधिलेखित हो जाएगा a[2]
, लेकिन क्या उस असाइनमेंट में अपरिभाषित व्यवहार होगा क्योंकि शून्य आरंभीकरण और असाइनमेंट अभिव्यक्ति के बीच कोई अनुक्रम बिंदु नहीं है? अनुक्रम बिंदु भी प्रासंगिक हैं (ऊपर देखें)? या सभी इनिशियलाइजर्स के मूल्यांकन के बाद शून्य इनिशियलाइज़ेशन होता है? यदि हां, तो a[2]
समाप्त होना चाहिए 0
।
क्योंकि सी मानक स्पष्ट रूप से परिभाषित नहीं करता है कि यहां क्या होता है, मेरा मानना है कि व्यवहार अपरिभाषित है (चूक से)।
a[2]=1
मूल्यांकन करता है1
।