لمؤشرات pointer الجزء الثانى

**تمرين آخر :
كود:
كود:
 	#include<stdio.h> main( ) { int u1 ,u2; int v =3; int pv  / pv pointer to v */ u1 = 2*(v + 5 ); /* ordinary expression */ pv = &v ; u2 = 2*(*pv + 5 ); printf(“\n u1 = %d       us2 = %d “,u1 , u2 );
}

ملاحظات :
- يشمل هذا البرنامج تعبيرين صحيحين اولهما 2*(v + 5 ) وهو تعبير حسابى معتاد . اما الثانى 2*(*pv + 5 ) يحتوى على استخدام مشير ويتكافئ التعبيران حيث أن كلا من v , *pv يمثل نفس القيمة الصحيحة
- ناتج البرنامج :
v = 3 u1 = 15 u2 = 16 pv = 3
u1=2*(v + 5 ) u2 = 2*(*pv + 5)
u1=2*(3+5) u2=2*(3+5)
u1= 16 u2=16
** تمرير المؤشرات إلى الاجراءات الفرعية **


- من المعلوم أن لغة C تمرر المتغيرات إلى الإجراءات بالقيمة وليس بالاشارة.
- اى عندما تمرر متغيراً لأحد الإجراءات فإن هذا الإجراء يتلقى نسخة من المتغير وليس المتغير نفسه ( أى يتلقى " قيمة " المتغير وليس المتغير نفسه ) كما فى الشكل التالى :-
نقره لتكبير أو تصغير الصورة ونقرتين لعرض الصورة في صفحة مستقلة بحجمها الطبيعي

ملاحظات :
- فى الإجراء main نعلن عن المتغير num ونضع فيه العدد 5 ثم نستدعى الإجراء change ونمرر له هذا المتغير.
- فى هذه الحالة يقوم المترجم بتمرير القيمة الموجودة فى المتغير num وهى العدد 5 إلى الاجراء change ولن يتمكن الإجراء change من رؤية المتغير num الموجود فى main
- فرغم ان المتغير num موجود فى الإجراء main وفى الإجراء change إلا ان كل واحد منهما يختلف عن الاخر، فكل واحد منهما متغير محلى local خاص بالإجراء الذى يوجد فيه.
- ملاحظة : ( تمرير المتغيرات بالقيمة وليس بالإشارة مسالة مفيدة لنها تحمى المتغيرات المحلية لكل إجراء من اى تعديل غير مقصود )


* إذا أردت أن تتيح للإجراء الفرعى أن يعدل المتغير الذى تمرره له . أتبع الاتى :-
الخطوة الأولى : -
- هى أن تعدل الاعلان عن الإجراء فى بداية البرنامج ورأس الاجراء نفسه بحيث تخبر المترجم ان سيتلقى مؤشراً وليس متغيراً عادياً.
- فمثلاً الاعلان عن الاجراء التالى : void change ( int * ptr );
- هنا نخبر المترجم ان الإجراء change سيتلقى مؤشراً وليس متغيراً عادياً
الخطوة الثانية :
- هى ان تمرر للإجراء عنواناً فى الذاكرة مثل : change(ptr) على اعتبار ptr هو مؤشر لأحد المتغيرات
- فى هذه الحالة سيكون لدى الاجراء الفرعى عنوان المتغير ويتمكن بالتالى من تعديل قيمته.
البرنامج التالى يوضح ذلك :
كود:
#
كود:
كود:
include<stdio.d> void change( int *ptr );
كود:
كود:
void main(void) { int num = 5; int *ptr; ptr = &num ; printf( “berfore change , num =%d \n “, num); change(ptr); printf(“after change, num = %d \n “, num ); } void change( int * ptr ) { *ptr = 7; }
ملاحظات
- فى بداية البرنامج نعلن عن الاجراء void change( int *ptr );
- هذا الاعلان يخبر المترجم ان الاجراء change يستقبل مؤشراً وليس متغيراً
- والسبب فى ذلك هو الحرف ( * ) الذى يسبق اسم المؤشر كذلك نفس الصيغة فى رأس الاجراء .
- وفى الاجراء main نعلن عن المتغير num ونضع فيه العدد 5 ثم نعلن عن المتغير ptr وننقل إليه عنوان المتغير num فى الذاكرة مثل : ptr = &num
- بهذا الشكل يصبح المتغير ptr حاملاً لعنوان المتغير فى الذاكرة
بعد ذلك نستخدم الاجراء peintf لنطبع قيمة المتغير num قبل استدعاء الإجراء change ثم نستدعى الاجراء change ونمرر له المتغير ptr
- الاجراء change يحتوى على *ptr = 7; هذه العبارة تستخدم المؤشر ptr لتضع العدد 7 فى العنوان الذى يشير إليه.
- ولما كان المتغير ptr يشير إلى num فإن هذه العبارة تغير محتويات المتغير num الى العدد
- ويكون ناتج البرنامج :-
before change , num = 5
after change , num = 7
** العودة بأكثر من قيمة من الإجراء الفرعى **
- ملاحظة : سبق إن ذكرنا أن استخدام كلمة return للعودة بقيمة ما من الاجراءات الفرعية ولكن كلمة return تعود بقيمة واحدة فقط
- الحل : هو ان تعلن عن متغيرات محلية بعدد المعلومات التى تريد ان يعود بها الاجراء ثم تمرر مؤشرات لهذه المتغيرات للاجراء ليضع المعلومات فيها
البرنامج التالى يوضح ذلك :-
كود:
كود:
#include<stdio.h> void fn( int *var1 , int *var2 , int *var3); void main(void) { int var1 ,var2, var3; fn(&var1 , &var2 , &var3) printf(“var1 = %d , var2 = %d , var3 = %d”, var1 , var2 , var3); }
كود:
كود:
void fn( int *p1 , int *p2 , int *p3) { *p1=10; *p2=20; *p3=30;
}


ملاحظات :
- فى بداية البرنامج نعلن عن ثلاثة متغيرات محلية var1,var2,var3 ولا نضع فيها اى قيمة
- بعد ذلك نستدعى الاجراء fn ونمرر له عناوين هذه المتغيرات الثلاثة
- الاجراء fn يستقبل هذه العناوين ويضعها فى مؤشرات باسم p1,p2,p3
- بعد ذلك يقوم الاجراء fn بتعيين هذه للعناوين التى تشير إليها هذه المؤشرات
- وعندما نعود الى الاجراء main نستخدم الاجراء printf لنطبع القيمة الموجودة فى المتغيرات var1,var2,var3
- نلاحظ انها نفس القيمة التى وضعها الاجراء fn فى العناوين التى مررناها له ويكون الناتج :-
var1 = 10, var2 = 20 , var3 = 30
بهذا الشكل يمكنك استقبال اى عدد من البيانات من الاجراءات الفرعية