जैसा कि पहले था कि बाद में सब कुछ डरावना लगता है, प्रारंभिक भय पर काबू पाने का सबसे अच्छा तरीका है कि आप अपने आप को अज्ञात की असुविधा में डुबो दें ! यह कई बार ऐसा होता है, जिसे हम सबसे अधिक सीखते हैं, आखिरकार।
दुर्भाग्य से, सीमाएं हैं। जब आप अभी भी एक फ़ंक्शन का उपयोग करना सीख रहे हैं, तो आपको उदाहरण के लिए, शिक्षक की भूमिका नहीं माननी चाहिए। मैं अक्सर उन लोगों के उत्तर पढ़ता हूं जो यह नहीं जानते कि कैसे उपयोग करना है realloc
(अर्थात वर्तमान में स्वीकृत उत्तर! ) दूसरों को यह बताते हुए कि इसे गलत तरीके से कैसे उपयोग किया जाए, कभी-कभी इस आड़ में कि वे गलती से निपटने में चूक गए हैं , भले ही यह एक सामान्य नुकसान हो। जिसका उल्लेख होना चाहिए। यहां बताया गया है कि realloc
सही तरीके से उपयोग करने का तरीका बताया गया है । ध्यान दें कि उत्तर त्रुटि जाँच करने के लिए रिटर्न मान को एक भिन्न चर में संग्रहित कर रहा है ।
जब भी आप किसी फ़ंक्शन को कॉल करते हैं, और हर बार जब आप किसी सरणी का उपयोग करते हैं, तो आप एक पॉइंटर का उपयोग कर रहे हैं। रूपांतरण स्पष्ट रूप से हो रहे हैं, जो कि अगर कुछ भी डरावना होना चाहिए, क्योंकि यह ऐसी चीजें हैं जो हम नहीं देखते हैं जो अक्सर सबसे अधिक समस्याएं पैदा करते हैं। उदाहरण के लिए, स्मृति लीक ...
एरियर ऑपरेटर पॉइंटर ऑपरेटर हैं। array[x]
वास्तव में एक शॉर्टकट है *(array + x)
, जिसे नीचे तोड़ा जा सकता है: *
और (array + x)
। यह सबसे अधिक संभावना है कि वही *
है जो आपको भ्रमित करता है। हम आगे संभालने से समस्या से इसके समाप्त कर सकते हैं x
होने के लिए 0
, इस प्रकार, array[0]
हो जाता है *array
क्योंकि जोड़ने 0
मूल्य में परिवर्तन नहीं होगा ...
... और इस प्रकार हम देख सकते हैं कि *array
इसके बराबर है array[0]
। आप एक का उपयोग कर सकते हैं जहां आप दूसरे का उपयोग करना चाहते हैं, और इसके विपरीत। एरियर ऑपरेटर पॉइंटर ऑपरेटर हैं।
malloc
, realloc
और दोस्तों एक पॉइंटर की अवधारणा का आविष्कार न करें जो आप सभी के साथ उपयोग कर रहे हैं; वे इसका उपयोग केवल कुछ अन्य विशेषता को लागू करने के लिए करते हैं, जो भंडारण अवधि का एक अलग रूप है, जब आप आकार में कठोर, गतिशील परिवर्तन चाहते हैं, तो यह सबसे उपयुक्त है ।
यह शर्म की बात है कि वर्तमान में स्वीकार किया गया उत्तर स्टैकऑवरफ्लो पर कुछ अन्य बहुत अच्छी तरह से स्थापित सलाह के अनाज के खिलाफ भी जाता है , और साथ ही, एक छोटी-ज्ञात सुविधा को पेश करने का अवसर याद करता है जो वास्तव में इस usecase के लिए चमकता है: लचीला सरणी सदस्यों! यह वास्तव में एक बहुत ही टूटा हुआ जवाब है ... :(
जब आप अपने को परिभाषित करते हैं struct
, तो संरचना के अंत में अपने सरणी की घोषणा करें , बिना किसी ऊपरी सीमा के। उदाहरण के लिए:
struct int_list {
size_t size;
int value[];
};
यह आपको अपने int
आबंटन में अपनी सरणी को अपने समान करने की अनुमति देगा count
, और उन्हें इस तरह से बाध्य करना बहुत आसान हो सकता है !
sizeof (struct int_list)
हालांकि value
0 के आकार के अनुसार कार्य करेगा , इसलिए यह आपको खाली सूची के साथ संरचना का आकार बताएगा । आपको अभी भी realloc
अपनी सूची का आकार निर्दिष्ट करने के लिए दिए गए आकार में जोड़ना होगा।
एक और आसान टिप यह याद रखना है कि realloc(NULL, x)
यह समकक्ष है malloc(x)
, और हम इसका उपयोग अपने कोड को सरल बनाने के लिए कर सकते हैं। उदाहरण के लिए:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->size = y;
return 0;
}
struct int_list *array = NULL;
struct int_list **
प्रथम तर्क के रूप में उपयोग करने का कारण मैंने तुरंत स्पष्ट नहीं हो सकता है, लेकिन यदि आप दूसरे तर्क के बारे में सोचते हैं, तो value
भीतर से किए गए कोई भी परिवर्तन push_back
उस फ़ंक्शन को दिखाई नहीं देंगे, जिसे हम सही कह रहे हैं? वही पहले तर्क के लिए जाता है, और हमें अपने को संशोधित करने में सक्षम होना चाहिए array
, न केवल यहां बल्कि संभवतः किसी अन्य फ़ंक्शन में भी / हम इसे पास करते हैं ...
array
कुछ भी नहीं की ओर इशारा करते हुए शुरू होता है; यह एक खाली सूची है। इसे शुरू करना इसे जोड़ने के समान है। उदाहरण के लिए:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
पुनश्च जब आप इसके साथ कर रहे हैं याद रखेंfree(array);
!