وظائف مؤشر Fortran: لماذا يعتمد سلوك هذا الرمز على ترتيب مكالمات الوظائف؟
سؤال
سياق
رمز Toy Fortran المنشور أدناه يستدعي وظيفتين مؤشرتين. وهذا هو ، كلتا الوظيفتين تُرجع مؤشرًا. في الواقع ، كلاهما مؤشرات صفيف. كلاهما يحاولان فعل الشيء نفسه ، وهو إرجاع مؤشر مجموعة عدد صحيح يشير إلى صفيف عدد صحيح له ثلاثة عناصر ، 1 و 2 و 3. تستخدم الوظيفة الأولى مشغل مهمة المؤشر (=>) لتوجيه مؤشر الوظيفة إلى صفيف مخصص يحمل البيانات. تخصص الوظيفة الثانية كتلة من الذاكرة الديناميكية مباشرة ، عبر المؤشر ، لتخزين البيانات. يطبع برنامج الاتصال عناصر الصفيف (المصفوفة) التي تم إرجاعها.
هذا ما أجده غريبًا.
- إذا كنت أشير
a
إلى نتيجةfunction1
, ، النتائج غير صحيحة. العنصر الأول منa
يبدو أنه "clobbered":a
لديها0
,2
,3
. - إذا كنت أشير
b
إلى نتيجةfunction2
, ، النتائج صحيحة.b
يحصل على1
,2
,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. ولكن هذا مجرد تخمين في تطبيق محتمل - النقطة الأساسية هي أنه لا يُسمح لك باستخدام قيمة المؤشر بعد أن يصبح المتغير غير محدد. يتم تعامل المتغيرات المتخصصة تلقائيًا عند الخروج من النطاق إلا إذا أعلنت سمة "حفظ".