الفرق بين المصفوفات والمؤشرات .. في لغة سي ++ .. مقالة توضح امورا دائما يخطأ بها المبرمجون ...

الناقل : elmasry | الكاتب الأصلى : سنان محمد صالح | المصدر : www.arabteam2000-forum.com

بسم الله الرحمن الرحيم

قرأت ورأيت كثيرا ممن يعتبر ان المصفوفات هي مؤشرات .. او ان المصفوفة بحد ذاتها هي مؤشر ..
تقنيا .. هذا الامر خاطئ ..لايوجد شئ في عالم البرمجة اسمه المصفوفة هي مؤشر ..
اذا ماهي المصفوفة ..؟؟
المصفوفة هي اي متغير في لغة السي او السي ++ .. ميزتها التي تفرق انها متغير ولكن تحت اسمها عدة متغيرات ..
لنأخذ المثال التالي ..

int arr[3]={3,4,5};
cout<<arr;

ماهو اخراج هذا الكود .. ؟؟
بالتأكيد الاخراج سيكون عنوان ...
ولكن عنوان .. قلنا عنوان .. ولم نقل مؤشر .. وهذا فرق كبير بين العنوان والمؤشر ..
ولكن انت ستقول بما انه طبعنا اسم المصفوفة فقط كانت النتيجة عنوان اذا اسم المصفوفة سيكون مؤشرا ..

ولكن هذا امر خاطئ .. والدليل .. لو اخذنا الكود التالي ..
int var;
cout<<&var;


هذا الكود سيطبع ايضا عنوان .. ولكن عنوان المتغير .. والعنوان لن يطبع الا باستخدام عامل العنونة & .. اما لو كان الكود بهذه الصيغة ..
int var;
cout<<var;


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

int* ptr=&intvar;


فالمتغير intvar له عنوان في الذاكرة يتم التعامل معه من قبل المعالج سواء تم التأشير عليه بمؤشر ام لا ..

ومن ما قلته اعلاه ..
المصفوفة هي شئ مشابه للمتغيرات .. فقط هي مجموعه من متغيرات .. تكون هذه المتغيرات من نفس النوع جميعها ..
ولكن هناك قاعدة مهمه .. وهي ان السي++ تنظر الى المصفوفة باسمها (اي عندما نكتب arr ققط) على انها مؤشر لاول موقع من تلك المصفوفة ..
فالكود الاول ..

code]int arr[3]={3,4,5};
cout<<arr;
[/code]

اخراجه سيكون عنوان والعنوان هو عنوان اول موقع من المصفوفة اي ان الكود السابق يعوض عن الكود التالي ..
&arr[0]


لو كتبنا اسم المصفوفة فقط سيطبع عنوان اي انه عملية مشابهه لاستخدام عامل العنونه مع الموقع الاول من المصفوفة ..

ارجو ان يكون الحال لهنا جيد .. وكل الكلام مفهوم ..

نصل الان الى سؤال مهم ممكن ان يساله شخص يقرأ هذا الموضوع وهو ..
ما هو اخراج الكود الذي يستعمل الكود التالي ..
cout << &arr


اي انه استعمل عامل العنونه مع اسم المصفوفة ..
بالتاكيد الاخراج سيكون نفس الاخراج السابق وهو عنوان الموقع الاول من المصفوفه ..
اي انه لو استعملنا اسم المصفوفة لوحده للطباعه او اسمها مع عامل العنونه فالاخراج هو عنوان الموقع الاول منها ..
اي انه سؤشر على عنوان الموقع الاول منها ..
اي اننا نصل الى الاثبات التالي ..

إقتباس

The value of &arr and arr is the same

وهي بجميع الاحوال ..
إقتباس
address of the first element


لنأخذ المثال التالي ..

int arr[3]={3,4,5};
cout<<"First element of the array: "<<arr[0] <<endl;
cout<<"Address of the first element: "<<&arr[0] <<endl;
cout<<"Address of the array: "<<arr <<endl;
cout<<"So what is this? "<<&arr <<endl;


الاخراج سيكون كالتالي ..
اول سطر سيطبع القيمة التي في الموقع الاول .. اي انه سيطبع 3 ..
ثاني سطر سيطبع عنوان الموقع الاول ..
ثالث سطر سيطبع ايضا عنوان الموقع الاول .. اي نفس الاخراج للسطر الثاني ولكن باستعمال صيغة مختلفة ..
رابع سطر ايضا سيطبع عنوان الموقع الاول .. اي نفس اخراج السطرين الثاني والثالث ولكن باستعمال صيغة اخرى ..


