C++ المؤشرات مع الأمثلة

⚡ ملخص ذكي

مؤشر في C++ المؤشر هو متغير يخزن عنوان الذاكرة لمتغير آخر. ستتعلم هنا كيفية عمل المؤشرات، وكيفية تعريفها واستخدامها، ومعاملات الإشارة وفك الإشارة، والمؤشرات الفارغة، ومزاياها.

  • 📍 ما هو : يخزن المؤشر عنوان الذاكرة لمتغير آخر.
  • 🔧 إعلان: قم بتعريف مؤشر باستخدام علامة النجمة، مثل int *ptr;.
  • 🔗 Operaتورس: استخدم & للحصول على عنوان و * للوصول إلى القيمة الموجودة فيه.
  • 🚫 باطل: يشير المؤشر الفارغ إلى لا شيء ويستخدم للتهيئة الآمنة.
  • 🤖 مساعدة الذكاء الاصطناعي: تقوم أدوات الذكاء الاصطناعي مثل GitHub Copilot بكتابة وتصحيح كود المؤشر على الفور.

C++ Pointers

ما هي المؤشرات؟

In C++يشير المؤشر إلى متغير يحمل عنوان متغير آخر. مثل المتغيرات العادية، تحتوي المؤشرات على نوع بيانات. على سبيل المثال، يمكن لمؤشر من النوع عدد صحيح أن يحمل عنوان متغير من النوع عدد صحيح. يمكن لمؤشر نوع الحرف أن يحمل عنوان متغير نوع الحرف.

يجب أن ترى المؤشر كتمثيل رمزي لعنوان الذاكرة. باستخدام المؤشرات، يمكن للبرامج محاكاة الاستدعاء حسب المرجع. يمكنهم أيضًا إنشاء ومعالجة هياكل البيانات الديناميكية. في C++يشير متغير المؤشر إلى متغير يشير إلى عنوان محدد في الذاكرة يشير إليه متغير آخر.

العناوين في C++

لفهم C++ المؤشرات، يجب أن تفهم كيف تقوم أجهزة الكمبيوتر بتخزين البيانات.

عندما تقوم بإنشاء متغير في الخاص بك C++ البرنامج، يتم تخصيص بعض المساحة في ذاكرة الكمبيوتر. يتم تخزين قيمة هذا المتغير في الموقع المخصص.

لمعرفة الموقع في ذاكرة الكمبيوتر حيث يتم تخزين البيانات، C++ يوفر & عامل (مرجع). يقوم هذا العامل بإرجاع العنوان الذي يشغله المتغير.

على سبيل المثال، إذا كان x متغيرًا، فسيُرجع &x عنوان المتغير.

بناء جملة إعلان المؤشر

إعلان C++ يأخذ بناء الجملة التالي:

datatype *variable_name; 
  • نوع البيانات هو النوع الأساسي للمؤشر الذي يجب أن يكون صالحًا C++ نوع البيانات.
  • يجب أن يكون اسم المتغير هو اسم متغير المؤشر.
  • إن علامة النجمة المستخدمة أعلاه لإعلان المؤشر تشبه علامة النجمة المستخدمة لإجراء عملية الضرب. إنها علامة النجمة التي تميز المتغير كمؤشر.

فيما يلي مثال لإعلانات المؤشر الصالحة في C++:

int    *x;    // a pointer to integer
double *x;    // a pointer to double
float  *x;    // a pointer to float
char   *ch     // a pointer to a character

عامل المرجع (&) وعامل التأخير (*)

يقوم عامل المرجع (&) بإرجاع عنوان المتغير.

يساعدنا عامل إلغاء المرجع (*) في الحصول على القيمة المخزنة في عنوان الذاكرة.

فمثلا:

إذا كان لدينا متغير اسمه num، فسيتم تخزينه في العنوان 0x234 وتخزين القيمة 28.

سوف يقوم عامل المرجع (&) بإرجاع 0x234.

سوف يقوم عامل إلغاء المرجع (*) بإرجاع القيمة 5.

مثال 1:

#include <iostream>
using namespace std;
int main() {
	int  x = 27;  
	int  *ip;        
	ip = &x;       
	cout << "Value of x is : ";
	cout << x << endl;
	cout << "Value of ip is : ";
	cout << ip<< endl;
	cout << "Value of *ip is : ";
	cout << *ip << endl;
	return 0;
}

الإخراج:

عامل المرجع (&) وعامل التأخير (*)

