दिलचस्प पोस्ट
दो जेवीएम के बीच साझा मेमोरी क्यों नहीं बिट-शिफ्ट, "<<", 32-बिट इंटिजर्स 32 से अधिक बार इस्तेमाल करते समय अपेक्षित काम करते हैं? सेलेनियम में दर्ज करें / वापसी कुंजी लिखें क्या यह सरल स्ट्रिंग मान मान्य JSON है? Google खोज परिणामों में वेबसाइट शीर्षक को अलग-अलग प्रदर्शित करता है कम से कम एक चेक करने के लिए एकाधिक चेकबॉक्स के साथ फ़ॉर्म को कैसे मान्य किया जाए आराम सामग्री प्रकार: क्या यह एक्सटेंशन पर आधारित या हेडर स्वीकार करना चाहिए? Jtable के प्रत्येक पंक्ति में जेबटन जोड़ें एंड्रॉइड: स्तंभ '_id' मौजूद नहीं है जावास्क्रिप्ट एसडीके में एफबी.लॉगिन विधि से प्रवेश टोकन कैसे प्राप्त करें क्या इस टपल-सृजन मुहावरे का नाम है? रिकर्सिव फ़ोल्डर को कॉपी करें, कुछ फ़ोल्डर्स को छोड़कर एक्लिप्से में एक एकल यूजिट परीक्षण चला रहा है एक कदम affine एक बिंदु के आसपास रोटेशन के लिए परिणत? पैचिंग / बचत करने पर दिनांक / समय मानों का गलत अर्थ क्यों है?

क्यों ऑरेंज प्रकार ऑब्जेक्ट संशोधनीय नहीं है?

यह यहाँ कहा गया है कि

शब्द बदलने योग्य लार्वेल का उपयोग करने पर जोर देने के लिए प्रयोग किया जाता है कि लालगु नामित ऑब्जेक्ट को और साथ ही जांच की अनुमति देता है। निम्नलिखित ऑब्जेक्ट प्रकार लावलु हैं, लेकिन संशोधनीय गुण नहीं हैं:

  • एक सरणी प्रकार
  • एक अपूर्ण प्रकार
  • एक कॉन्स्ट-योग्य प्रकार
  • एक कंटेंट प्रकार के रूप में योग्यता वाले एक सदस्य के साथ एक संरचना या संघ प्रकार

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

क्यों ऑरेंज प्रकार ऑब्जेक्ट संशोधनीय नहीं है? क्या यह लिखना सही नहीं है?

int i = 5, a[10] = {0}; a[i] = 1; 

?
और भी, एक अपूर्ण प्रकार क्या है?

Solutions Collecting From Web of "क्यों ऑरेंज प्रकार ऑब्जेक्ट संशोधनीय नहीं है?"

घोषित करें

 int a[10]; 

तो निम्न सभी सत्य हैं:

  • अभिव्यक्ति का प्रकार "10 के तत्व-तत्व" है; सिवाय जब a sizeof या अनारी & ऑपरेटरों का संचालन है, तो अभिव्यक्ति को "पॉइंटर टू int " प्रकार की अभिव्यक्ति में कनवर्ट किया जाएगा और इसका मान सरणी में पहला तत्व का पता होगा;
  • अभिव्यक्ति के प्रकार a[i] int ; यह पूर्णांक ऑब्जेक्ट को संदर्भित करता है जिसे i सरणी के तत्व के रूप में संग्रहीत करता i ;
  • अभिव्यक्ति a एक असाइनमेंट का लक्ष्य नहीं हो सकता है क्योंकि सी अन्य वेरिएबल जैसे सरणियों का इलाज नहीं करता है, इसलिए आप ऐसा कुछ नहीं लिख सकते हैं जैसे a = b या a = malloc(n * sizeof *a) या ऐसा कुछ भी

आप देखेंगे कि मैं शब्द "अभिव्यक्ति" पर बल देना जारी रखता हूं स्मृति का हिस्सा जिसे हमने 10 पूर्णांक धारण करने के लिए अलग रखा है और हम स्मृति के उस हिस्से को संदर्भित करने के लिए प्रतीक (अभिव्यक्ति) के बीच अंतर है हम इसे अभिव्यक्ति के साथ संदर्भित कर सकते हैं a । हम उस सरणी के लिए एक सूचक भी बना सकते हैं:

 int (*ptr)[10] = &a; 

अभिव्यक्ति *ptr में "10-तत्व एरे का भी प्रकार" होता है, और यह उस मेमोरी का a ही भाग को संदर्भित करता है जिसे a संदर्भ देता है।