لنأخذ المثال التالي ..
int arr[3]={3,4,5};
cout<<"Address of the first element: "<<&arr[0]+1 <<endl;
cout<<"Address of the array: "<<arr +1<<endl;
cout<<"So what is this? "<<&arr +1<<endl;


السطر الاول سيطبع عنوان الموقع الثاني من المصفوفه .. وهو ناتج من جمع عنوان الموقع الاول مع 1 ..
السطر الثاني سيطبع ايضا عنوان الموقع الثاني .. ولكن بصيغة مختلفه ...
السطر الثالث هنا يختلف .. لانه سيطبع اول موقع في الذاكرة بعد المصفوفة ... اي بعد انتهاء اخر موقع من هذه المصفوفة ..

بالتاكيد فيكم الان من يسال السؤال التالي ..
وهو انني كتبت قبل قليل انه عند استخدام اسم المصفوفة في الطباعة سيطبع عنوان اول موقع .. وعند استخدام اسم المصفوفة مع عامل العنونه & فانه سيطبع ايضا عنوان اول موقع .. ولكن الان لماذا اصبح هناك اختلاف عند اضافة 1 الى الاثنين ..؟؟؟
والاجابة بكل بساطة ستكون عند اضافة 1 الى &arr فانه سيطبع عنوان اول موقع بعد المصفوفه وهذا يختلف عما اذا اضفنا 1 الى arr فقط من دون استخدام عامل العنونه .. لانه عند استخدام العامل مع الاسم فانه يشير الى عنوان الموقع الاول من تلك المصفوفه وعند جمع 1 مع هذا التاشير فانه يشير الى مابعد انتهاء المصفوفة المؤشر عليها .. وهذا يختلف عند استخدام اسم المصفوفة فقط مع 1 .. لان سيطبع الموقع الثاني من تلك المصفوفة ..


امثله عن المصفوفات والمؤشرات والعلاقه بينها ..ولتوضيح ما تم ذكره اعلاه ..
المثال الاول ..
int arr[3]={1,3,4};              //Declares an array with 3 elements
int * ptr=arr;                    //Initialize pointer ptr with the address of  array arr
cout<<*(arr+2)<<endl;
cout<<*(ptr+2)<<endl;

/* output */
4
4


المثال الثاني ..
int arr[3]={1,3,4};              //Declares an array with 3 elements
int * ptr=arr;           //Initialize pointer ptr with the address of  array arr
cout<<arr[2]<<endl;
cout<<ptr[2]<<endl;

/* output */
4
4


المثال الثالث ..
int *ptr=new int[3]; 
ptr[0]=12;
ptr[2]=3;
cout<<ptr[2];

/* output */
3



المثال الرابع ..
int ar[2]={8,2};
int var1=66;
int var2=111;
int* ptarray[5];
ptarray[0]=ar;
ptarray[1]=&ar[1]; //Address of second element of array ar
ptarray[2]=&var1;
ptarray[3]=&var2;
ptarray[4]=&ar[0];
// To keep code small I use a loop
for(int i=0;i<5;i++)
        cout<<*(ptarray[i])<<endl;

/* output */
8
2
66
111
8


المثال الخامس ..
void test(char v[]);

int main(){
        char a[53];
                 //a="If a is an array, this line should generate an error";    
        test(pta);
        return 0;
}

void test(char v[]){
        v="If v is an array, this line should generate an error";
        cout<<v<<endl;
}




__________________________________________________________________________


بعد ان تقرأوا كل ما ورد اعلاه من شرح ومن اكواد .. وتفهموه وتستوعبوه .. ارجو منكم الاجابة على السؤال التالي .. وهو يتعلق بصلب الموضوع ..

لديكم الكود التالي ..
int x[4]= { 1,2,3,4};

cout << x[0]+1;


الاخراج سيكون على الشاشة .. رقم 2 ,, من اين جاء هذا الرقم ..؟؟؟؟؟


ارجو ان تكون هذه المقالة واضحه .. اردت ان اوضح شيئا لكم عن المصفوفات والمؤشرات ..
واي خطأ قد وقعت به اثناء الكتابة .. او اي تعقيب على الموضوع .. او اي شئ اخر .. مرحب به ..
والعضو الذي يرى انه فهم الموضوع ارجو ان يكتب اجابته على السؤال الذي وضعته في نهاية الشرح ..

تحياتي العطرة للجميع ..