كيف يعمل هذا:

عامل المرجع (&) وعامل التأخير (*)

فيما يلي لقطة شاشة للكود:

عامل المرجع (&) وعامل التأخير (*)

Code التفسير:

  1. قم باستيراد ملف رأس iostream. سيسمح لنا ذلك باستخدام الوظائف المحددة في ملف الرأس دون حدوث أخطاء.
  2. قم بتضمين مساحة الاسم std لاستخدام فئاتها دون استدعائها.
  3. استدعاء الدالة الرئيسية (). يجب إضافة منطق البرنامج داخل نص هذه الوظيفة. يمثل { بداية نص الوظيفة.
  4. قم بتعريف متغير صحيح x وتخصيص قيمة له بـ 27.
  5. قم بتعريف متغير المؤشر *ip.
  6. قم بتخزين عنوان المتغير x في متغير المؤشر.
  7. طباعة بعض النص على وحدة التحكم.
  8. اطبع قيمة المتغير x على الشاشة.
  9. طباعة بعض النص على وحدة التحكم.
  10. اطبع عنوان المتغير x. تم تخزين قيمة العنوان في المتغير ip.
  11. طباعة بعض النص على وحدة التحكم.
  12. طباعة القيمة المخزنة على عنوان المؤشر.
  13. يجب أن يقوم البرنامج بإرجاع القيمة عند التنفيذ الناجح.
  14. نهاية نص الدالة main().

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

تعمل المصفوفات والمؤشرات بناءً على مفهوم ذي صلة. هناك أشياء مختلفة يجب ملاحظتها عند العمل مع المصفوفات التي تحتوي على مؤشرات. يشير اسم المصفوفة نفسه إلى العنوان الأساسي للمصفوفة. هذا يعني أنه لتعيين عنوان مصفوفة لمؤشر، يجب عدم استخدام علامة العطف (&).

فمثلا:

p = arr;

ما ورد أعلاه صحيح لأن arr يمثل عنوان المصفوفات. هنا مثال آخر:

p = &arr;

ما ورد أعلاه غير صحيح.

يمكننا ضمنيًا تحويل المصفوفة إلى مؤشر. على سبيل المثال:

int arr [20];
int * ip;

فيما يلي عملية صالحة:

ip = arr;

بعد الإعلان أعلاه، سيكون ip وarr متكافئين، وسيتشاركان في الخصائص. ومع ذلك، يمكن تعيين عنوان مختلف لـ ip، لكن لا يمكننا تعيين أي شيء للوصول إليه.

مثال 2:

يوضح هذا المثال كيفية اجتياز مصفوفة باستخدام المؤشرات:

#include <iostream>
using namespace std;
int main() {
	int *ip;
	int arr[] = { 10, 34, 13, 76, 5, 46 };
	ip = arr;
	for (int x = 0; x < 6; x++) {
		cout << *ip << endl;
		ip++;
	}
	return 0;
}

الإخراج:

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

فيما يلي لقطة شاشة للكود:

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

Code التفسير:

  1. قم بتعريف متغير مؤشر عدد صحيح IP.
  2. قم بتعريف مصفوفة باسم arr وقم بتخزين 6 أعداد صحيحة فيها.
  3. تعيين آر إلى الملكية الفكرية. سيصبح ip وarr متساويين.
  4. إنشاء حلقة. تم إنشاء متغير الحلقة x للتكرار على عناصر المصفوفة من الفهرس 0 إلى 5.
  5. اطبع القيم المخزنة على عنوان IP الخاص بالمؤشر. سيتم إرجاع قيمة واحدة لكل تكرار، وسيتم إجراء ما مجموعه 6 تكرارات. النهاية هي أ C++ الكلمة الأساسية التي تعني خط النهاية. يتيح لك هذا الإجراء تحريك المؤشر إلى السطر التالي بعد طباعة كل قيمة. ستتم طباعة كل قيمة في سطر فردي.
  6. لتحريك المؤشر إلى موضع int التالي بعد كل تكرار.
  7. نهاية للحلقة.
  8. يجب أن يقوم البرنامج بإرجاع شيء ما عند التنفيذ الناجح.
  9. نهاية نص الوظيفة الرئيسية ().

مؤشر فارغ

إذا لم يكن هناك عنوان محدد ليتم تعيينه، فيمكن تعيين قيمة NULL لمتغير المؤشر. يجب أن يتم ذلك أثناء الإعلان. يُعرف هذا المؤشر بمؤشر فارغ. قيمته صفر ويتم تعريفه في العديد من المكتبات القياسية مثل iostream.

مثال 3:

#include <iostream>
using namespace std;
int main() {
	int  *ip = NULL;
	cout << "Value of ip is: " << ip;
	return 0;
}

الإخراج:

مؤشر فارغ

فيما يلي لقطة شاشة للكود:

مؤشر فارغ

Code التفسير:

  1. قم بتعريف متغير المؤشر ip وتعيين قيمة NULL له.
  2. اطبع قيمة متغير المؤشر ip بجانب بعض النص على وحدة التحكم.
  3. يجب أن يقوم البرنامج بإرجاع القيمة عند اكتماله بنجاح.
  4. نهاية نص الدالة main().

مؤشرات المتغيرات

مع C++يمكنك معالجة البيانات مباشرة من ذاكرة الكمبيوتر.

يمكن تخصيص مساحة الذاكرة أو إعادة تخصيصها حسب رغبة الشخص. أصبح هذا ممكنًا بواسطة متغيرات المؤشر.

تشير متغيرات المؤشر إلى عنوان محدد في ذاكرة الكمبيوتر يشير إليه متغير آخر.

ويمكن إعلانها على النحو التالي:

int *p;

أو،

int* p;

في المثال you، قمنا بتعريف متغير المؤشر p.

وسوف تحمل عنوان الذاكرة.

العلامة النجمية هي عامل إلغاء المرجع الذي يعني مؤشرًا إلى.

يشير المؤشر p إلى قيمة عددية في عنوان الذاكرة.

مثال 4:

#include <iostream>

using namespace std;
int main() {
	int *p, x = 30;
	p = &x;
	cout << "Value of x is: " << *p;
	return 0;
}

الإخراج:

مؤشرات المتغيرات

فيما يلي لقطة شاشة للكود:

مؤشرات المتغيرات

Code التفسير:

  1. قم بتعريف متغير المؤشر p ومتغير x بقيمة 30.
  2. قم بتعيين عنوان المتغير x إلى p.
  3. اطبع قيمة متغير المؤشر p بجانب بعض النصوص على وحدة التحكم.
  4. يجب أن يقوم البرنامج بإرجاع القيمة عند اكتماله بنجاح.
  5. نهاية نص الدالة main().

تطبيق المؤشرات

وظائف في C++ لا يمكن إرجاع سوى قيمة واحدة. علاوة على ذلك، يتم تخصيص جميع المتغيرات المعلنة في الدالة على مكدس استدعاء الدالة. بمجرد إرجاع الدالة، يتم تدمير جميع متغيرات المكدس.

يتم تمرير الوسائط إلى الدالة بالقيمة، وأي تعديل يتم إجراؤه على المتغيرات لا يغير قيمة المتغيرات الفعلية التي يتم تمريرها. يساعد المثال التالي في توضيح هذا المفهوم:

مثال 5:

#include <iostream>

using namespace std;
void test(int*, int*);
int main() {
	int a = 5, b = 5;
	cout << "Before changing:" << endl;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	test(&a, &b);

	cout << "\nAfter changing" << endl;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	return 0;
}

void test(int* n1, int* n2) {
	*n1 = 10;
	*n2 = 11;
}

الإخراج:

تطبيق المؤشرات

فيما يلي لقطة شاشة للكود:

تطبيق المؤشرات

Code التفسير:

  1. قم بإنشاء نموذج أولي لدالة تسمى test والتي ستأخذ معلمتين صحيحتين.
  2. استدعاء الدالة الرئيسية (). سنضيف منطق البرنامج داخل جسمه.
  3. قم بتعريف متغيرين صحيحين a وb، قيمة كل منهما 5.
  4. طباعة بعض النص على وحدة التحكم. سيحرك endl (خط النهاية) المؤشر لبدء الطباعة في السطر التالي.
  5. اطبع قيمة المتغير a على وحدة التحكم بجانب النص الآخر. سيحرك endl (خط النهاية) المؤشر لبدء الطباعة في السطر التالي.
  6. اطبع قيمة المتغير b على وحدة التحكم بجانب النص الآخر. سيحرك endl (خط النهاية) المؤشر لبدء الطباعة في السطر التالي.
  7. قم بإنشاء دالة باسم test() والتي تأخذ عناوين المتغير a وb كمعلمات.
  8. طباعة بعض النص على وحدة التحكم. سيقوم \n بإنشاء سطر فارغ جديد قبل طباعة النص. سيحرك endl (خط النهاية) المؤشر لبدء الطباعة في السطر التالي بعد طباعة النص.
  9. اطبع قيمة المتغير a على وحدة التحكم بجانب النص الآخر. سيحرك endl (خط النهاية) المؤشر لبدء الطباعة في السطر التالي.
  10. اطبع قيمة المتغير b على وحدة التحكم بجانب النص الآخر. سيحرك endl (خط النهاية) المؤشر لبدء الطباعة في السطر التالي.
  11. يجب أن يقوم البرنامج بإرجاع القيمة عند اكتماله بنجاح.
  12. نهاية نص الدالة main().
  13. تحديد اختبار الوظيفة (). يجب أن تأخذ الدالة متغيرين صحيحين للمؤشر *n1 و*n2.
  14. تعيين متغير المؤشر *n1 بقيمة 10.
  15. تعيين متغير المؤشر *n2 بقيمة 11.
  16. نهاية نص اختبار الوظيفة ().

على الرغم من أنه تم تعيين قيم جديدة للمتغيرين a وb داخل اختبار الوظيفة، بمجرد اكتمال استدعاء الوظيفة، فإن نفس الشيء لا ينعكس في الوظيفة الخارجية الرئيسية.

يساعد استخدام المؤشرات كوسائط دالة على تمرير العنوان الفعلي للمتغير في الوظيفة، وستنعكس جميع التغييرات التي يتم إجراؤها على المتغير في الوظيفة الخارجية.

في الحالة المذكورة أعلاه، تحتوي الدالة "test" على عنوان المتغيرين "a" و"b". يمكن الوصول إلى هذين المتغيرين مباشرة من خلال الدالة "test"، وبالتالي فإن أي تغيير يتم إجراؤه على هذه المتغيرات ينعكس في الدالة المستدعية "main".

مزايا استخدام المؤشرات

فيما يلي إيجابيات/فوائد استخدام المؤشرات

  • المؤشرات هي المتغيرات التي تخزن عنوان الآخرين المتغيرات في C++.
  • يمكن تعديل أكثر من متغير وإرجاعه بواسطة الدالة باستخدام المؤشرات.
  • يمكن تخصيص الذاكرة وإلغاء تخصيصها ديناميكيًا باستخدام المؤشرات.
  • تساعد المؤشرات في تبسيط تعقيد البرنامج.
  • تتحسن سرعة تنفيذ البرنامج باستخدام المؤشرات.

الأسئلة الشائعة

المؤشر هو متغير يخزن عنوان الذاكرة لمتغير آخر. فبدلاً من تخزين قيمة مباشرة، فإنه يخزن الموقع الذي تُحفظ فيه تلك القيمة في الذاكرة.

قم بتعريف مؤشر عن طريق وضع علامة النجمة (*) بين نوع البيانات والاسم، مثل int *ptr;. هذا يُنشئ مؤشرًا يمكنه تخزين عنوان عدد صحيح (int).

يقوم عامل الإشارة & بإرجاع عنوان الذاكرة لمتغير، ويقوم عامل فك الإشارة * بالوصول إلى القيمة المخزنة في العنوان الذي يحمله المؤشر.

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

يعمل اسم المصفوفة كمؤشر إلى العنصر الأول فيها، لذا يمكنك استخدام حساب المؤشرات للتنقل عبر عناصر المصفوفة بدلاً من استخدام أرقام الفهرس.

تقوم المساعدات الذكية مثل GitHub Copilot بإنشاء تعريفات المؤشرات، وكتابة العمليات الحسابية للمؤشرات، ووضع علامات على استخدام المؤشرات المعلقة أو الفارغة التي قد تتسبب في تعطل برنامجك.

نعم. تقوم الأدوات المدعومة بالذكاء الاصطناعي باكتشاف تسريبات الذاكرة والمؤشرات المعلقة وعمليات إلغاء المراجع الفارغة، وتقترح مؤشرات ذكية مثل unique_ptr لإدارة الذاكرة بشكل أكثر أمانًا.

تتيح المؤشرات الوصول المباشر إلى الذاكرة، والتعامل الفعال مع المصفوفات والسلاسل النصية، وتخصيص الذاكرة الديناميكي، وتمرير البيانات الكبيرة إلى الدوال دون نسخها.

تلخيص هذه التدوينة بـ: