وظائف مؤشر Fortran: لماذا يعتمد سلوك هذا الرمز على ترتيب مكالمات الوظائف؟

StackOverflow https://stackoverflow.com/questions/1580426

سؤال

سياق

رمز Toy Fortran المنشور أدناه يستدعي وظيفتين مؤشرتين. وهذا هو ، كلتا الوظيفتين تُرجع مؤشرًا. في الواقع ، كلاهما مؤشرات صفيف. كلاهما يحاولان فعل الشيء نفسه ، وهو إرجاع مؤشر مجموعة عدد صحيح يشير إلى صفيف عدد صحيح له ثلاثة عناصر ، 1 و 2 و 3. تستخدم الوظيفة الأولى مشغل مهمة المؤشر (=>) لتوجيه مؤشر الوظيفة إلى صفيف مخصص يحمل البيانات. تخصص الوظيفة الثانية كتلة من الذاكرة الديناميكية مباشرة ، عبر المؤشر ، لتخزين البيانات. يطبع برنامج الاتصال عناصر الصفيف (المصفوفة) التي تم إرجاعها.

هذا ما أجده غريبًا.

  1. إذا كنت أشير a إلى نتيجة function1, ، النتائج غير صحيحة. العنصر الأول من a يبدو أنه "clobbered": a لديها 0, 2, 3.
  2. إذا كنت أشير b إلى نتيجة function2, ، النتائج صحيحة. b يحصل على 1, 2, 3.
  3. غريب لا يزال ، يشير b إلى نتيجة function2 بعد تشير a ل function1 التغييرات a بحيث يصبح صحيحا. a ثم لديه 1, 2, 3.

سؤال

لماذا يحدث هذا؟ بتعبير أدق ، لماذا تعمل مؤشر المؤشر الذي يرجع مؤشرًا إلى صفيف مخصص للعنصر الأول من تلك الصفيف للمتصل؟ لا يزال أدق ، لماذا يشير مؤشر واحد (b) إنتاج تأثير جانبي على مؤشر آخر (a) ، حيث تأتي الأهداف من وظائف مختلفة مكتوبة حتى لا تتفاعل مع بعضها البعض على الإطلاق؟

تحفظات

أحصل على هذا السلوك باستخدام Gnu Fortran Compiler v.4.3.3 ، الذي يدير جهاز كمبيوتر محمول Intel مع Ubuntu (jaunty). قد تختلف نتائجك ، والتي قد تكون أكثر إثارة للاهتمام. أخيرًا ، كما هو الحال دائمًا ، قد يكون خطأ المشغل من جانبي ، والذي سيكون مثيرًا للاهتمام بالنسبة لي على الأقل.

شفرة

program main
  implicit none
  integer, dimension(:), pointer :: a, b
  integer :: i
  a => function1()
  b => function2()
  do i = 1, 3
     print *, a(i)
  end do
  ! do i = 1, 3
  !    print *, b(i)
  ! end do
contains
  function function1 ()
    integer, dimension(:), allocatable, target :: array
    integer, dimension(:), pointer :: function1
    allocate(array(3))
    array(1) = 1
    array(2) = 2
    array(3) = 3
    function1 => array
  end function function1

  function function2 ()
    integer, dimension(:), pointer :: function2
    allocate(function2(3))
    function2(1) = 1
    function2(2) = 2
    function2(3) = 3
  end function function2
end program main
هل كانت مفيدة؟

المحلول

عامل مجموعة مصفوفة من الوظيفة 1 هو متغير محلي - لأنه يتم إعلانه بدون سمة "حفظ" ، فهو غير ثابت وغير محدد عندما تخرج الوظيفة. تقوم بتعيين عنوان مجموعة مصفوفة إلى الوظيفة 1 ، "الحفاظ على" هذا العنوان ، لكن العنوان ليس ذا معنى بمجرد أن يصبح المتغير غير محدد بعد الخروج من الوظيفة. التنفيذ المحتمل هو ذلك مجموعة مصفوفة سيتم وضع Function1 على المكدس ، وسيتم تحرير منطقة المكدس هذه لاستخدامات أخرى عند إرجاع Function1. ولكن هذا مجرد تخمين في تطبيق محتمل - النقطة الأساسية هي أنه لا يُسمح لك باستخدام قيمة المؤشر بعد أن يصبح المتغير غير محدد. يتم تعامل المتغيرات المتخصصة تلقائيًا عند الخروج من النطاق إلا إذا أعلنت سمة "حفظ".

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