सी में संरचना और सूचक के लिए मॉलोक


84

मान लीजिए कि मैं वेक्टर की लंबाई और उसके मूल्यों का प्रतिनिधित्व करने वाली संरचना को परिभाषित करना चाहता हूं:

अब, मान लीजिए कि मैं एक वेक्टर y को परिभाषित करना चाहता हूं और इसके लिए मेमोरी आवंटित करना चाहता हूं।

इंटरनेट पर मेरी खोज बताती है कि मुझे एक्स के लिए मेमोरी अलग से आवंटित करनी चाहिए।

लेकिन, ऐसा लगता है कि मैं दो बार y-> x के लिए मेमोरी आवंटित कर रहा हूं, एक y के लिए मेमोरी आवंटित करते समय और दूसरा y-> x के लिए मेमोरी आवंटित करते समय, और यह मेमोरी की बर्बादी लगती है। यह बहुत सराहा जाता है अगर मुझे पता चल जाए कि कंपाइलर वास्तव में क्या करता है और दोनों y, और y-> x को इनिशियलाइज़ करने का सही तरीका क्या होगा।

अग्रिम में धन्यवाद।


5
जैसा कि paxdiablo द्वारा प्रमुखता से बताया गया है, कृपया malloc()सी में रिटर्न वैल्यू मत डालें । मैं कभी नहीं समझ पाऊंगा कि सभी को ऐसा करने की आवश्यकता क्यों महसूस होती है। :(
खोलना

14
@unwind, शायद वे पुराने C ++ प्रोग्रामर अपग्रेड कर रहे हैं C :-)
paxdiablo

@unwind जब C कोड पर Nvidia के nvcc कंपाइलर का उपयोग किया जाता है, अगर मैं Malloc का परिणाम नहीं डालती हूं, तो यह एक त्रुटि फेंकता है।
नुबेक

@Nubcake इस लिंक के अनुसार हो सकता है क्योंकि nvcc C ++ मोड में अंतर्निहित कंपाइलर को चलाता है, क्योंकि उनका CUDA इंटरफ़ेस C ++ है। सी में, आपको इसके लिए त्रुटियां नहीं मिलेंगी। C ++ में void *स्वचालित रूप से अन्य बिंदुओं में परिवर्तित नहीं होता है, और कलाकारों की जरूरत है (या, बस malloc()C ++ में उपयोग नहीं करते हैं , निश्चित रूप से)।
खोलना

@ यूंविंद हां, मैंने बाद में इस बारे में पाया :) बस एक ऐसी स्थिति बताना चाहता था जहां अगर आपने परिणाम नहीं डाला तो यह एक त्रुटि होगी।
मुबारक

जवाबों:


156

नहीं, आप दो बार मेमोरी आवंटित नहीं कर रहे हैं y->x

इसके बजाय, आप संरचना के लिए मेमोरी आवंटित कर रहे हैं (जिसमें एक पॉइंटर भी शामिल है) और उस पॉइंटर को इंगित करने के लिए कुछ और।

इस पर इस तरीके से विचार करें:

तो आपको वास्तव में सब कुछ स्टोर करने के लिए दो आवंटन ( 1और 2) की आवश्यकता है।

इसके अतिरिक्त, आपका प्रकार struct Vector *yएक पॉइंटर होने के बाद से होना चाहिए , और आपको mallocसी से रिटर्न वैल्यू कभी नहीं डालना चाहिए क्योंकि यह कुछ ऐसी समस्याओं को छिपा सकता है जो आप छिपाना नहीं चाहते हैं - सी void*किसी भी अन्य पॉइंटर को रिटर्न मान को अंतर्निहित करने में पूरी तरह से सक्षम है ।

और, ज़ाहिर है, आप शायद इन वैक्टरों के निर्माण को इनका प्रबंधन आसान बनाना चाहते हैं, जैसे कि:

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


28
मेरे ASCII कला कौशल पर गुस्सा: :-)
paxdiablo

बहुत बहुत धन्यवाद। वास्तव में सहायक है।
पूय

1
अगर ((= = NULL) में, रिटवल को रिटवल होना चाहिए
Legion Daeth

5

पहली बार, आप के लिए स्मृति को आबंटित Vectorजो चर का मतलब है, x, n

हालांकि x अभी तक कुछ भी उपयोगी के लिए इंगित नहीं करता है

इसलिए दूसरे आवंटन की भी जरूरत है


3

कुछ बिंदु

struct Vector y = (struct Vector*)malloc(sizeof(struct Vector)); गलत है

यह तब से होना चाहिए struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));जब तक yपॉइंटर रखा जाता है struct Vector

1 malloc()केवल वेक्टर संरचना को धारण करने के लिए पर्याप्त मेमोरी आवंटित करता है (जो कि डबल + इंट का सूचक है)

2 malloc()वास्तव में 10 डबल रखने के लिए मेमोरी आवंटित करते हैं।


2

आप वास्तव में एक ही मॉलॉक में वेक्टर और एक ही समय में सरणी के लिए आवंटित करके ऐसा कर सकते हैं। जैसे:

यह वेक्टर 'y' को आवंटित करता है, फिर वेक्टर संरचना (लेकिन उसी मेमोरी में) के तुरंत बाद अतिरिक्त आवंटित डेटा को y-> x बिंदु बनाता है।

यदि वेक्टर का आकार बदलना आवश्यक है, तो आपको इसे अनुशंसित दो आवंटन के साथ करना चाहिए। आंतरिक y-> x सरणी तब वेक्टर संरचना 'y' को अक्षुण्ण रखते हुए आकार बदलने में सक्षम होगी।


आपने विशेष रूप से चार वाई के लिए क्यों टाइप किया? क्यों नहीं (डबल *) y + आकार (स्ट्रक्चर वेक्टर)?
विष्णु प्रसाद

sizeof बाइट्स में संरचना का आकार देता है, और सूचक अंकगणितीय '+' ऑपरेटर 'y' सूचक को जोड़ देगा जो आकार ( y) का गुणक है यदि हमने जैसा कि आपने ऊपर किया था, y को sizeof (दोगुना) * sizeof (संरचना) से बढ़ाया जाएगा, जो बहुत अधिक है। कास्टिंग y से char हमें आकार (char) * sizeof (संरचना) = 1 * sizeof (संरचना) द्वारा वेतन वृद्धि y देता है
PQuinn

2

सिद्धांत रूप में आप इसे पहले से ही सही कर रहे हैं। आप जो चाहते हैं उसके लिए आपको दो malloc()एस की जरूरत है ।

बस कुछ टिप्पणियाँ:

होना चाहिए

पहली पंक्ति में, आप एक वेक्टर ऑब्जेक्ट के लिए मेमोरी आवंटित करते हैं। malloc()आवंटित मेमोरी में एक पॉइंटर लौटाता है, इसलिए y एक वेक्टर पॉइंटर होना चाहिए। दूसरी पंक्ति में आप 10 डबल्स की एक सरणी के लिए मेमोरी आवंटित करते हैं।

C में आपको स्पष्ट कास्ट की आवश्यकता नहीं है, और sizeof *yइसके बजाय sizeof(struct Vector)टाइप सुरक्षा के लिए बेहतर है, और इसके अलावा, यह टाइपिंग पर बचाता है।

आप अपनी संरचना को फिर से व्यवस्थित कर सकते हैं और ऐसा ही कर सकते हैं malloc():


"टाइपिंग पर बचत" प्रोग्रामिंग निर्णयों के लिए एक वैध तर्क नहीं है। वास्तविक कारण जो आप लेते हैं * y सुरक्षा कारणों से होता है, यह सुनिश्चित करता है कि आप संबंधित चर के लिए जितनी जगह की आवश्यकता है उतना ही आवंटित करें।
लुंडिन

@ लुंडिन मैंने अपना उत्तर अपडेट कर दिया है, लेकिन मुझे "टाइप सेफ्टी" तर्क लगभग लिखने के रूप में एक ही लीग में हैif(NULL == foo)
वेर्न्से

आप का उपयोग करने के लिए एक प्रचार कर रहे हैं sizeof *y। यदि आप इसे केवल 5 अक्षरों को टाइप करने के लिए करते हैं (sizeof * y बनाम sizeof (वेक्टर)) जिसमें कोई अन्य तर्क नहीं है, तो यह होना चाहिए क्योंकि आपको अपने कीबोर्ड पर 5 अक्षर टाइप करने का काम एक बड़ी बाधा लगता है। और यदि ऐसा है, तो शायद करियर की एक और पसंद पर विचार करें, क्योंकि प्रोग्रामिंग में कीबोर्ड की पूरी एक बहुत कुछ शामिल है ...
लंडिन

@ लुंडिन राइटिंग sizeof *yआपको लिखने के sizeof(Vector)दौरान त्रुटियों से लड़ने में मदद करता है sizeof(Matrix)। आप कितनी बार उन लोगों की तरह गलतियाँ करते हैं? जब आप करते हैं तो आप उन्हें कितनी जल्दी ढूंढते और ठीक करते हैं? मैं मानता हूं कि यह टाइप सेफ्टी बढ़ाता है, और मैं sizeof *yअपने कोड में लिखता हूं, लेकिन यह टाइपो को रोकने के लिए लिखने के रूप में लगभग पागल if(NULL == foo)है ==
वर्ना 12

1
@ शमूएलकामेंस्की वे कार्यात्मक रूप से समकक्ष हैं। yहै करने के लिए एक सूचक struct Vectorतो sizeof *y"क्या y अंक के आकार" कह रहा है, इसलिए sizeof struct Vector
वर्नसी

1

जब आप अपने लिए मेमोरी आवंटित करते हैं struct Vectorतो बस पॉइंटर के लिए मेमोरी आवंटित करते हैं x, यानी स्पेस के लिए, जहां उसका मूल्य, जिसमें एड्रेस होता है, रखा जाएगा। तो इस तरह से आप ब्लॉक के लिए मेमोरी आवंटित नहीं करते हैं, जिस पर y.xसंदर्भ होगा।


1

पहला मालॉक संरचना के लिए मेमोरी आवंटित करता है, जिसमें x (पॉइंटर टू डबल) के लिए मेमोरी शामिल है। दूसरा मॉलोक डबल वैल्ट के लिए मेमोरी आवंटित करता है जो कि x पॉइंट टू है।


0

जब आप malloc(sizeof(struct_name))स्वचालित रूप से संरचना के पूर्ण आकार के लिए मेमोरी आवंटित करते हैं, तो आपको प्रत्येक तत्व को अंदर करने की आवश्यकता नहीं है।

का प्रयोग करें -fsanitize=addressजाँच करने के लिए कि कैसे आप अपने कार्यक्रम स्मृति का उपयोग किया झंडा।


गलत। x सिर्फ एक सूचक है, आपको x बिंदुओं के मान के लिए मेमोरी आवंटित करनी होगी। अधिक विवरण प्राप्त करने के लिए अन्य उत्तर पढ़ें। (उदा: stackoverflow.com/a/14768280/5441253 )
मैक्सिमे आशूरोव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.