سؤال

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

Begin
    A := B;

لن تعمل كما قال لورين بيتشتيل هناالمشكلة هي A و B بالنسبة لي في وحدات مختلفة. لذلك، هل هناك طريقة لتحديد تعريف النوع من واحدة موجودة في فصل آخر؟

هل كانت مفيدة؟

المحلول

تحديد النوع في كتلة واجهة من بعض الوحدات ثم قم بتضمين تلك الوحدة عبر uses جملة في وحدات أخرى حيث تحتاج إلى هذا النوع.

unit A;
interface
type
  TMyArray = array [1..4] of Integer;

...

عندما تحتاج إلى استخدام TMyArray في وحدة أخرى:

unit B;
interface
uses A;

...
var x : TMyArray;

نصائح أخرى

بدلا من ذلك، حدد نوعك في قسم الواجهة من الوحدة C واستخدام هذه الوحدة في كل من A و B.

أنواع الصفيف في دلفي غريبة بعض الشيء. هو - هي تبدو مثل A و B من نفس النوع بالضبط، ولكن دلفي لا يعتبر أنهم هم نفس الشيء. تظهر "صفيف [1..4] من عدد صحيح" مرتين، لذلك يعتقد دلفي أن هناك نوعان مختلفان. هذا مجرد غريبة في دلفي. معظم اللغات الأخرى، وأعتقد، لن يهتم. انها ليست مشكلة في الممارسة؛ انها مجرد غريبة بعض الشيء. ربما هناك سبب وجيه لذلك. من تعرف. الحل، كما قال الآخرون، هو تحديد نوعك الخاص، والذي يمكنك وضعه في وحدة يمكن استخدامها من قبل وحدات أخرى. أنا فقط أذكر هذه المشكلة لأنواع الصفيف لأنها قد تكون مربكة لك.

نهج آخر، مدرسة قديمة بعض الشيء ولكن لا تزال تعمل، هي استخدام الكلمة الرئيسية المطلقة لفرض ذاكرة واحدة لتتراكم آخر، وجعل النوع الآخر متوافق. على سبيل المثال، في الوحدة، دعنا نقول أن لديك ما يلي:

TYPE
  TArrayA = Array[1..4] of integer;

ثم في الوحدة ب، لديك ما يلي:

TYPE
  TArrayB = Array[1..4] of integer;  

للتوافق، يمكنك القيام بما يلي:

VAR
  InstanceA : TArrayA;
  InstanceB : TArrayB;
  InstanceBasA : TArrayA ABSOLUTE InstanceB;

ما يفعله هذا هو إنشاء "InstanceBasa" متغير من النوع Arraya الذي يتراكم في نفس مساحة الذاكرة مثل المتغير "InstanceB". يتيح لك ذلك القيام بالأمر التالي:

InstanceA := InstanceBasA;

طريقة أخرى لنقل البيانات من Variablea إلى VariableD هي استخدام الأمر "نقل". على سبيل المثال، للانتقال من Arraya إلى Arrayb، يمكنك القيام بما يلي:

var
  ArrayA : array[1..4] of Integer;
  ArrayB : Array[1..4] of Integer;
begin
  FillChar(ArrayB[1],SizeOf(ArrayB),#0);
  ArrayA[1] := 1234;
  ArrayA[2] := 3456;
  ArrayA[3] := 7890;
  ArrayA[4] := 9876;

  // This is where the move from ArrayA to ArrayB happens.
  Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );

  Assert( ArrayA[4] = ArrayB[4], 'ArrayA[4] <> ArrayB[4]');
end;

يعمل هذا بحقيقة أن الصفيف يتم وضعها في أزياء خطية، لذلك نسخك البايتات التي تبدأ في وضع الصفيف الأول، لطول الصفيف.

يمكنك إجبار التحويل البرمجي على افتراض أنها من نفس النوع من خلال TypeCasting لهم:

type
  TIntArray = array[1..4] of integer;

begin
  Assert(SizeOf(ArrayA) = SizeOf(TIntArray));
  Assert(SizeOf(ArrayB) = SizeOf(TIntArray));
  TIntArray(ArrayA) := TIntArray(ArrayB);

ولكن يجب عليك التأكد من أن كلاهما في الواقع هو صفيف [1..4] وإلا فسوف تقوم بالكتابة فوق بعض الذاكرة. لهذا السبب أضفت التأكيدين.

مجرد استخدام يونيتا في unitb بعد inteface. وقبل تطبيق ...!!!!

أبدا، لا تستخدم أبدا رمز مثل هذا:

// This is where the move from ArrayA to ArrayB happens.
Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );

أين هو الخلل؟ أنت تستخدم حجم المصدر للحصول على عدد البايتات للتحرك، وليس حجم الوجهة !!! إذا Majsof (a)> Sizeof (B) لديك تجاوز سعة مخزن مؤقت وأنت تقوم بالكتابة فوق الذاكرة. إذا كنت حظا حظا، فأنت تحصل على AV، إذا لم تكن لديك ثغرة قابلة للاستغلال. من الأفضل دائما استخدام حجم الوجهة دائما، على الرغم من بهذه الطريقة أنه يمكنك إنهاء قراءة الذاكرة التي يجب ألا يجب أن تكون الحجم (ب)> الحجم (أ)، وربما تعريض البيانات غير المرغوب فيها. على أي حال، تحقق دائما من حدود الهيكل عند نقل البيانات - تم حظر بعض الشركات عمليات مثل هذا (أي MEMCPY ()) من التعليمات البرمجية الخاصة بهم.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top