المؤشرات Pointers :

استعرض الموضوع السابق استعرض الموضوع التالي اذهب الى الأسفل

المؤشرات Pointers :

مُساهمة من طرف Admin في الأحد فبراير 23, 2014 8:34 pm

المؤشرات Pointers :
نحن نعرف أن "المتغيرات" هى مواقع بالذاكرة ، والتى يمكن الوصول إليها عن طريق "المعرفات" الخاصة بها ، وهى أسمائها ، . بهذه الطريقة ، لا يحتاج البرنامج إلى الاهتمام بالعنوان الفعلى للبيانات فى الذاكرة ، بل ببساطة يستخدم المعرف (الاسم) كلما احتاج الرجوع إلى المتغير .

فى لغة السى ، الذاكرة تشبه "الخلايا المتتابعة" (المتسلسلة) ، كل خلية بحجم "واحد بايت" ، وكل خلية لها عنوان فريد . يتم ترتيب خلايا الذاكرة ذات الواحد بايت هذه بطريقة تسمح للبيانات الممثلة بأكبر من بايت واحد بأن تحتل خلايا ذاكرة لها عناوين متتالية .
بهذه الطريقة ، فإن كل خلية يمكن أن تقع بسهولة فى الذاكرة عن طريق عنواها الفريد . على سبيل المثال ، خلية الذاكرة التى عنوانها (1776) تكون دائما مباشرة بعد الخلية التى عنوانها (1775) ، وتسبق الخلية التى عنوانها (1777) ، ويكون هناك بالضبط "ألف خلية" بعد الخلية التى عنوانها (776) ، و ألف خلية قبل الخلية التى عنوانها (2776) .
عندما يتم إعلان (تعريف) المتغير ، فإنه يتم تخصيص (تعيين) مواقع (أماكن) محددة من الذاكرة المطلوبة لتخزين قيمته ( أى عناوين ذاكرته) . عموما ، برامج لغة السى لا تقرر بالضبط عناوين الذاكرة حيث يتم حفظ متغيراتها . هذه المهمة تترك للمترجم ، ووقت التشغيل . ومع ذلك ، قد يكون من المفيد للبرنامج أن يكون قادرا على الحصول على "عنوان المتغير أثناء وقت التشغيل" من أجل الوصول إلى خلايا البيانات التى تكون عند مكان محدد بالنسبة له .

عامل المرجعية (&) Reference Operator :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: المؤشرات Pointers :

مُساهمة من طرف Admin في الأحد فبراير 23, 2014 8:40 pm



عامل المرجعية (&) Reference Operator :

يمكن الحصول على "عنوان المتغير" عن طريق سبق (تقديم) اسم المتغير بعلامة العطف (&) ، والمعروفة باسم "عامل المرجعية" ، والذى يمكن ترجمته حرفيا بأنه "عنوان ال" . على سبيل المثال :
   

الكود:


foo = &myvar;




وهذا من شأنه تخصيص "قيمة عنوان المتغير myvar " ( &myvar) إلى "قيمة المتغير  foo " (foo)  ، عن طريق سبق اسم المتغير myvar بعامل المرجعية &، فإننا لا نخصص محتوى المتغير نفسه إلى foo ، ولكن نخصص عنوانه .
العنوان الفعلى للمتغير بالذاكرة "لا يمكن معرفته قبل وقت التشغيل" ، ولكن دعونا نفترض ، من أجل المساعدة فى توضيح بعض المفاهيم ، أن المتغير myvar قد وضع أثناء وقت التشغيل بعنوان الذاكرة (1776) .
فى هذه الحالة اعتبر قطعة الكود الصغيرة التالية :


الكود:


myvar = 25;
foo = &myvar;
bar = myvar;




القيم المحتواة بكل متغير بعد تنفيذ هذا الجزء تكون كما هو مبين بالمخطط التالى :





• فى البداية ، بعبارة تخصيص ، خصصنا القيمة (25) إلى المتغير myvar ( أصبحت محتوياته 25 وعنوانه ، الذى فرضناه ، بالذاكرة هو 1776 )  .  
• ثم ، بعبارة تخصيص ثانية ، خصصنا قيمة عنوان المتغير myvar إلى المتغير foo ، الذى فرضنا أنه 1776 (أصبحت "محتويات" المتغير foo بالقيمة 1776) .
• وأخيرا ، وبعبارة تخصيص ثالثة ، خصصنا القيمة المحتواة بالمتغير myvar (وهى 25 ) إلى المتغير bar (ليصبح محتواه 25 ) . وهذه هى عبارة التخصيص القياسية التى نعرفها جيدا .  
الفرق بين عبارة التخصيص الثانية وعبارة التخصيص الثالثة هو ظهور معامل المرجعية (&) .
"المتغير الذى يخزن عنوان متغير آخر يسمى مؤشر Pointer " ، مثل المتغير foo فى المثال السابق . المؤشرات هى ميزة قوية جدا فى لغة السى . لاحقا سوف نتناول طريقة إعلان واستخدام المؤشرات .

عامل إلغاء المرجعية Dereference ( * ) :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: المؤشرات Pointers :

مُساهمة من طرف Admin في الأحد فبراير 23, 2014 8:50 pm


عامل إلغاء المرجعية Dereference ( * ) :

كما رأينا للتو ، المتغير الذى يخزن عنوان متغير آخر يسمى "مؤشر" . يقال أن المؤشرات "تشير إلى" المتغير الذى تقوم بحفظ عنوانه .

الميزة المثيرة للاهتمام فى المؤشرات هى أنه "يمكن استخدامها للوصول إلى المتغير الذى تشير إليه مباشرة" . يتم عمل ذلك عن طريق "سبق اسم المؤشر بعامل إلغاء المرجعية ( * ) . العامل فى حد ذاته يمكن قراءته فى صيغة " القيمة المشار إليها بواسطة" .

لذلك ، وبالمتابعة مع قيم المثال السابق ، فأن العبارة التالية :




الكود:


baz = *foo;





يمكن أن تقرأ على النحو التالى : "قيمة المتغير baz " تساوى "القيمة المشار إليها بالمتغير foo" ، وسوف تقوم العبارة فعليا بتخصيص القيمة 25 إلى المتغير baz ، حيث أن المتغير foo قيمته 1776 ، والقيمة المشار إليها بواسطة 1776 سوف تكون 25 ( فى أعقاب المثال أعلاه) .  






من المهم أن نفرق بوضوح بين أن المتغير foo يشير إلى القيمة 1776 ، فى حين أن (*foo) (مع وجود *  تسبق اسم المتغير) تشير إلى القيمة المخزنة عند العنوان 1776 ، وهذه القيمة فى هذه الحالة هى 25 .  لاحظ الفرق بين تضمين أو عدم تضمين عامل إلغاء المرجعية كما هو مكتوب بالتعليقات على العبارات التالية :


الكود:


baz = foo;              // baz equal to foo (1776)

baz = *foo;           // baz equal to value pointed to by foo (25)



وبالتالى فإن عامل المرجعية وعامل إلغاء المرجعية هى عوامل مكملة أو متتامة :

·       العامل &  هو عامل المرجعية ، ويمكن قراءته كما يلى "عنوان ال .." .

·       العامل *  هو عامل إلغاء المرجعية ، ويمكن قراءته كما يلى "القيمة المشار إليها بواسطة ..." .  

وبالتالى فإن لها معانى معكوسة : المتغير الذى يرجع إليه بالعامل & يمكن أن يتم إلغاء مرجعيته بالعامل * .

فى وقت سابق أجرينا عملتى التخصيص التالية :




الكود:


myvar = 25;

foo = &myvar;



بعد هذه العبارات مباشرة ، فإن جميع العبارات التالية تعطى "صواب" true كنتيجة :




الكود:


myvar == 25

&myvar == 1776

foo == 1776

*foo == 25



·       التعبير الأول واضح تماما ، باعتبار أن عملية التخصيص التى أجريت على المتغير myvar كانت myvar = 25 .

·       التعبير الثانى يستخدم عامل المرجعية (&) ، والذى يعيد return عنوان المتغير myvar ، والذى فرضنا أن له القيمة  1776 .

