2009-04-03 9 views
9

मैं पहले से ही संदर्भ द्वारा पारित करने और इतनेडेल्फी में संदर्भ के द्वारा आप एक सरणी कैसे पास करते हैं?

procedure test(var x:integer); 
begin 
    x:=x+5; 
end; 

तो उपरोक्त कोड अपडेट 5 संदर्भ द्वारा के बारे में पढ़ा है। मुझे लगता है कि अगर मैं संदर्भ द्वारा एक सरणी अद्यतन कर रहा था तो मैं var X: blah की सरणी घोषित कर सकता था ... कुछ बाध्य बग्स और बस जानना चाहता था कि मुझे डेटा के लिए पॉइंटर के लिए डेटा के प्रकार का उपयोग करना चाहिए या नहीं सूचक हमेशा int है ... बस मुझे पता है कि अगर मैं संदर्भ में अपना गुजर रहा हूं या मेरे कोड में कुछ और है जो मुद्दा है।

उत्तर

19

यदि आप एक गैर-var पैरामीटर के रूप में गतिशील सरणी पास करते हैं, तो संकलक एक प्रतिलिपि बना देगा।

नीचे दिया गया छोटा कोड नमूना दर्शाता है कि फॉर्म कैप्शन में 37/42 प्रदर्शित करके।

procedure IncArray1(data: array of integer); 
var i : integer; 
begin 
    for i := Low(data) to High(data) do 
    data[i] := data[i] + 5; 
end; 

procedure IncArray2(var data: array of integer); 
var i : integer; 
begin 
    for i := Low(data) to High(data) do 
    data[i] := data[i] + 5; 
end; 

procedure TForm8.FormCreate(Sender: TObject); 
var 
    data: array of integer; 
begin 
    SetLength(data, 1); 
    data[0] := 37; 
    IncArray1(data); 
    Caption := IntToStr(data[0]); 
    IncArray2(data); 
    Caption := Caption + '/' + IntToStr(data[0]); 
end; 

अगर हम उत्पन्न कोडांतरक कोड पर गौर, IncArray1

004552B4 8BCA    mov ecx,edx 
004552B6 85C9    test ecx,ecx 
004552B8 7807    js $004552c1 
004552BA 8B1C88   mov ebx,[eax+ecx*4] 
004552BD 49    dec ecx 
004552BE 53    push ebx 
004552BF 79F9    jns $004552ba 
004552C1 8BC4    mov eax,esp 

साथ इस कोड को प्रतियां स्रोत सरणी ढेर करने के लिए शुरू होता है और (= पते में संग्रहीत पहला तत्व का पता करने के लिए eax सेट अंतिम धक्का के बाद स्टैक सूचक)। ढेर नीचे बढ़ता है इसलिए कोड अंतिम तत्व के साथ शुरू होता है (edx में उच्च (डेटा) होता है जब IncArray1 कहा जाता है) और दोहराया जाता है (तत्व पढ़ें; पुश तत्व; कमी सूचकांक) जब तक यह तत्व 0 तक नहीं पहुंच जाता है।

IncArray2 में कोई नहीं है ऐसा कोड IncArray2 और IncArray2 को कॉल करने से पहले कॉलर डेटा के पते को ईएक्स रजिस्टर में संग्रहीत करता है, बस इस पते का उपयोग करता है।

यदि आप किसी भी कारण से 'var' का उपयोग नहीं करना चाहते हैं, तो आप डेटा के पते को अपनी विधि में पास कर सकते हैं। लेकिन जैसा कि आप पैरामीटर घोषणा में वाक्यविन्यास 'डेटा:^पूर्णांक का सरणी' का उपयोग नहीं कर सकते हैं, आपको अपने डेटा के लिए एक प्रकार घोषित करना होगा। और आपको विधि में हर जगह 'डेटा' के बजाय 'डेटा ^' का उपयोग करना होगा।

type 
    TData = array of integer; 
    PData = ^TData; 

procedure IncArray(data: PData); 
var i : integer; 
begin 
    for i := Low(data^) to High(data^) do 
    data^[i] := data^[i] + 5; 
end; 

procedure TForm8.FormCreate(Sender: TObject); 
var 
    data: TData; 
begin 
    SetLength(data, 2); 
    data[0] := 37; 
    IncArray(@data); 
    Caption := IntToStr(data[0]); 
end; 

डेल्फी 2007

+0

ठीक है तो ऐसा करने का कोई तरीका है, मेरे पास एक बड़ी सरणी है जिसे मैं संदर्भ के माध्यम से काम करना चाहता हूं। सरणी की प्रतिलिपि महंगी comptationaly दूर है। – Arthur

+0

हां, बस उपरोक्त कोड में IncArray2 करता है - उपयोगकर्ता 'var' उपसर्ग। – gabr

+0

@gabr, क्या आप जांच सकते हैं कि जब आप म्यूटेट नहीं करते हैं तो गतिशील सरणी की प्रतिलिपि बनाई जाती है या नहीं?मुझे पता है कि तार कॉपी-ऑन-राइट हैं। –

6

साथ परीक्षण किया गया Gabr के जवाब सही है, लेकिन प्रमुख मुद्दा काफी गहरी है कि मैं यह एक अलग पोस्ट के रूप में बाहर लाता हूँ दफन है:

पहले अपने प्रकार परिभाषित करें! इस विशिष्ट मामले में कंपाइलर ने वहां पूर्णांक की एक सरणी स्वीकार की, लेकिन ऐसा इसलिए है क्योंकि इसका विशेष अर्थ है और यह जो आपने अपेक्षित था। प्रक्रिया की परिभाषा में एक प्रकार को परिभाषित करने का कोई अन्य प्रयास बस असफल रहा होगा।

सी के विपरीत, आप दो चीजों असाइनमेंट संगत आप उन्हें वही प्रकार, केवल दो नहीं प्रकार है कि एक ही निर्माण कर रहे हैं होने के रूप में घोषित करने के लिए है होना चाहते हैं:

Var 
    A : Array [1..4] of Integer; 
    B : Array [1..4] of Integer; 

Begin 
    A := B; 

संकलन नहीं होगा । इसके बजाय:

Type 
    Array4 = array [1..4] of Integer; 

Var 
    A : Array4; 
    B : Array4; 

Begin 
    A := B; 

और संकलक जो आप उम्मीद करेंगे वह करता है।

+0

गैबर के पोस्ट के बाद कोड बदलने के लिए भागने के बाद अब मेरे पास सही मुद्दा है जो आप कह रहे हैं, यह ढेर नहीं आएगा, यह कहता है कि औपचारिक प्रकार अहेव समान हैं .. मेरे लिए ए और बी विभिन्न इकाइयों में हैं .. मैं क्या कर सकता हूँ? – Arthur

+0

मान लीजिए कि यूनिट ए "यूनिट" का उपयोग करता है। साझा बी को यूनिट बी में घोषित करें, और दोनों उस परिभाषा को "देख" सकते हैं। – Argalatyr

+2

यदि आप गैबर कोड चलाते हैं लेकिन सभी "पूर्णांक की सरणी" के साथ TIntArray (जहां TIntArray = पूर्णांक की सरणी) द्वारा प्रतिस्थापित किया जाता है, तो सरणी हमेशा संदर्भ द्वारा पारित होती है, और डेटा [0] 37 + 5 + 5 = 49 है। क्या वह अजीब नहीं है? –

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