सी सरणी अभिव्यक्ति ( a , *ptr ) को अन्य प्रकार के अभिव्यक्तियों की तरह व्यवहार नहीं करता है, और अंतर में से एक यह है कि एरे प्रकार की अभिव्यक्ति किसी असाइनमेंट का लक्ष्य नहीं हो सकती है। आप एक अलग सरणी ऑब्जेक्ट को संदर्भित करने के लिए पुन: निर्दिष्ट नहीं कर सकते (अभिव्यक्ति *ptr )। आप a[i] या (*ptr)[i] (प्रत्येक सरणी तत्व का मान बदल सकते हैं) के लिए एक नया मान असाइन कर सकते हैं, और आप एक अलग सरणी को इंगित करने के लिए ptr असाइन कर सकते हैं:

 int b[10], c[10]; ..... ptr = &b; ..... ptr = &c; 

दूसरे प्रश्न के लिए …

एक अधूरा प्रकार का आकार जानकारी नहीं है; घोषणाओं की तरह

 struct foo; int bar[]; union bletch; 

सभी अधूरे प्रकार बनाते हैं क्योंकि कम्पाइलर के लिए उस प्रकार के ऑब्जेक्ट के लिए कितना भंडारण सेट करना निर्धारित करने के लिए पर्याप्त जानकारी नहीं है आप अपूर्ण प्रकार की वस्तुओं को नहीं बना सकते हैं; उदाहरण के लिए, आप घोषित नहीं कर सकते

 struct foo myFoo; 

जब तक आप struct foo लिए परिभाषा को पूरा नहीं करते हालांकि, आप अपूर्ण प्रकारों को संकेत बना सकते हैं; उदाहरण के लिए, आप घोषित कर सकते हैं

 struct foo *myFooPtr; 

