التخصيص باستخدام calloc()
جزء من قسم Logic & Flow في رحلة C على Coddy — الدرس 36 من 63.
بينما تعد malloc() هي الدالة الأكثر شيوعاً لتخصيص الذاكرة الديناميكي، توفر لغة C بديلاً مفيداً آخر: calloc(). توفر دالة calloc()، والتي ترمز إلى "التخصيص المتصل" (contiguous allocation)، طريقة ملائمة لتخصيص الذاكرة للمصفوفات مع ميزة إضافية مهمة.
على عكس malloc() التي تأخذ وسيطاً واحداً (إجمالي البايتات)، تأخذ calloc() وسيطين: عدد العناصر التي تريد تخصيصها وحجم كل عنصر. وهذا يجعلها بديهية بشكل خاص عند التعامل مع المصفوفات. على سبيل المثال:
#include <stdlib.h>
// تخصيص مساحة لـ 5 أعداد صحيحة باستخدام calloc()
int *arr = (int*)calloc(5, sizeof(int));
// هذا يعادل: malloc(5 * sizeof(int))الميزة الأساسية لـ calloc() هي أنها تقوم تلقائياً بـ تهيئة جميع الذاكرة المخصصة إلى الصفر. عندما تستخدم malloc()، تحتوي الذاكرة المخصصة على أي قيم عشوائية كانت مخزنة هناك مسبقاً، ولكن calloc() تضمن تعيين كل بايت على الصفر. وهذا يعني أن جميع الأعداد الصحيحة ستكون 0، وجميع الأعداد العشرية ستكون 0.0، وجميع المؤشرات ستكون NULL.
مثل malloc()، يعيد calloc() مؤشراً إلى الذاكرة المحجوزة أو NULL إذا فشل الحجز، لذا يجب عليك دائماً التحقق من فشل الحجز وتذكر أن تقوم بـ free() للذاكرة عند الانتهاء من استخدامها.
التحدي
سهلاكتب برنامجاً بلغة C يوضح استخدام calloc() لتخصيص الذاكرة الديناميكي مع التهيئة التلقائية للصفر. يجب على برنامجك القيام بما يلي:
- قراءة عدد صحيح
sizeمن المستخدم يمثل عدد الأعداد الصحيحة المطلوب تخصيصها - استخدام
calloc()لتخصيص ذاكرة ديناميكياً لمصفوفة من الأعداد الصحيحة بحجمsize - التحقق مما إذا كان تخصيص الذاكرة ناجحاً - إذا فشل، اطبع
Memory allocation failed!وأنهِ البرنامج - إذا نجح التخصيص، اطبع
Memory allocated and initialized to zero! - اطبع جميع القيم الأولية في المصفوفة لإثبات أنها صفر، بالتنسيق التالي:
Initial values: [value1] [value2] [value3] ... - قراءة قيم
sizeمن الأعداد الصحيحة من المستخدم وتخزينها في المصفوفة المخصصة - اطبع جميع القيم المحدثة بالتنسيق التالي:
Updated values: [value1] [value2] [value3] ... - احسب واطبع مجموع كل القيم بالتنسيق التالي:
Sum: [value] - استخدم
free()لإلغاء تخصيص الذاكرة - اطبع
Memory freed!لتأكيد عملية التنظيف
تذكر تضمين الترويسة <stdlib.h> لاستخدام calloc() و free(). يوضح هذا التحدي الميزة الرئيسية لـ calloc() على malloc(): التهيئة التلقائية لجميع الذاكرة المخصصة إلى الصفر.
على سبيل المثال، إذا كان الإدخال هو:
3
10 20 30يجب أن يكون مخرجك:
Memory allocated and initialized to zero!
Initial values: 0 0 0
Updated values: 10 20 30
Sum: 60
Memory freed!يسلط هذا التحدي الضوء على كيفية توفير calloc() لحالة بداية نظيفة ويمكن التنبؤ بها لمصفوفاتك المخصصة ديناميكياً، مما يلغي قيم القمامة (garbage values) غير المتوقعة التي قد يتركها malloc() وراءه.
ورقة مرجعية
توفر الدالة calloc() تخصيصاً ديناميكياً للذاكرة مع تهيئة تلقائية للصفر.
الصيغة البرمجية:
void* calloc(size_t num_elements, size_t element_size);الاختلافات الرئيسية عن malloc():
- تأخذ وسيطين: عدد العناصر وحجم كل عنصر
- تقوم بتهيئة جميع الذاكرة المخصصة تلقائياً إلى الصفر
- أكثر سهولة لتخصيص المصفوفات
مثال على الاستخدام:
#include <stdlib.h>
// تخصيص مساحة لـ 5 أعداد صحيحة باستخدام calloc()
int *arr = (int*)calloc(5, sizeof(int));
// هذا يعادل: malloc(5 * sizeof(int))
// ولكن جميع القيم مضمونة لتكون 0مثل malloc()، تعيد calloc() مؤشراً إلى الذاكرة المخصصة أو NULL إذا فشل التخصيص. تحقق دائماً من فشل التخصيص واستخدم free() لإلغاء تخصيص الذاكرة عند الانتهاء.
جرّب بنفسك
#include <stdio.h>
#include <stdlib.h>
int main() {
int size;
// قراءة حجم المصفوفة
scanf("%d", &size);
// TODO: اكتب الكود الخاص بك أدناه
// استخدم calloc() لتخصيص ذاكرة للمصفوفة
// تحقق مما إذا كان التخصيص ناجحًا
// طباعة القيم الأولية (يجب أن تكون صفرًا)
// قراءة وتخزين قيم المدخلات
// طباعة القيم المحدثة
// حساب وطباعة المجموع
// تحرير الذاكرة المخصصة
return 0;
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1أساسيات المؤشرات
ما هو المؤشر؟الإعلان عن المؤشراتعامل العنوان (&)عامل إلغاء المرجعية (*)مؤشرات NULLمراجعة: أساسيات المؤشرات4مشروع: أداة نصوص بسيطة
نظرة عامة على المشروععد الأحرف2المؤشرات والمصفوفات
أسماء المصفوفات كمؤشراتعناصر المصفوفة - المؤشراتالعمليات الحسابية على المؤشراتمقارنة المؤشراتمراجعة: التنقل في المصفوفة باستخدام المؤشرات5المؤشرات والدوال
التمرير بالقيمةتمرير المؤشرات إلى الدوالتعديل المتغيرات عبر المؤشراتمثال كلاسيكي: التبديلتمرير المصفوفات إلى الدوالملخص: وسائط المؤشرات في الدوال8الهياكل والمؤشرات
المؤشرات إلى الهياكلعامل السهم (->)تمرير الهياكل بالقيمةتمرير مؤشرات الهياكلالتخصيص الديناميكي للهياكلمراجعة: تعديل الهياكل باستخدام المؤشرات11تحديات المراجعة النهائية
مراجعة: دمج السلاسل النصية الديناميكيمراجعة: مصفوفة من الـ Structsمراجعة: عداد تكرار الكلمات3مصفوفات الأحرف والسلاسل النصية
السلاسل النصية كمصفوفات charالمُنهي الصفري (Null Terminator)إدخال السلاسل النصية باستخدام scanfاستخدام strlen()استخدام strcpy()استخدام strcat()استخدام strcmp()مراجعة: دوال السلاسل النصية الأساسية6إدارة الذاكرة
ذاكرة Stack مقابل Heapالتخصيص الديناميكي - malloc()استخدام sizeof() للتخصيصالتحقق من فشل التخصيصتحرير الذاكرة باستخدام free()التخصيص باستخدام calloc()ملخص: المصفوفة الديناميكية