تهيئة الـ Stack
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 14 من 61.
ليس كل كائن يحتاج للعيش في الـ heap. عندما يكون الـ struct صغيراً وله عمر قصير، فإن تخصيصه على الـ stack يكون أبسط وأسرع — لا malloc، ولا free، ولا يوجد خطر من حدوث تسرب للذاكرة.
بدلاً من إرجاع pointer، يمكن لـ factory function إرجاع الـ struct بواسطة القيمة (by value). يتم نسخ الـ struct بالكامل إلى الـ caller:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
يتلقى المتصل نسخة مهيأة بالكامل:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
لا توجد مؤشرات، ولا يلزم إجراء عملية تنظيف. عندما يخرج origin و cursor عن النطاق، يتم تدميرهما تلقائيًا.
يعمل هذا النهج بشكل أفضل مع الهياكل (structs) الصغيرة التي لا تحتوي على أعضاء مخصصة ديناميكيًا. بالنسبة للكائنات الأكبر حجمًا أو تلك التي تحتوي على مؤشرات إلى ذاكرة الكومة (heap memory)، يظل نمط المنشئ (constructor pattern) مع malloc هو الخيار الأفضل.
التحدي
سهللنقم ببناء وحدة Temperature تقوم بإنشاء قراءات لدرجة الحرارة على الـ stack باستخدام دالة مصنع (factory function). على عكس المنشئات (constructors) التي تعتمد على الـ heap في الدروس السابقة، فإن هذا النهج يعيد الـ struct بالقيمة (by value) — لا حاجة لـ malloc، ولا free، مجرد تخصيص بسيط وفعال على الـ stack.
ستقوم بإنشاء ثلاثة ملفات:
temperature.h: قم بالتصريح عن struct باسمTemperatureيحتوي على عضوين:double celsiusوchar scale(لتخزين 'C' للدرجة المئوية). صرح أيضاً عن دالتين:create_temperature— تأخذ قيمة double وتعيد struct من نوعTemperatureبالقيمة (وليس مؤشراً!)temperature_to_fahrenheit— تأخذconst Temperature *وتعيد درجة الحرارة المكافئة بالفهرنهايت كـ double
TEMPERATURE_H.temperature.c: قم بتنفيذ كلتا الدالتين. يجب أن تقوم دالة المصنع بإنشاء متغيرTemperatureمحلي، وتهيئة حقوله (تعيينscaleإلى'C')، وإعادته. صيغة التحويل هي:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c: استخدم دالة المصنع لإنشاء قراءة لدرجة الحرارة وعرض قيمتي Celsius و Fahrenheit.
ستتلقى مدخلاً واحداً: درجة الحرارة بالسيلزيوس (كـ double).
في ملفك الرئيسي، استخدم create_temperature لإنشاء struct من نوع Temperature بالقيمة المعطاة. ثم اطبع قيمة Celsius الأصلية وما يعادلها بالفهرنهايت.
اطبع المخرجات بهذا التنسيق:
Celsius: {celsius}
Fahrenheit: {fahrenheit}استخدم %.2f لكلتا القيمتين لعرض منزلتين عشريتين.
على سبيل المثال، مع مدخل 25.0، ستكون المخرجات:
Celsius: 25.00
Fahrenheit: 77.00لاحظ مدى نظافة هذا النهج — فأنت تتلقى struct مهيأ بالكامل دون أي مخاوف تتعلق بإدارة الذاكرة. عندما يخرج متغير Temperature الخاص بك عن النطاق (scope)، يتم تنظيفه تلقائياً.
ورقة مرجعية
يمكن لدوال المصنع (Factory functions) إرجاع الهياكل (structs) بالقيمة بدلاً من المؤشرات. يقوم هذا بتخصيص الهيكل على المكدس (stack) — لا يوجد malloc، ولا free، ولا تسريبات للذاكرة.
مثال على دالة مصنع ترجع بالقيمة:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
استخدام دالة المصنع:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
يتم نسخ الهيكل إلى المستدعي ويتم تدميره تلقائياً عندما يخرج عن النطاق. يعمل هذا النهج بشكل أفضل مع الهياكل الصغيرة التي لا تحتوي على أعضاء مخصصة ديناميكياً.
جرّب بنفسك
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: استخدم create_temperature لإنشاء هيكل Temperature
// TODO: اطبع قيمة Celsius باستخدام تنسيق %.2f
// TODO: استخدم temperature_to_fahrenheit لتحويل وطباعة قيمة Fahrenheit
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرة