C: المصفوفات

تخيّل صفًا من الخزائن، كل واحدة مرقّمة بدءًا من 0، تخزن عناصر من نفس النوع — تلك هي المصفوفة. تتيح لك إدارة مجموعة من البيانات من نفس النوع تحت اسم واحد.

1. تعريف وتهيئة المصفوفات أحادية البعد

المصفوفة هي مجموعة مرتّبة من عناصر من نفس النوع، مخزّنة بشكل متجاور في الذاكرة. عند تعريف مصفوفة، تحدد نوع العناصر وعددها.

C
int scores[5];

هذا يعرّف مصفوفة من 5 عناصر من نوع int، لكن المحتويات غير مهيأة وقيمها غير محددة. يُنصح بتهيئة المصفوفة عند التعريف:

C
int scores[5] = {90, 85, 78, 92, 88};

إذا كانت قائمة التهيئة أقصر من المصفوفة، تُعيَّن العناصر المتبقية تلقائيًا إلى 0:

C
int data[5] = {10, 20};

الآن data[2] و data[3] و data[4] جميعها 0. باستخدام هذه الخاصية، يمكنك تصفير مصفوفة كاملة:

C
int zeros[100] = {0};

إذا قدمت قائمة تهيئة كاملة، يمكنك حذف طول المصفوفة ويحسبه المترجم تلقائيًا:

C
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

2. الوصول بالدليل

يُوصل إلى عناصر المصفوفة بالدليل (الفهرس)، بدءًا من 0. لمصفوفة طولها N، تتراوح الأدلة الصالحة من 0 إلى N-1.

C
int scores[5] = {90, 85, 78, 92, 88};

int first = scores[0];
int last = scores[4];

scores[2] = 100;

يمكن أن يكون الدليل تعبيرًا عددًا صحيحًا، مما يسهّل الاجتياز بالحلقات:

TEXT 📖 للعرض فقط
int i = 3;
int val = scores[i];
💡 نصيحة: تذكّر: لمصفوفة طولها 5، الدليل الأقصى هو 4 وليس 5. لا تتحقق C من حدود المصفوفة وقت التنفيذ. الوصول المتجاوز لن ينتج خطأ، لكن العواقب قد تكون خطيرة.


3. مخاطر تجاوز الحدود

لا تتحقق C مما إذا كانت أدلة المصفوفة متجاوزة للحدود. الوصول إلى عناصر متجاوزة هو سلوك غير معرّف — قد يقرأ بيانات عشوائية، أو يعدّل متغيرات أخرى، أو ينهار البرنامج.

C
int arr[3] = {10, 20, 30};

printf("%d\n", arr[3]);
printf("%d\n", arr[-1]);

كلتا السطرين تصلان إلى مواقع غير مشروعة. لن يحذرك المترجم، لكن النتائج غير متوقعة.

⚠️ ملاحظة: الوصول المتجاوز للحدود هو أحد أكثر مصادر الأخطاء شيوعًا في C. عند كتابة الحلقات، تحقق دائمًا من شروط الحدود واستخدم < بدلًا من <= عند المقارنة مع الطول.


4. اجتياز المصفوفة

استخدام حلقة for لمعالجة كل عنصر بالتسلسل هو أكثر عمليات المصفوفات شيوعًا:

C
int scores[5] = {90, 85, 78, 92, 88};
int i;

for (i = 0; i < 5; i++) {
    printf("scores[%d] = %d\n", i, scores[i]);
}

جمع جميع العناصر:

C
int sum = 0;
for (i = 0; i < 5; i++) {
    sum += scores[i];
}
printf("Total: %d\n", sum);

إيجاد القيمة القصوى:

TEXT 📖 للعرض فقط
int max = scores[0];
for (i = 1; i < 5; i++) {
    if (scores[i] > max) {
        max = scores[i];
    }
}
printf("Highest: %d\n", max);

▶ مثال

حساب متوسط الدرجات وعدد الرسوب:

C
#include <stdio.h>

int main(void) {
    double scores[] = {78.5, 92.0, 55.5, 88.0, 43.0, 67.5, 90.0};
    int len = sizeof(scores) / sizeof(scores[0]);
    double sum = 0;
    int fail = 0;
    int i;

    for (i = 0; i < len; i++) {
        sum += scores[i];
        if (scores[i] < 60.0) {
            fail++;
        }
    }

    printf("Average: %.1f\n", sum / len);
    printf("Failing: %d\n", fail);

    return 0;
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
Average: 73.5
Failing: 2

هنا، sizeof(scores) / sizeof(scores[0]) يحسب عدد العناصر ديناميكيًا، لذا لا تحتاج لتحديث شرط الحلقة عند تغيير محتويات المصفوفة.


5. المصفوفات كمعاملات دوال

عند تمرير مصفوفة إلى دالة، لا تُنسخ المصفوفة بالكامل — بل يُمرَّر عنوان العنصر الأول فقط. هذا يعني أن الدالة لا يمكنها تحديد طول المصفوفة باستخدام sizeof؛ يجب تمرير الطول كمعامل منفصل.

C
void print_array(int arr[], int len) {
    int i;
    for (i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

المعامل int arr[] يكافئ int *arr، مما يعكس "الانحلال" إلى مؤشر. تعديل عناصر المصفوفة داخل الدالة يؤثر على المصفوفة الأصلية لأن كلاهما يعملان على نفس الذاكرة.

C
void double_values(int arr[], int len) {
    int i;
    for (i = 0; i < len; i++) {
        arr[i] *= 2;
    }
}

int main(void) {
    int data[] = {1, 2, 3, 4, 5};
    double_values(data, 5);
    return 0;
}

بعد الاستدعاء، تحتوي data على {2, 4, 6, 8, 10}.


6. المصفوفات ثنائية البعد

يمكن اعتبار المصفوفة ثنائية البعد "مصفوفة من المصفوفات"، وتُستخدم شيوعًا لتمثيل المصفوفات الرياضية أو البيانات الجدولية.

C
int matrix[3][4];

هذا يعرّف مصفوفة ثنائية البعد من 3 صفوف و4 أعمدة. يمكن تجميع التهيئة حسب الصف:

C
int matrix[3][4] = {
    {1,  2,  3,  4},
    {5,  6,  7,  8},
    {9, 10, 11, 12}
};

يمكن أيضًا كتابتها مسطحة — التأثير هو نفسه:

C
int matrix[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

الوصول إلى العناصر بدليلين:

C
int val = matrix[1][2];
matrix[0][0] = 100;

اجتياز مصفوفة ثنائية البعد يتطلب حلقة مزدوجة:

TEXT 📖 للعرض فقط
int i, j;
for (i = 0; i < 3; i++) {
    for (j = 0; j < 4; j++) {
        printf("%4d", matrix[i][j]);
    }
    printf("\n");
}

عند التهيئة، يمكنك حذف عدد الصفوف ولكن لا يمكنك حذف عدد الأعمدة:

C
int m[][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8}
};

يستنتج المترجم صفين من بيانات التهيئة.

▶ مثال

حساب متوسط الدرجات عبر 4 مواد لـ 3 طلاب:

C
#include <stdio.h>

void student_avg(double grades[][4], int rows) {
    int i, j;
    for (i = 0; i < rows; i++) {
        double sum = 0;
        for (j = 0; j < 4; j++) {
            sum += grades[i][j];
        }
        printf("Student%d Average: %.1f\n", i + 1, sum / 4);
    }
}

int main(void) {
    double grades[3][4] = {
        {85.0, 90.0, 78.0, 92.0},
        {70.0, 65.0, 80.0, 75.0},
        {95.0, 88.0, 92.0, 97.0}
    };

    student_avg(grades, 3);

    return 0;
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
Student1 Average: 86.2
Student2 Average: 72.5
Student3 Average: 93.0
💡 نصيحة: عند استخدام مصفوفة ثنائية البعد كمعامل دالة، يجب تحديد عدد الأعمدة (حجم البعد الثاني)؛ ويُمرَّر عدد الصفوف كمعامل منفصل.


❓ أسئلة شائعة

س ما القيم في مصفوفة عُرّفت لكن لم تُهيَّأ؟
ج المصفوفات المحلية لها محتويات غير محددة (قيم عشوائية على المكدس)؛ والمصفوفات العامة والمستقلة تُهيَّأ تلقائيًا إلى 0.
س لماذا لا يمكن استخدام sizeof(arr) داخل دالة لمعرفة عدد العناصر؟
ج بعد تمرير المصفوفة كمعامل، تنحل إلى مؤشر. sizeof يعطي حجم المؤشر (4 أو 8 بايت)، وليس الحجم الكلي للمصفوفة.
س هل يمكن أن يكون دليل المصفوفة سالبًا؟
ج نحويًا يُترجم، لكنه يصل إلى ذاكرة قبل عنوان بداية المصفوفة، وهو تجاوز حدود وسلوك غير معرّف.
س كيف تُخزَّن المصفوفات ثنائية البعد في الذاكرة؟
ج بترتيب الصفوف، بشكل متجاور. تُخزَّن جميع عناصر الصف 0 أولًا، ثم الصف 1، وهكذا.

📖 ملخص

📝 تمارين

  1. اكتب برنامجًا يقرأ 10 أعداد صحيحة في مصفوفة، ثم يطبع جميع العناصر بترتيب عكسي.
  2. اكتب دالة تستقبل مصفوفة أعداد صحيحة وطولها، وتُرجع دليل القيمة القصوى.
  3. عرّف مصفوفة أعداد صحيحة 4x4، تهيّئها، واحسب مجموع القطرين.
Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%