logo

C مؤشر مزدوج (مؤشر إلى مؤشر)

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

مؤشر إلى مؤشر في ج

ويرد أدناه بناء جملة الإعلان عن مؤشر مزدوج.

 int **p; // pointer to a pointer which is pointing to an integer. 

النظر في المثال التالي.

 #include void main () { int a = 10; int *p; int **pp; p = &a; // pointer p is pointing to the address of a pp = &p; // pointer pp is a double pointer pointing to the address of pointer p printf('address of a: %x
',p); // Address of a will be printed printf('address of p: %x
',pp); // Address of p will be printed printf('value stored at p: %d
',*p); // value stoted at the address contained by p i.e. 10 will be printed printf('value stored at pp: %d
',**pp); // value stored at the address contained by the pointer stoyred at pp } 

انتاج |

 address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10 

مثال على المؤشر المزدوج C

دعونا نرى مثالاً حيث يشير أحد المؤشرات إلى عنوان مؤشر آخر.

مؤشر C إلى مثال المؤشر

كما ترون في الشكل أعلاه، p2 يحتوي على عنوان p (fff2)، وp يحتوي على عنوان المتغير الرقمي (fff4).

 #include int main(){ int number=50; int *p;//pointer to int int **p2;//pointer to pointer p=&number;//stores the address of number variable p2=&p; printf('Address of number variable is %x 
',&number); printf('Address of p variable is %x 
',p); printf('Value of *p variable is %d 
',*p); printf('Address of p2 variable is %x 
',p2); printf('Value of **p2 variable is %d 
',*p); return 0; } 

انتاج |

 Address of number variable is fff4 Address of p variable is fff4 Value of *p variable is 50 Address of p2 variable is fff2 Value of **p variable is 50 

س: ما هي مخرجات البرنامج التالي؟

 #include void main () { int a[10] = {100, 206, 300, 409, 509, 601}; //Line 1 int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; //Line 2 int **pp = p; //Line 3 pp++; // Line 4 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 5 *pp++; // Line 6 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 7 ++*pp; // Line 8 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 9 ++**pp; // Line 10 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 11 } 

توضيح

سؤال المؤشر المزدوج

في السؤال أعلاه، يتم استخدام حساب المؤشر مع المؤشر المزدوج. يتم تعريف مجموعة من 6 عناصر يتم الإشارة إليها بواسطة مجموعة من المؤشر p. تتم الإشارة إلى صفيف المؤشر p بواسطة مؤشر مزدوج pp. ومع ذلك، فإن الصورة أعلاه تعطيك فكرة موجزة عن كيفية تخصيص الذاكرة للمصفوفة a ومصفوفة المؤشر p. عناصر p هي المؤشرات التي تشير إلى كل عنصر في المصفوفة a. وبما أننا نعلم أن اسم المصفوفة يحتوي على العنوان الأساسي للمصفوفة، فإنه سيعمل كمؤشر ويمكن اجتياز القيمة باستخدام *(a)، *(a+1)، إلخ. كما هو موضح في الصورة ، يمكن الوصول إلى [0] بالطرق التالية.

  • a[0]: إنها أبسط طريقة للوصول إلى العنصر الأول في المصفوفة
  • *(a): نظرًا لأنه يخزن عنوان العنصر الأول في المصفوفة، فيمكننا الوصول إلى قيمته باستخدام مؤشر الاتجاه غير المباشر عليه.
  • *p[0]: إذا كان سيتم الوصول إلى a[0] باستخدام مؤشر p إليه، فيمكننا استخدام عامل التشغيل غير المباشر (*) على العنصر الأول من مصفوفة المؤشر p، أي *p[0].
  • **(pp): نظرًا لأن pp يخزن العنوان الأساسي لمصفوفة المؤشر، فإن *pp سيعطي قيمة العنصر الأول في مصفوفة المؤشر وهو عنوان العنصر الأول في مصفوفة الأعداد الصحيحة. **p سيعطي القيمة الفعلية للعنصر الأول في مصفوفة الأعداد الصحيحة.