·       التعبير الثالث واضح إلى حد ما ، لأن التعبير الثانى كان صحيحا وأن عملية التخصيص التى أجريت على المتغير foo كانت foo = &myvar .

·       التعبير الرابع يستخدم عامل إلغاء المرجعية (*) والذى يمكن قراءتع بالصيغة "القيمة المشار إليها بواسطة ..." ، والقيمة المشار إليها بالمتغير foo هى فى الواقع 25 .

لذلك ، وبعد كل ذلك ، يمكنك أيضا أن تستنتج أنه طالما أن العنوان المشار إلية بالمتغير foo لم يتغير ، فإن التعبير التالى سوف يكون صواب true أيضا :


الكود:


*foo == myvar





إعلان (تعريف) المؤشرات Declaring Pointers :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: المؤشرات Pointers :

مُساهمة من طرف Admin في الأحد فبراير 23, 2014 8:53 pm

إعلان (تعريف) المؤشرات Declaring Pointers :

نتيجة لقدرة المؤشر على الإشارة (الرجوع) مباشرة إلى القيمة التى يشير إليها ، فإن المؤشر له خصائص مختلفة عندما يشير إلى قيمة لحرف char عنه عندما يشير إلى قيمة لعدد صحيح int أو عدد حقيقى float . بمجرد إلغاء المرجعية ، فإن النوع ينبغى أن يكون معروفا . ولهذا ، فإن "إعلان المؤشر ينبغى أن يتضمن نوع البيانات التى سوف يشير إليها المؤشر .

إعلان المؤشرات يكون بالصيغة التالية :



الكود:


type * name;


حيث النوع type هو نوع البيانات المشار إليها بواسطة المؤشر . هذا النوع ليس هو نوع المؤشر نفسه ، ولكن نوع البيانات التى يشير إليها المؤشر . على سبيل المثال :

الكود:


int * number;

char * character;

double * decimals;




هذه ثلاثة إعلانات لمؤشرات . كل إعلان يهدف إلى الإشارة إلى نوع مختلف من البيانات ، ولكن ، فى الواقع ، جميعها مؤشرات وجميعها سوف تحتل نفس مقدار المساحة فى الذاكرة ( حجم الذاكرة للمؤشر يعتمد على المنصة حيث يعمل البرنامج ) . وعلى الرغم من ذلك ، فإن البيانات التى تشير إليها لا تحتل نفس مقدار المساحة ولا هى من نفس النوع :

· المؤشر الأول يشير إلى متغير نوع عدد صحيح int .

· المؤشر الثانى يشير إلى متغير نوع حرف char .

· والمؤشر الأخير يشير إلى متغير من النوع double (عدد حقيقى مزدوج) .

لذلك ، على الرغم من أن هذه الأمثلة للمتغيرات الثلاثة جميعها هى مؤشرات ، فإنها الواقع لها أنواع مختلفة من البيانات وهى int , char , double على الترتيب وهذا يتوقف على النوع الذى تشير إليه .

لاحظ أن علامة النجمة (*) تستخدم عندما يعلن عن مؤشر فإنه يعنى فقط أن هذا يكون مؤشرا ( لأن هذا جزء من محدد النوع المركب ) ، وينبغى عدم الخلط بينه وبين "عامل إلغاء المرجعية" الذى تم التعرف عليه من قليل والذى يكتب أيضا كعلامة النجمة (*) . فهما ببساطة شيئين مختلفين ممثلة بنفس العلامة .



مثال على المؤشرات :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: المؤشرات Pointers :

مُساهمة من طرف Admin في الأحد فبراير 23, 2014 8:55 pm

مثال على المؤشرات :

الكود:


void main ()

{

  int firstvalue, secondvalue;

  int * mypointer;

……….

………

  mypointer = &firstvalue;

  *mypointer = 10;

 

  mypointer = &secondvalue;

  *mypointer = 20;

……….

……….

  }




