You are on page 1of 10

‫برمجة تراكيب البيانات‬

‫المحاضرة الثانية‬
‫‪Pointers‬‬ ‫المؤشرات‬

‫المؤشرات ‪Pointers‬‬
‫‪ o‬تعد ادلؤشرات من أىم وأقوى اخلصائص ادلتوفرة يف لغة ‪ C++‬وىي اليت متيز ىذه اللغة عن باقي لغات الربرلة‪.‬‬

‫‪ o‬تكمن فائدة استخدام ادلؤشرات يف الربرلة عموماَ يف‪:‬‬

‫‪.a‬إمكانية التعامل مع ادلتغًنات بالعناوين أي عناوينها يف الذاكرة بشكل مباشر‪.‬‬

‫‪.b‬الوصول إىل عناصر ادلصفوفة ‪.‬‬

‫‪.c‬مترير ادلعامالت إىل دالة باستخدام العنوان (‪. )Passing By Reference‬‬

‫‪ .d‬إمكانية استحداث واستخدام تراكيب بيانات ديناميكية‪ ،‬أي تراكيب بيانات متغًنة ميكن ذلا أن تنمو أو‬

‫تتقلص أثنـاء تنفيذ الربنامج مثل القوائم ادلتصلة )‪ (Linked Lists‬والطوابًن )‪(Queues‬‬

‫وادلكدسات )‪ (Stacks‬وكذلك األشجار )‪.(Trees‬‬

‫أو يمكن القول باختصار‬

‫أن ادلؤشرات تستخدم يف الربامج اليت حنتاج فيها إىل حجز وإلغاء حجز الذاكرة أثناء تنفيذ الربنامج ‪.‬‬

‫تعريف المؤشر ‪-:‬‬


‫ىو عبارة عن موقع يف الذاكرة حيمل عنوان موقع آخر وبالتايل ميكن أن نقول أن ادلوقع األول عبارة عن‬
‫مؤشر يؤشر إىل ادلوقع اآلخر ‪.‬‬
‫‪X‬‬ ‫‪Y‬‬
‫‪address of Y‬‬

‫‪ X‬تؤشر إىل ‪Y‬‬

‫‪1‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬


‫برمجة تراكيب البيانات‬
‫اإلعالن عن المؤشرات‬
‫‪ ‬مثل بقية ادلتغًنات جيب التصريح عن ادلؤشرات قبل استخدامها‪ ،‬ويتم التصريح عن ادلؤشر بوضع إشارة * قبل‬
‫اسم ادلؤشر‪.‬‬
‫‪ ‬ميكن أن يتم التصريح عن ادلؤشر ليؤشر على قيمة أو متغًن من أي نوع من أنواع البيانات األساسية يف‬
‫لغة‪C++‬‬
‫الصيغة العامة لإلعالن عن المؤشر‬
‫‪data type‬‬ ‫; ‪*pointer name‬‬
‫حيث ‪-:‬‬
‫‪ data type‬ىي نوع البيانات اليت يشًن إليها ادلؤشر‬
‫‪ pointer name‬ىو اسم ادلؤشر ‪.‬‬

‫أمثلة ‪:‬‬
‫;‪1. int * p‬‬
‫إعالن عن مؤشر يشًن إىل متغًن من النوع الصحيح ‪.‬‬

‫;‪2. int i,j,a[10],b[2]*p,*q‬‬

‫إعالن عن رلموعة من ادلتغًنات وادلصفوفات وادلؤشرات من النوع الصحيح ‪.‬‬


‫;‪3. float *q‬‬
‫إعالن عن مؤشر يشًن إىل متغًن من النوع احلقيقي ‪.‬‬
‫;‪4. char *r‬‬
‫إعالن عن مؤشر يشًن إىل متغًن من النوع احلريف‪.‬‬
‫‪5. float *m, *n‬‬
‫إعالن عن مؤشرين باسم ‪ m,n‬ليؤشرا على قيمتٌن حقيقيتٌن‪.‬‬

‫عند إسناد قيمة أو متغًن إىل مؤشر جيب أن تكون ىذه القيمة أو ادلتغًن من نفس نوع‬
‫‪‬‬
‫بيانات ادلؤشر وغًن ذلك يؤدي إىل خطأ قواعدي يف الربنامج‬

‫‪2‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬


‫برمجة تراكيب البيانات‬
‫معامل العنوان (&) ومعامل المحتوى (*)‬
‫مع ادلؤشرات يتم استخدام أداتان مهمتان يف لغة ‪ C++‬ومها‬
‫‪ .1‬األداة & واليت تستخدم إلعطاء عنوان متغًن يف الذاكرة على سبيل ادلثال‬
‫;‪mem=&x‬‬
‫فإذا كان ادلتغًن ‪ x‬واقعاً يف ادلوقع ‪ 1111‬من الذاكرة وكانت قيمة ‪ x‬يف ادلوقع ىي ‪ 3‬فإن مجلة التعيٌن‬
‫السابقة تعطي ادلتغًن ‪ mem‬يف موقعو القيمة ‪ 1111‬وىي عنوان ‪ x‬يف الذاكرة وعليو فإن معىن اجلملة‬
‫] ‪ [mem=&x‬ىو أعطى ادلتغًن ‪ mem‬يف موقعو عنوان ‪. x‬‬

‫‪ .2‬األداة * واليت تستخدم إلعطاء قيمة ادلتغًن للمؤشر ( ادلشار إليو) أي قيمة ‪ x‬يف ادلثال السابق ‪.‬‬
‫وادلثال التايل يوضح العملية كما يلي ‪:‬‬
‫;‪y=*mem‬‬
‫ويف ىذه احلالة تكون القيمة ادلخزنة يف موقع ادلتغًن ‪ y‬ىي قيمة ‪ x‬نفسها أي ‪ 3‬أي يصبح معىن اجلملة ىو أعطى ‪y‬‬
‫القيمة ادلخزنة لدى موقع ادلؤشر ‪mem‬‬
‫ولإليضاح أكثر نأخذ المثال التالي ‪:‬‬
‫لنفرض‬
‫;‪int i,*p‬‬
‫;‪p=&i‬‬
‫وعليو فيوضع عنوان ‪ i‬يف ادلؤشر ‪ p‬فإن ىذا ادلؤشر سوف يشًن إىل ادلتغًن ‪i‬‬

‫‪0‬‬ ‫?‬ ‫كما يلي ‪:‬‬

‫‪p‬‬ ‫‪i‬‬

‫إن وضع عنوان ‪ i‬يف ادلؤشر ‪ p‬مل يؤثر على زلتوى ادلوقع ادلخصص للمتغًن ‪i‬‬
‫وميكن وضع العنوان يف ادلؤشر أثناء اإلعالن كما يلي ‪:‬‬
‫;‪int i‬‬
‫;‪int *p=&i‬‬

‫‪3‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬


‫برمجة تراكيب البيانات‬
‫بعد أن يشًن ادلؤشر إىل ادلتغًن ميكن الوصول إىل القيمة ادلخزنة يف العنوان باستخدام معامل احملتوى (*) فإذا كانت ‪p‬‬
‫تشًن إىل ادلتغًن ‪ i‬فانو باإلمكان طباعة زلتوى ادلوقع (قيمة ‪ )i‬كما يلي ‪:‬‬
‫;‪cout<<*p‬‬
‫ومادامت ‪ p‬تشًن اىل ‪ i‬فإن ‪ *p‬ىي نفسها قيمة ‪( i‬وكأنو اسم مرادف ل ـ ‪) i‬‬
‫انظر الشكل التالي ‪:‬‬
‫‪p‬‬ ‫‪0‬‬ ‫?‬
‫;‪p=&i‬‬

‫‪p‬‬ ‫‪1‬‬ ‫‪1‬‬


‫;‪i=l‬‬

‫‪cout<<i ; // print 1‬‬


‫‪cout<<*p; // print 1‬‬
‫متتلك لغة ‪ C++‬ادلقدرة على نسخ ادلؤشرات (على أن تكون من نفس النوع ) باستخدام أمر ادلساواة‬
‫فلو فرضنا أن ‪ q,p,j,i‬مت اإلعالن عنها كما يلي ‪:‬‬

‫‪int i,j,*p,*q‬‬

‫فإن اجلملة التالية تضع عنوان ادلتغًن ‪ i‬يف ادلؤشر ‪p‬‬


‫;‪P=&i‬‬
‫واستخدام التعليمة التالية‬
‫;‪q=p‬‬

‫سيؤدي إىل أن تشًن ادلؤشرات إىل ادلتغًن ‪ i‬كما يلي‬


‫‪0‬‬ ‫‪p‬‬

‫‪q‬‬ ‫?‬

‫‪0‬‬
‫‪i‬‬

‫بعد ذلك ميكن إعطاء ادلتغًن قيم باستخدام ادلؤشر كما يلي ‪:‬‬

‫‪4‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬


‫برمجة تراكيب البيانات‬
‫;‪*p=1‬‬

‫‪1‬‬ ‫‪p‬‬

‫‪q‬‬ ‫‪1‬‬

‫‪1‬‬
‫‪i‬‬

‫;‪*q =2‬‬

‫‪2‬‬ ‫‪p‬‬

‫‪q‬‬ ‫‪2‬‬

‫‪2‬‬
‫‪i‬‬

‫تأخذ األداتان & و* أولوية يف التنفيذ على سائر العمليات (ادلؤثرات) ادلختلفة‬
‫‪‬‬

‫مثال‪ :1‬يوضح كيفية نسخ ادلؤشرات ‪:‬‬


‫>‪#include <iostream.h‬‬
‫)(‪int main‬‬
‫{‬
‫;‪int i =5‬‬
‫;‪int *p,*q‬‬
‫;‪p=&i‬‬
‫;‪*p = i**p‬‬
‫;‪q = p‬‬
‫;‪*q =*q+*p‬‬
‫;"‪cout<<" i= "<<i<<" \n‬‬
‫;"‪cout<<" *p= "<<*p<<" \n‬‬
‫;"‪cout<<" *q= "<<*q<<" \n‬‬
‫;‪return 0‬‬
‫}‬

‫‪5‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬


‫برمجة تراكيب البيانات‬
‫مثال‪:2‬‬
‫تتبع الربنامج التايل ‪ ،‬و حاول أن تستنتج شكل ادلخرجات‬
‫>‪#include <iostream.h‬‬
‫)( ‪int main‬‬
‫{‬
‫;‪int value1 = 5, value2 = 15‬‬
‫;‪int* p1‬‬
‫;‪int* p2‬‬
‫;‪p1 = &value1‬‬
‫;‪p2 = &value2‬‬
‫;‪*p1 = 10‬‬
‫;‪*p2 = *p1‬‬
‫;‪p1 = p2‬‬
‫;‪*p1 = 20‬‬
‫;‪cout << "value1==" <<value1<<"\t value2=="<< value2<<endl‬‬
‫;‪return 0‬‬
‫}‬
‫العمليات الحسابية على المؤشرات‪:‬‬
‫تستطيع ادلؤشرات اإلشارة إىل ادلتغًنات ادلفردة كما وتشًن إىل عناصر ادلصفوفة ‪array‬‬
‫لنفرتض أن ‪ a,p‬عرفت كما يلي‪:‬‬
‫;‪int a[10],*p‬‬
‫فبهذا ميكن استخدام ادلؤشر ‪ p‬لإلشارة إىل العنصر األول من ادلصفوفة ‪) a[0] ( a‬‬
‫كما يلي‪:‬‬
‫;‪p=a‬‬ ‫وىي مكافئة للعبارة‬ ‫;]‪p=&a[0‬‬

‫‪p‬‬
‫أي‬

‫‪a‬‬

‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬

‫وهبذا ميكن الوصول إىل ]‪ a[0‬عن طريق ‪ p‬وبإمكاننا ختزين القيمة ‪ 5‬على سبيل ادلثال كعنصر يف ادلوقع األول‬
‫من ادلصفوفة كما يلي‪:‬‬
‫;‪*p=5‬‬
‫‪6‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬
‫برمجة تراكيب البيانات‬
‫‪p‬‬ ‫فيصبح الشكل كما يلي‪:‬‬

‫‪a‬‬ ‫‪5‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬

‫يعترب اسم ادلصفوفة مؤشر ثابت على أول عنصر من عناصرىا‬ ‫‪‬‬

‫يمكن تنفيذ ثالث عمليات حسابية أساسية على المؤشر وهي‪:‬‬


‫‪ .1‬زيادة رقم صحيح إىل ادلؤشر‪.‬‬
‫‪ .2‬طرح رقم صحيح من ادلؤشر‪.‬‬
‫‪ .3‬طرح مؤشر من مؤشر‪.‬‬
‫لنفرتض التعريف التايل‪:‬‬
‫;‪int a[10],*p,*q‬‬
‫فإذا كان ادلؤشر ‪ p‬يشًن إىل ]‪ a[i‬فإن زيادة ‪ j‬إىل ادلؤشر تعين أن ادلؤشر سوف يشًن إىل العنصر ]‪a[i+j‬‬
‫وميكن توضيح العملية كما يلي‪:‬‬
‫;]‪p=&a[2‬‬ ‫‪p‬‬

‫‪a‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬
‫;‪q=p+3‬‬ ‫إذا جعلنا‬
‫‪p‬‬
‫فهذا يعين‪:‬‬
‫‪q‬‬
‫‪p‬‬ ‫‪p‬‬

‫‪a‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬
‫;‪p+=6‬‬ ‫إذا جعلنا‬

‫‪7‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬


‫برمجة تراكيب البيانات‬
‫فهذا يعين‪:‬‬
‫‪p‬‬ ‫‪p‬‬
‫‪p‬‬ ‫‪p‬‬

‫‪a‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬

‫أما عملية الطرح من ادلؤشر فيمكن توضيحها بالشكل التايل‪:‬‬


‫;]‪p=&a[8‬‬
‫;‪q=p-3‬‬
‫‪q‬‬ ‫‪p‬‬
‫‪p‬‬ ‫‪p‬‬

‫‪a‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬

‫كما ميكن طرح مؤشر من مؤشر آخر كما يلي‪:‬‬


‫;]‪p=&a[5‬‬
‫;]‪q=&a[1‬‬
‫;‪q=p-q‬‬
‫‪q‬‬ ‫‪p‬‬
‫‪p‬‬ ‫‪p‬‬

‫‪a‬‬
‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪7‬‬ ‫‪8‬‬ ‫‪9‬‬

‫ميكن بواسطة ادلؤشرات حساب رلموع عناصر مصفوفة‬


‫مثال ‪-:3‬‬
‫باستخدام ادلؤشرات احسب وأطبع رلموع عناصر مصفوفة حجمها عشرة عناصر تستخدم لتخزين بيانات‬
‫من النوع الصحيح‬
‫>‪#include <iostream.h‬‬
‫)(‪int main‬‬
‫{‬
‫;‪int a[10],sum,*p,i‬‬
‫;‪sum=0‬‬
‫‪8‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬
‫برمجة تراكيب البيانات‬
for(i=0;i<10;i++)
{
cout<<"enter a["<<i+1<<"]:";
cin>>a[i];
}
for(p=&a[0];p<&a[10];p++)
sum+=*p;
cout<<"sum="<<sum<<endl;
return 0;
}
-:4 ‫مثال‬
:‫يوضح استخدام ادلؤشرات مع ادلصفوفات‬
#include<iostream.h>
int main()
{
int a[5]={5,10,15,20,25};
int *p;
p=a; //p=&a[0];
cout<<"the first method to print array elements \n";
for(int i=0;i<5;i++)
cout<<*(p+i)<<"\t";
cout<<"\n";
cout<<"the second method to print array elements\n";
for(p=a;p<&a[5];p++)
cout<<*p<<"\t";
cout<<"\n";
return 0;
}
pointers to pointers ‫مؤشرات المؤشرات‬
:‫عند اعتبارنا ادلؤشر كمتغًن فإنو ميكننا أن نشًن لو مبؤشر آخر‬
‫ تأشًن منفرد‬.1
‫المؤشر‬ ‫المتغير‬

‫عنوان المتغير‬ ‫قيمة المتغير‬

9 ‫حذيفة عبد الرحمن‬/‫إعداد األستاذ‬


‫برمجة تراكيب البيانات‬
‫‪ .2‬تأشًن زوجي‬
‫مؤشر ثاني‬ ‫مؤشر أول‬ ‫المتغير‬

‫عنوان المؤشر األول‬ ‫عنوان المتغير‬ ‫قيمة المتغير‬

‫;‪int **p‬‬ ‫ويتم اإلعالن عن مؤشر ادلؤشر بالشكل التايل‬


‫وىو مؤشر دلؤشر من نوع عددي صحيح‬

‫مثال‪-:5‬‬
‫>‪#include<iostream.h‬‬
‫)(‪int main‬‬
‫{‬
‫;‪int v,*a,**b‬‬
‫;‪v=20‬‬
‫;‪a=&v‬‬
‫;‪b=&a‬‬
‫;‪cout<<"**b="<<**b<<endl‬‬
‫;‪return 0‬‬
‫}‬

‫‪11‬‬ ‫إعداد األستاذ‪/‬حذيفة عبد الرحمن‬

You might also like