struct foo लिए परिभाषा को पूरा किए बिना, क्योंकि एक सूचक सिर्फ ऑब्जेक्ट के पते को संग्रहीत करता है, और उस प्रकार के आकार का पता करने की आवश्यकता नहीं है इससे स्व-संदर्भित प्रकारों को परिभाषित करना संभव होता है

 struct node { T key; // for any type T Q val; // for any type Q struct node *left; struct node *right; }; 

struct node की प्रकार परिभाषा पूरी नहीं है जब तक हम उस समापन को नहीं मारते } । चूंकि हम एक अपूर्ण प्रकार को संकेतक घोषित कर सकते हैं, हम ठीक हैं। हालांकि, हम इस रूप में संरचना को परिभाषित नहीं कर सके

 struct node { ... // same as above struct node left; struct node right; }; 

क्योंकि जब हम left और right सदस्यों को घोषित करते हैं तो पूरी तरह से नहीं होता है, और यह भी क्योंकि प्रत्येक left और right सदस्य प्रत्येक अपने स्वयं के left और right सदस्य होते हैं, जिनमें से प्रत्येक में अपने स्वयं के left और right सदस्य होते हैं, और और पर और पर।

यह structs और यूनियनों के लिए बहुत अच्छा है, लेकिन इसके बारे में क्या

 int bar[]; 

???

हमने प्रतीक bar घोषित किया है और संकेत दिया है कि यह एक सरणी प्रकार होगा, लेकिन आकार इस बिंदु पर अज्ञात है। आखिरकार हमें इसे आकार के साथ परिभाषित करना होगा, लेकिन इस तरह का प्रतीक उन संदर्भों में उपयोग किया जा सकता है जहां सरणी आकार सार्थक या आवश्यक नहीं है इस बात को स्पष्ट करने के लिए मेरे सिर के शीर्ष पर एक अच्छा, गैर-अनुवाचित उदाहरण नहीं है, हालांकि,

संपादित करें

यहां टिप्पणी के जवाब में, चूंकि मैं जो लिखना चाहता हूं, उसके लिए टिप्पणी अनुभाग में कमरे में नहीं जा रहा है (मैं इस शाम को एक वर्बोज़ मूड में हूं)। तुम ने पूछा था:

इसका मतलब यह है कि हर चर अभिव्यक्ति है?

इसका मतलब है कि किसी भी चर एक अभिव्यक्ति, या एक अभिव्यक्ति का हिस्सा हो सकता है। यहां बताया गया है कि कैसे भाषा मानक शब्द अभिव्यक्ति को परिभाषित करता है:

6.5 भाव
1 एक अभिव्यक्ति ऑपरेटरों और ऑपेरेक्स का एक अनुक्रम है जो मान की गणना को निर्दिष्ट करता है, या वह ऑब्जेक्ट या फंक्शन को निर्दिष्ट करता है, या जो साइड इफेक्ट उत्पन्न करता है, या जो उसके संयोजन का प्रदर्शन करता है

उदाहरण के लिए, वेरिएबल स्वयं एक अभिव्यक्ति के रूप में गिना जाता है; यह सरणी ऑब्जेक्ट को परिभाषित करता है जिसे हम 10 पूर्णांक मान रखने के लिए निर्धारित करते हैं। यह सरणी के पहले तत्व के पते का भी मूल्यांकन करता है। चर a भी एक बड़ी अभिव्यक्ति का हिस्सा हो सकता है जैसे a[i] ; ऑपरेटर सबस्क्रिप्ट ऑपरेटर है [] और ऑपरेंड वेरिएबल्स a और i । यह अभिव्यक्ति सरणी के एक सदस्य को निर्दिष्ट करती है, और वह उस सदस्य में सही ढंग से संग्रहीत मान का मूल्यांकन करती है। बदले में यह अभिव्यक्ति एक बड़ी अभिव्यक्ति का एक हिस्सा हो सकती है जैसे a[i] = 0

और मुझे यह भी स्पष्ट करते हैं कि, घोषणापत्र int [10] में, [एआरए] प्रकार का एक प्रकार है

हाँ बिल्कुल।

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

 x = y; 

अभिव्यक्ति y का प्रकार int , इसलिए y की घोषणा लिखी गई है

 int y; 

अगर, दूसरी तरफ, आपके पास int की एक सरणी होती है, और आप किसी विशिष्ट एलीमेंट तक पहुंचना चाहते हैं, तो आप उस नाम को एक्सेस करने के लिए एसेरे नाम और एक इंडेक्स का इस्तेमाल करेंगे, जैसे कि उस मूल्य को एक्सेस करने के लिए, जैसे

 x = a[i]; 

अभिव्यक्ति का प्रकार a[i] int , इसलिए सरणी की घोषणा के रूप में लिखा है

 int arr[N]; // for some value N. 

arr का "इंटैनेस" प्रकार विनिर्देशक int द्वारा दिया जाता है; arr का "सरणी-निष्ठा" arr arr[N] द्वारा दिया गया है। घोषणापत्र हमें " arr " ("एक एन-तत्व एरे" है) द्वारा दिए गए कुछ अतिरिक्त प्रकार की जानकारी के साथ घोषित घोषित वस्तु का नाम देता है। घोषणा "पढ़ता है" के रूप में

  a -- a a[N] -- is an N-element array int a[N]; -- of int 

2 संपादित करें

और आखिरकार, मैंने अभी भी आपको असली कारण नहीं बताया है कि क्यों सरणी अभिव्यक्तियां गैर-संशोधित गुण हैं। तो यहाँ एक जवाब की इस पुस्तक का एक और अध्याय है।

सी पूरी तरह से डेनिस रिची के दिमाग से वसंत नहीं हुआ; यह बी के रूप में जाना जाने वाला एक पहले की भाषा से ली गई थी (जो बीसीपीएल से निकला था)। 1 बी एक "विशिष्ट" भाषा थी; इसके पास पूर्णांक, फ्लोट, टेक्स्ट, रिकॉर्ड, आदि के लिए अलग-अलग प्रकार नहीं थे। इसके बजाय, सब कुछ केवल एक निश्चित लंबाई शब्द या "सेल" था (अनिवार्य रूप से एक अहस्ताक्षरित पूर्णांक)। मेमोरी कोशिकाओं के एक रैखिक सरणी के रूप में इलाज किया गया था। जब आप बी में एक सरणी आवंटित करते हैं, जैसे कि

 auto V[10]; 

कंपाइलर 11 कोशिकाओं आवंटित; सरणी के लिए 10 निकटवर्ती कोशिकाएं, साथ ही एक सेल जो पहले सेल के स्थान को वी से जुड़ा था:

  +----+ V: | | -----+ +----+ | ... | +----+ | | | <----+ +----+ | | +----+ | | +----+ | | +----+ ... 

जब रिची सी के लिए struct प्रकार जोड़ रहा था, तो उन्होंने महसूस किया कि इस व्यवस्था के कारण उन्हें कुछ समस्याएं पैदा हो रही थीं। उदाहरण के लिए, वह किसी फ़ाइल या निर्देशिका तालिका में प्रविष्टि का प्रतिनिधित्व करने के लिए एक स्ट्रक्चर प्रकार बनाना चाहता था:

 struct { int inumber; char name[14]; }; 

वह संरचना को सिर्फ एक सार तरीके से प्रवेश का वर्णन नहीं करना चाहता था, बल्कि वास्तविक फ़ाइल तालिका प्रविष्टि में बिट्स का प्रतिनिधित्व करने के लिए भी था, जिसमें सरणी में पहले तत्व के स्थान को संग्रहित करने के लिए एक अतिरिक्त सेल या शब्द नहीं था। तो उसने इसे से छुटकारा दिलाया – पहले तत्व के पते को स्टोर करने के लिए एक अलग स्थान को अलग करने के बजाय, उन्होंने सी लिखा था कि पहले तत्व का पता गणना किया जाएगा, जब सरणी अभिव्यक्ति का मूल्यांकन किया जाएगा।

यही कारण है कि आप कुछ ऐसा नहीं कर सकते

 int a[N], b[N]; a = b; 

क्योंकि उस संदर्भ में सूचक मूल्यों के लिए a और b दोनों का मूल्यांकन किया जाता है; यह 3 = 4 लिखने के बराबर है स्मृति में कुछ भी नहीं है जो वास्तव में सरणी में पहले तत्व का पता संग्रहीत करता है; कंपाइलर केवल अनुवाद चरण के दौरान इसे गणना करता है।


1. यह सब कागज से लिया जाता है सी भाषा का विकास

शब्द "सरणी प्रकार का लावलु" शब्दशः सरणी वस्तु को सरणी प्रकार के एक लावलू के रूप में संदर्भित करता है, अर्थात संपूर्ण वस्तु के रूप में सरणी वस्तु। इस लार्वेल को पूरी तरह से बदलने योग्य नहीं है, क्योंकि इसमें कोई कानूनी कार्यवाही नहीं है जो इसे पूरी तरह से संशोधित कर सकती है। वास्तव में, केवल आपरेशन जो आप सरणी प्रकार के एक लावलू पर कर सकते हैं: एकरूप & (का पता), sizeof और सूचक प्रकार के लिए अंतर्निहित रूपांतरण। इनमें से कोई भी ऑपरेशन सरणी को संशोधित नहीं करता है, यही वजह है कि सरणी ऑब्जेक्ट्स संशोधनीय नहीं हैं।

a[i] सरणी प्रकार के लावल्यू के साथ काम नहीं करता। a[i] एक int ऑब्जेक्ट को निर्दिष्ट करता है: सरणी का i- थ तत्व A इस अभिव्यक्ति की अभिव्यक्ति (यदि स्पष्ट रूप से वर्णित है): *((int *) a + i) पहला कदम – (int *) a – पहले से ही सरणी प्रकार के लार्वल को प्रकार int * एक rvalue में कनवर्ट करता है। इस बिंदु पर सरणी प्रकार का लावल्यू अच्छा के लिए तस्वीर से बाहर है।

अपूर्ण प्रकार एक प्रकार है जिसका आकार [अभी तक] ज्ञात नहीं है उदाहरण के लिए: एक स्ट्रक्चर प्रकार जिसे घोषित किया गया है लेकिन परिभाषित नहीं, अनिर्दिष्ट आकार के साथ एक सरणी प्रकार, void प्रकार

एक अपूर्ण प्रकार एक प्रकार है जिसे घोषित किया गया है लेकिन परिभाषित नहीं है, उदाहरण के लिए, struct Foo;

आप हमेशा अलग-अलग सरणी तत्वों को असाइन कर सकते हैं (संभालने वे const नहीं हैं)। लेकिन आप कुछ को पूरी सरणी में निर्दिष्ट नहीं कर सकते

सी और सी ++ बहुत कुछ भ्रामक हैं जैसे कि int a[10] = {0, 1, 2, 3}; एक असाइनमेंट नहीं है, लेकिन एक प्रारंभिकता हालांकि यह असाइनमेंट की तरह बहुत ज्यादा दिखती है।

यह ठीक है (प्रारंभिकरण):

 int a[10] = {0, 1, 2, 3}; 

यह सी / सी ++ में काम नहीं करता है:

 int a[10]; a = {0, 1, 2, 3}; 

मानते हुए a ints की एक सरणी है, a[10] एक सरणी नहीं है। यह एक int

a = {0} अवैध होगा

याद रखें कि किसी सरणी का मान वास्तव में उसके पहले तत्व का पता (सूचक) है इस पते को संशोधित नहीं किया जा सकता। इसलिए

 int a[10], b[10]; a = b 

अवैध है

a[1] = 3 में सरणी की सामग्री को संशोधित करने के साथ इसमें कुछ भी नहीं है