عند الدخول إلى البرنامج، يعلن السطر 1 و 2 عن مجموعة الأعداد الصحيحة والمؤشر نسبيًا. يقوم السطر 3 بتهيئة المؤشر المزدوج لمصفوفة المؤشر p. كما هو موضح في الصورة، إذا كان عنوان المصفوفة يبدأ من 200 وحجم العدد الصحيح هو 2، فإن مصفوفة المؤشر ستحتوي على القيم مثل 200، 202، 204، 206، 208، 210. لنفترض أن المصفوفة العنوان الأساسي لمصفوفة المؤشر هو 300؛ يحتوي المؤشر المزدوج pp على عنوان مصفوفة المؤشر، أي 300. ويزيد السطر رقم 4 قيمة pp بمقدار 1، أي أن pp سيشير الآن إلى العنوان 302.

يحتوي السطر رقم 5 على تعبير يطبع ثلاث قيم، أي pp - p، *pp - a، **pp. فلنحسبهم كل واحد منهم.

  • pp = 302، p = 300 => pp-p = (302-300)/2 => pp-p = 1، أي سيتم طباعة 1.
  • pp = 302، *pp = 202، a = 200 => *pp - a = 202 - 200 = 2/2 = 1، أي سيتم طباعة 1.
  • ص = 302، * ص = 202، *(* ص) = 206، أي سيتم طباعة 206.

لذلك، كنتيجة للسطر 5، سيتم طباعة الإخراج 1، 1، 206 على وحدة التحكم. في السطر 6، يتم كتابة *pp++. هنا، يجب أن نلاحظ أن المعاملين الأحاديين * و ++ لهما نفس الأولوية. لذلك، وفقًا لقاعدة الترابط، سيتم تقييمها من اليمين إلى اليسار. ولذلك يمكن إعادة كتابة التعبير *pp++ كـ (*(pp++)). بما أن pp = 302 والتي ستصبح الآن 304. *pp ستعطي 204.

في السطر 7، مرة أخرى يتم كتابة التعبير الذي يطبع ثلاث قيم، أي pp-p، *pp-a، *pp. دعونا نحسب كل واحد منهم.

  • ص = 304، ص = 300 => ص - ص = (304 - 300)/2 => ص - ع = 2، أي سيتم طباعة 2.
  • pp = 304، *pp = 204، a = 200 => *pp-a = (204 - 200)/2 = 2، أي سيتم طباعة 2.
  • ص = 304، * ص = 204، *(* ص) = 300، أي سيتم طباعة 300.

ولذلك، كنتيجة للسطر 7، سيتم طباعة الإخراج 2، 2، 300 على وحدة التحكم. في السطر 8، يتم كتابة +***pp. وفقًا لقاعدة الترابط، يمكن إعادة كتابة هذا بالشكل، (++(*(pp))). نظرًا لأن pp = 304، *pp = 204، فإن قيمة *pp = *(p[2]) = 206 والتي ستشير الآن إلى a[3].

في السطر 9، مرة أخرى يتم كتابة التعبير الذي يطبع ثلاث قيم، أي pp-p، *pp-a، *pp. دعونا نحسب كل واحد منهم.

  • ص = 304، ص = 300 => ص - ص = (304 - 300)/2 => ص - ع = 2، أي سيتم طباعة 2.
  • pp = 304، *pp = 206، a = 200 => *pp-a = (206 - 200)/2 = 3، أي سيتم طباعة 3.
  • ص = 304، * ص = 206، *(* ص) = 409، أي سيتم طباعة 409.

لذلك، كنتيجة للسطر 9، سيتم طباعة الإخراج 2، 3، 409 على وحدة التحكم. في السطر 10، يتم كتابة +***pp. وفقًا لقاعدة الترابط، يمكن إعادة كتابتها بالشكل التالي: (++(*(*(pp))))). pp = 304، *pp = 206، **pp = 409، +***pp => *pp = *pp + 1 = 410. وبعبارة أخرى، a[3] = 410.

في السطر 11، مرة أخرى يتم كتابة التعبير الذي يطبع ثلاث قيم، أي pp-p، *pp-a، *pp. دعونا نحسب كل واحد منهم.

  • ص = 304، ص = 300 => ص - ص = (304 - 300)/2 => ص - ع = 2، أي سيتم طباعة 2.
  • pp = 304، *pp = 206، a = 200 => *pp-a = (206 - 200)/2 = 3، أي سيتم طباعة 3.
  • في السطر 8، **ص = 410.

لذلك، كنتيجة للسطر 9، سيتم طباعة الإخراج 2، 3، 410 على وحدة التحكم.

أخيرًا، سيتم إعطاء مخرجات البرنامج الكامل على النحو التالي:

انتاج |

 1 1 206 2 2 300 2 3 409 2 3 410