لاحظ أنه على الرغم من أنه لا firstvalue ولا secondvalue قد تم تحديد أى قيمة مباشرة لها فى البرنامج ، إلا أن كليهما انتهيا بتحديد قيمة بطريقة "غير مباشرة" من خلال استخدام المؤشر mypointer . فيما يلى كيف حدث ذلك :

· فى البداية يخصص للمؤشر mypointer عنوان المتغير firstvalue باستخدام عامل المرجعية (&) ، بالصيغة التالية :



الكود:


mypointer = &firstvalue;


· بعد ذلك ، "القيمة المشار إليها بواسطة المؤشر " *mypointer يخصص لها القيمة (10) كما يلى :

الكود:


*mypointer = 10;


ولأنه ، عند هذه اللحظة ، المؤشر mypointer يكون مشيرا إلى موقع الذاكرة (عنوان) للمتغير firstvalue ، فإن هذا فى واقع الأمر يعدل من قيمة المتغير firstvalue .

· ولتوضيح أن المؤشر قد يشير إلى متغيرات مختلفة خلال فترة بقائه (حياته) فى البرنامج ، يتم تكرار العملية السابقة مع المتغير secondvalue وبنفس المؤشر mypointer كما يلى :

الكود:


 mypointer = &secondvalue;

 

*mypointer = 20;




مثال آخر مفصل أكثر بعض الشىء :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: المؤشرات Pointers :

مُساهمة من طرف Admin في الأحد فبراير 23, 2014 8:57 pm

مثال آخر مفصل أكثر بعض الشىء :

الكود:


void main ()

{

 

  int firstvalue = 5, secondvalue = 15;

  int * p1, * p2;

 

  p1 = &firstvalue;              // p1 = address of firstvalue

  p2 = &secondvalue;          // p2 = address of secondvalue

 

  *p1 = 10;                            // value pointed to by p1 = 10

 

  *p2 = *p1;                          // value pointed to by p2 = value pointed by p1

 

  p1 = p2;                              // p1 = p2 (value of pointer is copied)

 

  *p1 = 20;                            // value pointed by p1 = 20

 

    }





تتضمن كل عملية تخصيص تعليق على كيفية قراءة كل سطر : أى استبدال العامل (&) بواسطة الصيغة "عنون ال ...) ، واستبدال العامل ( * ) بالصيغة "قيمة المشار إليه بواسطة ...." .

لاحظ أن هناك تعبيرات مع المؤشرات p1و p2 ، كلاهما مع أو بدون عامل إلغاء المرجعية ( * ) . معنى التعبيير باستخدام عامل إلغاء المرجعية يختلف تماما عن تلك التى بدونه . عندما يسبق هذا العامل اسم مؤشر ، فإن التعبير يشير إلى القيمة المراد الإشارة إليها ، بينما يظهر اسم المؤشر بدون هذا العامل ، فإنه يشير إلى قيمة المؤشر نفسه ( أى عنوان ما يشير إليه المؤشر) .

شىء آخر قد يلفت انتباهك ، وهو السطر التالى :

الكود:


int * p1, * p2;


هنا ، يتم إعلان المؤشرين المستخدمة فى المثال السابق . ولكن لاحظ أن هناك علامة النجمة ( * ) لكل مؤشر ، وذلك لأن كل منهما له النوع int ( مؤشر إلى متغير نوع العدد الصحيح int ) . وهذا يكون مطلوب نتيجة لقواعد الأسبقية . لاحظ أنه بدلا من ذلك كان الكود بالشكل التالى :

الكود:


int * p1, p2;


فى الواقع ، p1 سوف يكون من النوع int* ، ولكن p2 سوف يكون من النوع int . المسافات لا تهم على الإطلاق لهذا الغرض . ولكن على أى حال ، ببساطة تذكر أن وضع علامة النجمة لكل مؤشر يكون كافيا لمغظم المستخدمين المهتمين بإعلان مؤشرات متعددة لكل عبارة . أو حتى من الأفضل : استخدام عبارات مختلفة من أجل كل متغير .

المؤشرات والمصفوفات :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

استعرض الموضوع السابق استعرض الموضوع التالي الرجوع الى أعلى الصفحة


 
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى