1 / 66

C++ Programming

C++ Programming. L7 . Pointers. مقدمة Introduction :. إن ذاكرة الحاسب هي عبارة عن مصفوفة من البايتات .

jadon
Download Presentation

C++ Programming

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. C++ Programming • L7 . Pointers

  2. مقدمة Introduction: • إن ذاكرة الحاسب هي عبارة عن مصفوفة من البايتات . • المتحول variable : هو مكان في الذاكرة نحفظ فيه قيمة محرفية أو رقمية أو غير ذلك، ويختلف حجم هذا المتحول على حسب نوعه فقد يكون حجمه بايت واحد فقط في حال كان من النمط char ، ويكون حجمه 4 bytes في حال كان من النمط integer ، وهكذا .... • فإننا عندما نقوم بحجز متحول من النمط integer فإنه يتم حجز 4 bytes له في الذاكرة .

  3. مقدمة Introduction: • أما عندما نقوم بتعريف متحول من النمط char فإنه يتم حجز بايت واحد فقط له . • وعندما نقوم بإنشاء متحول من صف ما object from class فإن هذا المتحول سيأخذ حجماً في الذاكرة يناسب الصف المعرف .

  4. المراجع References : • إن كل متحول في الذاكرة له عنوان ، للحصول على عنوان متحول ما نستخدم العلامة & ونتبعها باسم المتحول . • مثال : ليكن المتحول x من النمط integer ويحمل القيمة 10 أي : • int x = 10; • cout<<x<<endl ; ( 10) • cout<<&x<<endl; (0x1BFE9C) • لا يمكن التعديل على عنوان متحول ما ، أي أن الكتابة التالية هي خاطئة : • &x = 11;(Error)

  5. المراجع References : • أمثلة عن تعريف المتحولات وكيفية الحجز بالذاكرة، وكيفية معرفة عناوين المتحولات

  6. الاسم المستعار alias name : الاسم المستعار r هو اسم مرادف لمتغير آخر . إذا طلبت المتحول r كأنني طلبت المتحول n ويكون لهما نفس المكان في الذاكرة .

  7. الاسم المستعار alias name : إن r و n لهما مكان واحد في الذاكرة وإن التعامل مع أحدهم يعني كأننا نتعامل مع الآخر، فإن إنقاص أحدهم يؤدي حتماً إلى إنقاص الآخر .

  8. المؤشرات pointers : • المؤشر pointer : هو أيضاً مكان في الذاكرة ولكنه يحوي عنوان (address) متحول آخر(وهي قيمة عددية مكتوبة بالنظام الست عشري وتمثل عنوان متحول ما في الذاكرة)، ودائماً يكون حجم المؤشر 4 bytes مهما كان محتواه . • إن المؤشرات تعطي لغة c++ فاعلية وسرعة كبيرتين. • ولكن إن التفكير والعمل بالمؤشرات يتطلب الدقة والحذر .

  9. أهمية المؤشرات pointers : • إن المؤشرات تمكننا من إنشاء أغراض أثناء الـRuntime . • حيث إننا سابقاً كنا نقوم بتعريف مصفوفة حصراً طولها ثابت : • int vector[5] ; • أما إذا كتبنا التالي : • inti ; • cin>>i; • int vector[i] ; (Error)

  10. أهمية المؤشرات pointers : • عن طريق المؤشرات يمكننا بناء أنماط معطيات جديدة مثل : (Tree , Stack , Queue , linked list , …..) • المؤشرات تمكننا من تمرير متحول إلى تابع على أنه متحول دخل وخرج معاً، حيث يمكننا التعديل على المتحول داخل التابع ، وبعد الخروج من التابع نجد أن قيمة المتحول قد تغيرت عمّا كانت عليه قبل استدعاء التابع .

  11. تعريف المؤشرات pointers : • يتم تعريف المؤشر تبعاً للصيغة التالية : • أمثلة :

  12. تهيئة المؤشرات pointers : • يتم إعطاء قيمة ابتدائية للمؤشر عن طريق : • إن NULL هي معرفة في المكتبتين <stdlib.h> and <iostream> • وهنا لا يشير المؤشر إلى أي موقع في الذاكرة.

  13. المؤشرات pointers : • يجب أن يكون نمط المؤشر من نفس نمط المعطيات التي يشير عليها كما في المثال السابق، أما الكتابة التالية فهي خاطئة : • تنويه: إن تعريف المؤشر قد يكون بأحد الأشكال التالية :

  14. ربط المؤشر مع متحول ما من نفس النمط: • مثال : • وهنا المؤشر yPtr يحوي عنوان المتحول y وبالتالي فإنه يشير إلى المتحول y .

  15. ربط المؤشر مع متحول ما من نفس النمط: • مثال آخر :

  16. ربط المؤشر مع متحول ما من نفس النمط: • مثال آخر : • نلاحظ أن قيمة المؤشر p هي عنوان المتحول a . • وبما أن المؤشر p هو متحول وبالتالي فإنه له عنوان نحصل عليه بكتابة &p .

  17. ربط المؤشر مع متحول ما من نفس النمط: • يمكن الوصول إلى قيمة المتحول الذي يشير إليه المؤشر p عن طريق استخدام *p . • يسمى المعامل * بـ Dereferencing Operator وتسمى العملية بـ Dereferencing

  18. ربط المؤشر مع متحول ما من نفس النمط: • يمكن الوصول إلى قيمة المتحول الذي يشير إليه المؤشر p عن طريق استخدام *p . • احذر استعمال *p في حال كان المؤشر لا يشير إلى شيء أي في حال كان يحوي Null . ولنتجنب حدوث الأخطاء نستخدم التالي :

  19. مثال على المؤشرات pointers :

  20. مثال على المؤشرات pointers :

  21. مثال على المؤشرات pointers :

  22. مثال على المؤشرات pointers :

  23. مثال على المؤشرات pointers :

  24. ما هو خرج الكود التالي :

  25. ما هو خرج الكود التالي : تذكر أن قيمة المؤشر هي عنوان متحول وليس قيمة ما ! . وتذكر أيضاً أن استخدام *p تعني قيمة المتحول الذي يشير إليه المؤشر p لذلكتجنب استعمال هذا التعبير *p في حال كان المؤشر لا يشير إلى شيء أي (NULL) .

  26. مثال :

  27. تتمة مثال :

  28. تتمة مثال :

  29. سؤال ؟ ما هو الفرق بين التعبيرين *p1 = *p2 و p1 = p2 ? التعبير الأول : *p1 = *p2 معناه وضع في المتحول الذي يشير إليه p1 نفس قيمة المتحول الذي يشير إليه p2 . التعبير الثاني: p1 = p2 معناه جعل قيمة المؤشر p1 نفس قيمة المؤشر p2 أي يمكننا القول أيضاً جعل p1 يشير إلى المكان الذي يشير إليه p2 .

  30. سؤال ؟ ما هو الفرق بين التعبيرين *p1 = *p2 و p1 = p2 ?

  31. مقارنة العناوين ومقارنة المحتوى : ما هو الفرق بين التعبيرين if ( *p1 == *p2 ) و if ( p1 == p2 ) ? التعبير الأول : if ( *p1 == *p2 ) معناه هل قيمة المتحول الذي يشير إليه p1 تساوي قيمة المتحول الذي يشير إليه p2 . التعبير الثاني: if ( p1 == p2 ) هل قيمة المؤشر p1 هي نفس قيمة المؤشر p2 أي يمكننا القول أيضاً هل المؤشران p1 و p2 يشيران إلى نفس المكان في الذاكرة... تذكر أن قيمة مؤشر ما هي عنوان في الذاكرة .

  32. تمرير المتحولات إلى تابع : يوجد ثلاث طرق لتمرير المتحولات إلى تابع وهي : التمرير بالقيمة by value . التمرير بالمرجع عن طريق العناوين (وسطاء التابع هي عناوين) . التمرير بالمرجع عن طريق المؤشرات (وسطاء التابع هي مؤشرات).

  33. تمرير المتحولات إلى تابع : الطريقة الأولى : التمرير بالقيمة by value هنا يكون متحولات التابع هي متحولات دخل فقط حيث أنه بعد الخروج من التابع تعود المتحولات إلى قيمها قبل الاستدعاء .

  34. تمرير المتحولات إلى تابع : الطريقة الثانية : التمرير بالمرجع عن طريق العناوين (وسطاء التابع هي عناوين) هنا يكون متحولات التابع هي متحولات دخل وخرج حيث أنه بعد الخروج من التابع تكون المتحولات قد تم تعديل قيمها .

  35. تمرير المتحولات إلى تابع : الطريقة الثالثة: التمرير بالمرجع عن طريق المؤشرات (وسطاء التابع هي مؤشرات) هنا يكون متحولات التابع هي متحولات دخل وخرج حيث أنه بعد الخروج من التابع تكون المتحولات قد تم تعديل قيمها . انتبه إلى الاستدعاء.

  36. ماذا يحصل بالـ local variable بعد الخروج من نطاقه ؟ بعد الخروج من التابع يزول المتحول المحلي x ولكن قيمته تبقى موجودة في الذاكرة . ولكن هنا لا يمكننا الوصول إلى القيمة 5 الموجودة في الذاكرة لأننا لا نعلم موقع الذاكرة التي وضعت فيها أي أننا لا نعلم عنوان المتحول x بعد الخروج من التابع .

  37. ماذا يحصل بالـ local variable بعد الخروج من نطاقه ؟ بعد الخروج من التابع يزول المتحول المحلي x ولكن قيمته تبقى موجودة في الذاكرة . المؤشر p يبقى يشير إلى مكان في الذاكرة يحوي القيمة 5 . يمكن التعديل على القيمة الموجودة في مكان الذاكرة الذي يشير إليه المؤشر p عن طريق الـDereferencing Operator . نتيجة البرنامج هي 6 .

  38. تابع يرد مؤشر !! بعد استدعاء التابع والخروج منه نجد أن المتحول x يزول ولكن قيمته تبقى موجودة في الذاكرة ويمكن الوصول إليها بواسطة المؤشر p . إن السطر (*p)++ يؤدي إلى زيادة قيمة المتحول الذي يشير إليه المؤشر p . نتيجة البرنامج هي 6 .

  39. ملاحظات : يجب عند تعريف مرجع ما إعطاءه قيمة ابتدائية مباشرة . يجب عدم استعمال الـDereferencing Operator مع مؤشر يؤشر إلى لاشيء.

  40. ما هو خرج البرنامج التالي ؟ إن المؤشر p يشير إلى المتحول n إن r هو اسم مستعار للمتحول الذي يحوي القيمة *p أي أنه اسم مستعار للمتحول n . إن * و & تعملان عملان متعاكسان فإن :n == *p و p == &n ويمكن التعبير عن ذلك أيضاً بـِ : n == *&n و p == &*p

  41. ملاحظات متفرقة : • إذا قمنا بتعريف متحول ما على أنه const ثم قمنا بتعديله فإنه سيظهر لنا Compiler Error . • عند تعريف أي متحول على أنه const يجب إعطاءه قيمة ابتدائية مباشرة ولا يمكن أبداً تعديلها وإن محاولة تعديلها سيظهر خطأ Compiler Error . • تذكر دائماً أن بعد المصفوفة هو ثابت سواء كان متحول تم التصريح عنه على أنه const أو كان قيمة عددية ثابتة.

  42. الحجز الديناميكيباستخدام المؤشراتDynamic AllocationUsing Pointers

  43. ما هو الحجز الديناميكي ؟ نحن معتادون على الحجز الستاتيكي في الذاكرة static allocation . حيث أن أبعاد المصفوفة هو ثابت يكون معروف مسبقاً وبالتالي هنا يتم الحجز في الذاكرة أثناء مرحلة الـCompiling . إذا أردنا أن يكون حجم المصفوفة متغير أي أنه غير معروف مسبقاً فإننا سنلجأ لاستخدام الحجز الديناميكي dynamic allocation وهنا يتم الحجز في الذاكرة أثناء مرحلة الـRuntime .

  44. متى نستخدم الحجز الديناميكي ؟ عندما نقوم بإنشاء أغراض أثناء الـRuntime . عندما نقوم بإنشاء مصفوفات بأبعاد غير معروفة مسبقاً حيث يتم معرفة حجم المصفوفة أثناء التنفيذ فمثلاً قد يدخل المستخدم حجم المصفوفة من لوحة المفاتيح . الحجز الديناميكي يُمكننا من التعامل مع الذاكرة بشكل أقرب حيث يمكننا أن نحرر ما تم حجزه في الذاكرة أثناء الـRuntime قبل الانتهاء من تنفيذ البرنامج .

  45. الحجز في الذاكرة Memory Allocation : • إذاً هناك نوعين للحجز في الذاكرة : • الحجز الستاتيكيstatic allocation: • يتم تعريف المتحول عند التصريح عنه مثلاً int x = 3 . • يتم إزالة المتحول بعد الخروج من مجاله أي بعد الخروج من Local Block. • الحجز الديناميكي dynamic allocation)ويتم باستخدام المؤشرات(: • يتم تعريف المتحول عن طريق التعليمة new . • يتم إزالة المتحول عن طريق التعليمة delete .

  46. الحجز في الذاكرة Memory Allocation :

  47. التعليمة new! • إن التعليمة new متبوعة بنمط معطيات ما تقوم بالتالي : • تقوم بإنشاء مكان في الذاكرة وفقاً للنمط المذكور . • تعيد التعليمة new عنوان مكان الذاكرة السابق ، فإذا كنا نريد أن نصل إلى مكان الذاكرة الذي تم حجزه فإن يجب علينا أن نصرح على مؤشر ونجعله يشير إلى ذلك المكان في الذاكرة وبالتالي يصبح لدينا :

  48. التعليمة new! ويمكن الكتابة أيضاً على مرحلتين كما في المثال التالي : تتم عملية الحجز الديناميكية في مكان في الذاكرة يدعى heap الكومة . عند التصريح عن التعليمة أي حجز مكان في الكومة بحجم أربعة بايتات ، فإذا كان هناك متسع في الذاكرة بهذا الحجم تتم عملية الحجز بنجاح وترد التعليمة new عنوان مكان الذاكرة الذي تم به الحجز ، وإلا فإن قيمة المؤشر تكون NULL أي أن المؤشر لا يشير إلى شيء .

  49. مثال (1) عن التعليمة new : في المثال السابق تم حجز مكان في الذاكرة للنمط integer وتم إنشاء مؤشر اسمه p وجعلنا p يشير إلى ذلك المكان في الذاكرة من دون أن نضع قيمة ابتدائية في ذلك المكان في الذاكرة وهذا هو الاستخدام الأول للتعليمة new .

  50. مثال (2) عن التعليمة new : في المثال السابق تم حجز مكان في الذاكرة للنمط integer وتم إنشاء مؤشر اسمه p وجعلنا p يشير إلى ذلك المكان في الذاكرة ، وتم وضع القيمة 5 في ذلك المكان في الذاكرة وهذا هو الاستخدام الثاني للتعليمة new .

More Related