1 / 14

التعامل مع المؤشرات Pointers في لغة C++

التعامل مع المؤشرات Pointers في لغة C++. مفهوم مواقع الذاكرة عنونة المتغيرات في الذاكرة و الحصول على عناوين المتغيرات في الذاكرة ما هو المؤشر ؟ الإعلان عن المؤشر في البرنامج و استخدامه و لكن ما هي فائدة المؤشرات ؟؟؟ الوصول إلى محتوى القيمة التي يشر اليها المؤشر المؤشرات و المصفوفات

nibal
Download Presentation

التعامل مع المؤشرات Pointers في لغة C++

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. مواقع الذاكرة • لنعتبر ان شكل الذاكرة مثل صناديق البريد ، حيث تمثل كل خانة موقع في الذاكرة و تقوم بتخزين قيمة وحيدة (قد تكون صحيحة int او حقيقة float او char) ، كل موقع في الذاكرة له عنوان ، و يتم تمثيل عناوين الذاكرة باستخدام النظام الست عشري من باب تسهيل كون انه في الاصل يمثل باستخدام النظام الثنائي ، فعلى سبيل المثال لتمثيل الخانة رقم 15 باستخدام النظام الثنائي فإننا سوف نحتاج إلى اربع خانات هي 1111 على عكس النظام الست عشري الذي يمثلها بخانة واحدة هي F .

  3. عنونة المتغيرات في الذاكرة • عند تعريف المتغيرات في البرنامج ، فإنها تأخذ حيزاً في الذاكرة بما يتناسب مع حجمها فعلى سبيل المثال المتغيرات من نوع int تشغل 2 bytes على عكس المتغيرات من char و التي تشغل 1 byte. • لاحظ هذا المثال : main() { int i = 19; char c = 'X'; float f = 3.453; } • السؤال الآن .. هل يمكن ان نتعامل مع عنوان المتغير في الذاكرة بدل ان نتعامل معه بشكل مباشر ؟؟ ثم كيف يمكن ان نحصل على عنوان متغير ما في الذاكرة ؟

  4. عناوين المتغيرات في الذاكرة • كي نستطيع ان نعرف عنوان متغير ما في الذاكرة نقوم بإضافة الإشارة & قبل المتغير و هي تعني عنوان المتغير (Address Of ) ،لاحظ : #include "iostream.h" #include "conio.h" void main() { int x; cout << "Enter Number: "; cin >> x; cout << "\nThe Number is:" << x << endl; cout << "\nand The address in memory is: "<< &x << endl; getch(); } • عند تجربة البرنامج تظهري لي النتيجة التالية : The Number is: 5and Thr address in memory is: 0x0012FF7C لاحظ ان الناتج من الممكن أنا يختلف من كمبيوتر إلي كمبيوتر آخر, ومن تنفيذ إلي أخر (لماذا) يطبع محتوى المتغير يطبع عنوان المتغير

  5. ما هو المؤشر ؟ • تمثل المؤشرات احد أهم الإمكانيات التي توفرها لغة C++ ... اول سؤال سيبدر إلى ذهنك ما هو المؤشر و إلى ماذا يشير ... • و كما هو الحال مع أي متغير ، فإننا قبل ان نستخدم المؤشر في برنامجنا لابد لنا من ان نعلن عنه .. • كل المتغيرات من نوع مؤشر لها نفس الحجم في الذاكرة و هو حجم العنوان الذي تحتويه (فهي مجهزة لتخزين العناوين) .. المؤشر عبارة عن متغير يحتوي على عنوان في الذاكرة (و ليس قيمة عادية) ، وهو يشير الى العنوان الذي يحتويه و بالتالي فهو يشير إلى متغير اخر ...

  6. نوع القيمة التي يشير اليها المؤشر الإعلان عن المؤشر في البرنامج و استخدامه • يتم الاعلان عن المؤشر في البرنامج بتحديد نوع القيمة التي يشير اليها (أي هل يشير إلى قيمة من نوع int-char-float ..) ثم اضافة العلامة (الرمز) نجمة * ثم اسم المؤشر ، لاحظ هذا المثال : • لا يمكن التعامل مباشرة مع المؤشر في البرنامج قبل ان نسند اليه عنوان متغير ما كما يلي : int i; iPtr = & i • لاحظ انه من المتعارف عليه(و ليس شرط) ان تبدأ اسم اسماء المؤشرات بالمتغير الذي تشير اليه و تنتهي بالكلمة Ptr ، و لابد ان يشر المؤشر إلى قيمة لها نفس نوعه . int *iPtr; // int* iPtr; نجمة يليها اسم المؤشر

  7. 1020 1022 العناوين في الذاكرة 10032 … 88 5 … 1024 … y yPtr الإعلان عن المؤشر في البرنامج و استخدامه • اتفقنا ان الرمز & يعيد عنوان المتغير في الذاكرة ، لاحظ هذا المثال : int y = 5; int *yPtr; yPtr = &y; // y تأخذ عنوان yPtr • لاحظ كيف سيكون شكل المتغيرات في الذاكرة : • لاحظ من المثال ان انشاء المؤشر يتم على مرحلتين الاولى نعلن فيها عن المؤشر yPtr و الثانية نستد اليه عنوان متغير في الذاكرة و ذلك يعني ان yPtr سوف تشير إلى المتغير y في الذاكرة و بالتالي من الممكن التعامل مع y بشكل غير مباشر عن طريق yPtr . y yPtr 5

  8. و لكن ما هي فائدة المؤشرات ؟؟؟ • لنتخيل اننا نريد ان نخزن رقم هاتف شخص ما في ذاكرة هاتف النقال و ليكن هذا الشخص "محمد" ، فإننا سوف نقوم اولاً بإدخال رقم الهاتف ثم سندخل بعدها اسم "محمد" .. و الآن اذا اردنا نتصل بـ "محمد" فإننا سوف نبحث عن اسم "محمد" و نقوم بالاتصال به .. و لكن في الحقيقة لا يوجد رقم تلفون رقمه "محمد" و لكن اسم "محمد" هذا يشير على مكان في ذاكرة الهاتف يحتوي على الرقم المراد الاتصال به .... • في المثال السابق ، يمثل لنا الاسم ”محمد ” المؤشر الذي يحتوي على رقم الهاتف و بدلاً من ان نتصل بإدخال الرقم فإننا نستخدم ”محمد“ كونها تسهل لنا الامور و تسرعها ...

  9. و لكن ما هي فائدة المؤشرات ؟؟؟ • هناك حالات لابد معها من استخدام المؤشرات ، و هناك حالات لا تشترط ذلك ، و لكن الامور تكون اسهل و اسرع في حال ان استخدمنا المؤشرات.. من فوائد المؤشرات : • الوصول إلى عناصر المصفوفة . • تمرير المعاملات إلى دالة باستخدام العنوان (Passing By Reference) . • ارسال المصفوفة او سلاسل الحروف إلى الدوال . • التحكم بمساحة اكبر من الذاكرة. • في التعامل مع هياكل البيانات (Linked List , ……) .

  10. الوصول إلى محتوى القيمة التي يشر اليها المؤشر • عندما نعلن عن مؤشر فإننا نستخدم الصيغة (int *varPtr) حيث ان اسم المؤشر هو varPtr ، و لكننا نستخدم الصيغة *varPtrداخل البرنامج (كتعبير) من اجل الوصول إلى محتويات المتغير الذي يشير اليه المؤشر varPtr ، لاحظ هذا المثال : void main () { int *varPtr; Int var = 20 ; varPtr = &var; cout << *varPtr; // 20 cout << var ; // 20 } • و هكذا عليك بالانتباه إلى : • استخدام *varPtr في جملة الاعلان int *varPtr; تعني اننا نعلن عن مؤشر اسمه varPtr و يشير إلى قيمة من نوع عدد صحيح . • استخدام *varPtr في البرنامج كتعبير cout << *varPtr; تعني اننا نتعامل مع محتوى القيمة التي يشير اليها المؤشر varPtr . يستخدم اسم المؤشر مسبوق بالنجمة في البرنامج ، من اجل الوصل إلى محتويات المتغير الذي يشير اليه.

  11. الوصول إلى محتوى القيمة التي يشر اليها المؤشر • تتبع البرنامج التالي ، و حاول ان تستنتج شكل المخرجات : int main (){ int value1 = 5, value2 = 15; // الاعلان عن متغيرين صحيحين int* p1; // الاعلان عن مؤشر يشير إلى قيمة من نوع عدد صحيح int* p2; // الاعلان عن مؤشر ثاني يشير إلى قيمة من نوع عدد صحيح p1 = &value1; // جعل المؤشر الاول يشير إلى المتغير الاول p2 = &value2; // جعل المؤشر الثاني يشير إلى المتغير الثاني *p1 = 10; // تخزين القيمة 10 في المتغير الذي يشير اليه المؤشر *p2 = *p1; // مساواة قيم المتغيرات التي تشير لها المؤشرات p1 = p2; // جعل المؤشر الثاني يشير إلى المتغير الذي يشير اليه المؤشر الاول *p1 = 20; // تخزين القيمة 20 في المتغير الذي يشير اليه المؤشر الاول cout << "value1==" <<value1<<"/ value2=="<< value2; return 0; } • النتيجة هي : • Value1 is 10 • Value2 is 20

  12. المؤشرات و المصفوفات • هناك علاقة خاصة بين المصفوفات و المؤشرات ، لاحظ كيف يمكن الوصول الى عناصر المصفوفة A في المثال التالي : int A[5] = {7 ,2 ,6 ,4 ,3} ; for(int i=0;i<5;i++) cout<<A[i]; من خلال المثال السابق نلاحظ انه تم الوصول الى عناصر المصفوفة عن طريق ذكر اسم المصفوفة (ال1ي يمثل عنوانها في الذاكرة) و رقم العنصر المراد الوصول اليه (تذكر ذلك لاحقاً) . • انتبه معي الى التالي : • اسم المصفوفة يدل على موقعها في الذاكرة ، اذن فأسم المصفوفة عبارة عن مؤشر ، و هذا المؤشر يشير الى اول موقع في المصفوفة ، أي العنصر A[0] ، و بالتالي فمن الممكن القول ان (ليس بشكل برمجي و لكن كمفهوم): A[0] = A

  13. المؤشرات و المصفوفات • لاحظ كيف يمكن الوصول الى عناصر المصفوفة A باستخدام المؤشرات في المثال التالي : int A[5] = {7 ,2 ,6 ,4 ,3} ; Int* aPtr; aPtr = A; // تم اسناد عنوان المصفوفة عن طريق اسمها الى المؤشر for(int i=0;i<10;i++) cout<<*( aPtr + i ); • في المثال السابق لاحظ : • تم الوصول الى محتويات المصفوفة عن طريق *( aPtr + i ) حيث ان المؤشر aPtr يشير الى المصفوفة A (الى اول موقع فيها و الذي رقمه 0) ، و النجمة قبل اسم المؤشر تعني محتوى القيمة التي يشير اليها المؤشر، و من اجل الانتقال الى العنصر التالي في المصفوفة نقوم بإضافة قيمة i (و التي تكون متسلسلة 1 2 ....) ، لان اضافة قيمة i يعمل على تحريك المؤشر بمقدار 2 bytes (لأن المؤشر من نوع int) ، و بالتالي الانتقال الى الخانة التالية .

  14. المصفوفة مؤشر ثابت ، لكن المؤشرات متحركة ! • لاحظ التغير الذي طرأ على المثال السابق int A[5] = {7 ,2 ,6 ,4 ,3} ; Int* aPtr; aPtr = A; // تم اسناد عنوان المصفوفة عن طريق اسمها الى المؤشر for(int i=0;i<10;i++) cout<<*( aPtr ++); • في المثال السابق لاحظ : • تم اسناد عنوان المصفوفة A الى المؤشر aPtr لذا اصبح من الممكن الوصول الى عناصر المصفوفة عن طريق هذا المؤشر ، في المثال السابق (الصفحة السابقة) استخدمنا الصيغة *( aPtr + i ) لتحريك المؤشر بين عناصر المصفوفة ، و في هذا المثال استخدمنا صيغة اخرى لتحريك المؤشر بين عناصر المصفوفة و التي هي *( aPtr ++) ، و كلا الصغتين صحيح لانه يضيف مقدار 2 bytes الى المؤشر aPtr مما يحركه الى العنصر التالي . • لكن هل من الممكن عمل *(A ++) ، أي التحريك و الانتقال باستخدام اسم المصفوفة (الذي هو مؤشر الى المصفوفة) ؟؟ الاجابة لا ، لأن التعبير A و الذي يدل على عنوان المصفوفة في الذاكرة عبارة عن موقع ثابت لا ينبغي تغيره او العبث به .

More Related