العمليات الحسابية على المؤشرات
جزء من قسم Logic & Flow في رحلة C على Coddy — الدرس 9 من 63.
لقد تعلمت كيفية الوصول إلى عناصر المصفوفة باستخدام تدوين المؤشرات مثل *(array + i). الآن ستكتشف تقنية أكثر قوة: حسابيات المؤشرات، والتي تتيح لك تحريك المؤشرات عبر الذاكرة باستخدام عمليات الزيادة والنقصان البسيطة.
عندما تقوم بزيادة مؤشر باستخدام ++ أو إنقاصه باستخدام --، فإن المؤشر لا يتحرك بمقدار بايت واحد فقط. بدلاً من ذلك، فإنه يتحرك بمقدار حجم نوع البيانات الذي يشير إليه. بالنسبة لمؤشر عدد صحيح، فإن ptr++ يتحرك للأمام بمقدار sizeof(int) بايت، مما يجعله يستقر تماماً على العدد الصحيح التالي في الذاكرة.
int numbers[5] = {10, 20, 30, 40, 50};
int *ptr = numbers; // يشير إلى العنصر الأول (10)
ptr++; // يشير الآن إلى العنصر الثاني (20)
ptr++; // يشير الآن إلى العنصر الثالث (30)هذا الحساب التلقائي للحجم هو ما يجعل حسابات المؤشرات (pointer arithmetic) قوية ومريحة للغاية. لا داعي للقلق بشأن حسابات البايتات - لغة C تتولى معالجة الذاكرة نيابة عنك بناءً على نوع بيانات المؤشر (pointer's data type).
تعتبر العمليات الحسابية على المؤشرات مفيدة بشكل خاص للتنقل عبر المصفوفات في الحلقات التكرارية. فبدلاً من استخدام فهارس المصفوفة، يمكنك زيادة قيمة المؤشر للتنقل عبر كل عنصر بالتتابع، مما يؤدي غالباً إلى كود أكثر كفاءة.
التحدي
سهلاكتب برنامجاً بلغة C يوضح حسابات المؤشرات (pointer arithmetic) باستخدام عمليات زيادة المؤشر للتنقل ومعالجة مصفوفة. يجب أن يقوم برنامجك بما يلي:
- الإعلان عن مصفوفة أعداد صحيحة تسمى
dataتحتوي على 5 عناصر وتهيئتها بالقيم {12, 24, 36, 48, 60} - الإعلان عن مؤشر لعدد صحيح يسمى
ptrوتهيئته ليشير إلى العنصر الأول في المصفوفة - استخدام حلقة for تعمل 5 مرات للتنقل عبر المصفوفة بأكملها باستخدام حسابات المؤشرات فقط
- داخل الحلقة:
- طباعة القيمة الحالية التي يشير إليها
ptrباستخدام عامل إلغاء المرجعية (dereference operator) - طباعة عنوان الذاكرة المخزن في
ptrباستخدام محدد التنسيق%p - زيادة المؤشر باستخدام
ptr++للانتقال إلى العنصر التالي
- طباعة القيمة الحالية التي يشير إليها
- بعد الحلقة، أعد تعيين
ptrليشير مرة أخرى إلى العنصر الأول في المصفوفة - استخدام حسابات المؤشرات للوصول المباشر وطباعة العنصر الثالث (الفهرس 2) باستخدام
*(ptr + 2) - استخدام حسابات المؤشرات للوصول المباشر وطباعة العنصر الأخير (الفهرس 4) باستخدام
*(ptr + 4)
يجب أن يعرض مخرج البرنامج النتائج بالتنسيق التالي:
Value: 12, Address: [address]
Value: 24, Address: [address]
Value: 36, Address: [address]
Value: 48, Address: [address]
Value: 60, Address: [address]
Third element: 36
Last element: 60يختبر هذا التحدي فهمك لكيفية تحرك عمليات زيادة المؤشر تلقائياً بحجم نوع البيانات، وكيف يمكنك استخدام حسابات المؤشرات للوصول إلى عناصر المصفوفة عند إزاحات محددة من موقع المؤشر الأساسي.
ورقة مرجعية
تسمح لك حسابات المؤشرات (Pointer arithmetic) بتحريك المؤشرات عبر الذاكرة باستخدام عمليات الزيادة والنقصان. عندما تقوم بزيادة مؤشر، فإنه يتحرك بمقدار حجم نوع البيانات الذي يشير إليه، وليس بمقدار بايت واحد.
عمليات حسابات المؤشرات الأساسية:
int numbers[5] = {10, 20, 30, 40, 50};
int *ptr = numbers; // يشير إلى العنصر الأول (10)
ptr++; // يشير الآن إلى العنصر الثاني (20)
ptr++; // يشير الآن إلى العنصر الثالث (30)يمكنك أيضاً استخدام حسابات المؤشرات للوصول إلى العناصر عند إزاحات (offsets) محددة:
*(ptr + 2) // الوصول إلى العنصر عند الإزاحة 2 من الموضع الحاليتعتبر حسابات المؤشرات مفيدة للتنقل عبر المصفوفات في الحلقات التكرارية، وغالباً ما تؤدي إلى كود أكثر كفاءة من استخدام فهارس المصفوفة.
جرّب بنفسك
#include <stdio.h>
int main() {
// TODO: اكتب كودك هنا
// قم بتعريف وتهيئة المصفوفة 'data' بالقيم {12, 24, 36, 48, 60}
// قم بتعريف المؤشر 'ptr' وتهيئته ليشير إلى العنصر الأول
// استخدم حلقة for مع حسابات المؤشرات للتنقل عبر المصفوفة
// اطبع كل قيمة وعنوان، ثم قم بزيادة المؤشر
// أعد ضبط المؤشر واستخدم حسابات المؤشرات للوصول إلى عناصر محددة
return 0;
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1أساسيات المؤشرات
ما هو المؤشر؟الإعلان عن المؤشراتعامل العنوان (&)عامل إلغاء المرجعية (*)مؤشرات NULLمراجعة: أساسيات المؤشرات4مشروع: أداة نصوص بسيطة
نظرة عامة على المشروععد الأحرف2المؤشرات والمصفوفات
أسماء المصفوفات كمؤشراتعناصر المصفوفة - المؤشراتالعمليات الحسابية على المؤشراتمقارنة المؤشراتمراجعة: التنقل في المصفوفة باستخدام المؤشرات5المؤشرات والدوال
التمرير بالقيمةتمرير المؤشرات إلى الدوالتعديل المتغيرات عبر المؤشراتمثال كلاسيكي: التبديلتمرير المصفوفات إلى الدوالملخص: وسائط المؤشرات في الدوال8الهياكل والمؤشرات
المؤشرات إلى الهياكلعامل السهم (->)تمرير الهياكل بالقيمةتمرير مؤشرات الهياكلالتخصيص الديناميكي للهياكلمراجعة: تعديل الهياكل باستخدام المؤشرات11تحديات المراجعة النهائية
مراجعة: دمج السلاسل النصية الديناميكيمراجعة: مصفوفة من الـ Structsمراجعة: عداد تكرار الكلمات3مصفوفات الأحرف والسلاسل النصية
السلاسل النصية كمصفوفات charالمُنهي الصفري (Null Terminator)إدخال السلاسل النصية باستخدام scanfاستخدام strlen()استخدام strcpy()استخدام strcat()استخدام strcmp()مراجعة: دوال السلاسل النصية الأساسية