2012-12-29 4 views
6

निम्नलिखित कोड मेरे सिस्टम में अपेक्षित के रूप में चलता है, लेकिन मुझे यकीन नहीं है कि P परिवर्तनीय की गारंटी है MyArray[0] के बाद एक ही मान के लिए एक ही मूल्य है।डेल्फी: क्या एक अस्थायी पीसीर पीसीआर द्वारा इंगित स्ट्रिंग वेरिएबल के बाद एक ही मूल्य रखने की गारंटी है?

procedure Test; 
var 
    MyArray: array of string; 
    P : PChar; 

begin 
    SetLength(MyArray, 2); 
    MyArray[0] := 'ABCD'; 
    MyArray[1] := '1234'; 

    // Is P guaranteed to have the same value all the time? 
    P := PChar(MyArray[0]); 

    MyArray[0] := MyArray[1]; 
    MyArray[1] := P; 

    WriteLn(MyArray[0]); 
    WriteLn(MyArray[1]); 
end; 

उत्तर

13

आपका कोड तकनीकी रूप से अमान्य है। यह केवल एक कार्यान्वयन विस्तार के कारण ही चलता है जिस पर भरोसा नहीं किया जाना चाहिए।

के कोड की उचित अनुभाग पर एक नज़र डालें:

P := PChar(MyArray[0]); 
MyArray[0] := MyArray[1]; 
MyArray[1] := P; 

पहले हम myArray का पहला वर्ण के लिए पी बिंदु बनाने [0]। फिर हम MyArray [0] को आवंटित करते हैं। इस बिंदु पर स्ट्रिंग बफर के लिए कोई कारण नहीं है कि पी पॉइंट को जिंदा रखा जाए। कोई स्ट्रिंग वैरिएबल इसे संदर्भित नहीं करता है। इसकी संदर्भ संख्या शून्य हो गई है, और इसलिए इसे हटा दिया जाना चाहिए। जो पी के बाद के उपयोग को अमान्य बनाता है।

किस मामले में, आपका कोड क्यों चलता है? क्योंकि आपके द्वारा उपयोग किए जाने वाले तारों को अक्षर कहा जाता है। और इसलिए वे संदर्भ संख्या के बराबर -1 के साथ संग्रहित होते हैं और स्ट्रिंग द्वारा उपयोग किए जाने वाले सामान्य ढेर आवंटन दिनचर्या को बाईपास करते हैं। लेकिन अगर आप उन स्ट्रिंग मानों का उपयोग करना चाहते थे जो अक्षर नहीं थे, तो उपर्युक्त अनुच्छेद में जो वर्णन करता हूं, वह होगा। और मुझे उम्मीद है कि आपका वास्तविक कोड अक्षर का उपयोग नहीं करेगा।

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

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

+2

@ डेविड_हेफरन, वाह, यह एक व्यापक स्पष्टीकरण है। आपका बहुत बहुत धन्यवाद। बीटीडब्ल्यू, मैं अपनी परियोजनाओं में उपरोक्त मेरे कोड उदाहरण का उपयोग नहीं करता हूं। यह सिर्फ एक टेस्ट कोड है जिसे मैंने पीसीहर रहस्य को समझने के लिए बनाया है। :-) – Astaroth

+2

@Astaroth पीसीएचर्स के बारे में अच्छा लेख: http://rvelthuis.de/articles/articles-pchars.html – Torbins

2

ऐसा लगता है कि एक स्ट्रिंग से पीसीहर तक कास्टिंग का पता अपना पता लेने से अलग है। नीचे दिए गए कोड को देखें, यह स्ट्रिंग का पता ले जाएगा।

procedure Test; 
var 
    MyArray: array of string; 
    P : ^String; 

begin 
    SetLength(MyArray, 2); 
    MyArray[0] := 'ABCD'; 
    MyArray[1] := '1234'; 

    // take the pointer 
    P := @MyArray[0]; 

    WriteLn(MyArray[0]); 
    WriteLn(MyArray[1]); 
    WriteLn(P^); 

    // when content of array changes, P^ will change as well 
    MyArray[0] := 'HELLO'; 
    WriteLn(P^); 
end; 
+2

हां, पीसीहर और^स्ट्रिंग पूरी तरह से अलग हैं। –

संबंधित मुद्दे