علوم البرمجة

مدخل إلى لغة سي البرمجية C Programming

حول لغة سي About C Programming Language

تُعتبر لغة سي البرمجية إحدى أشهر لغات البرمجة وأكثرها استخداماً في وقتنا الحاليّ، وذلك على الرّغم من قدمها أو حتى عدم دعمها لنموذج البرمجة كائنية التوجه، حيث أنها تدعم نموذج البرمجة الإجرائية. لغة سي هي لغة عامة التوجه General Purpose وغير معتمدة على الآلة Machine Independent (هذه الخاصية تُعرف أيضاً بقابلية النقل Portability)  بمعنى أنه من غير الضروري استخدام معالجات مُحددة أو معمارية حزمة تعليمات خاصة من أجل تنفيذ البرامج المكتوبة بلغة سي، وهكذا يمكن كتابة برامج باستخدام لغة سي على نظام تشغيل ويندوز وتشغيله على حاسوب ماك أو حاسوب يعمل بنظام تشغيل لينوكس.

تعتبر لغة سي حجر الأساس الذي يتم الاعتماد عليه في مجال برمجة أنظمة التشغيل، كما أنها العمود الفقريّ في مجال برمجة الأنظمة المضمنة Embedded Systems بفضل خواصها التي تتيح قدراتٍ متقدمة من ناحية التحكم بالعتاد وإدارة الذواكر، ولذلك فإنها تعتبر اليوم بالنسبة للكثيرين على أنها “لغة مُنخفضة المستوى” مقياساً بلغات البرمجة الأخرى الحديثة.

بحسب مؤشر شركة تيوبي TIOBE الشهير والخاص بتقييم شعبية لغات البرمجة ومدى استخدامها، تحتل لغة سي حالياً المركز الأول، وذلك بالنسبة لشهر نوفمبر من سنة 2020.

التطور التاريخي للغة سي

يعود الفضل في تطوير لغة سي البرمجية للمهندس الشهير دينيس ريتشي الذي قام بإطلاق لغة سي سنة 1972 أثناء عمله ضمن مختبرات بيل، حيث جمعت هذه اللغة ميزات عدة لغات برمجة أقدم منها وهي ألغول ALGOL و BCPL و B، وقد صاحب نشوء اللغة ارتباط وثيق بنظام تشغيل يونيكس UNIX وكانت اللغة بالأساس موجهة للاستخدام ضمنه، ولكن ومع تزايد شعبيتها وظهور مترجماتٍ جديدة لها أصبح بالإمكان استخدامها مع أنظمة تشغيل أخرى لتصبح اللغة عابرة للمنصات Cross-Platform.

دينيس ريتشي (1941 – 2011) مصمم ومطور لغة سي البرمجية أثناء عمله في مختبرات شركة بيل

مع تطور اللغة وتزايد شعبيتها، بدأت الجهود من أجل تطوير مرجعٍ للغة، وهو ما حصل عام 1989 عندما قام المعهد الوطني الأميركي للمعايير ANSI بتحديد معيارٍ تجاريّ للغة وتم تسميته باسم ANSI-C، وتم قبول اللغة من قبل المنظمة العالمية للمعايير ISO عام 1990، ليُصبح هنالك مرجعٍ رسميّ يوضح قواعد اللغة وإصداراتها المختلفة.

بعد أن أصبحت اللغة مرجعية، ظهر عدة إصدارات جديدة لها، وهي الإصدار C99 الذي تضمن ميزاتٍ جديدة مثل التوابع السطرية Inline Functions وأنماط معطيات جديدة، ومن ثم ظهر إصدار C11 الذي جلب معه دعم العمليات الذرية Atomic Operations والبنى المجهولة Anonymous Structures ودعم تعدد المسالك Multithreading بالإضافة لتحسين التوافقية مع لغة سي بلس بلس. آخر الإصدارات المستقرة للغة سي هو C17 الذي حمل تحسيناتٍ على معيار C11، وتم مؤخراً إطلاق مسودة الملف المرجعي الأولي لنسخة سي المقبلة والتي تحمل حالياً اسم C2X، ومن المتوقع أن يتم إطلاقها بشكلٍ رسميّ سنة 2021.

بعيداً عن الإصدارات المرجعية للغة سي، هنالك توسعة من لغة سي مرتبطة ببرمجة الأنظمة المضمنة والمتحكمات الصغرية والنابعة من بعض الخصوصيات العتادية المرتبطة بها، وهذه التوسعة معروفة باسم “لغة سي المضمنة Embedded-C” والتي تشتمل على دعمٍ لخصائص مثل العمليات على منافذ الدخل والخرج ودعم تعدد قطاعات الذاكرة المنفصلة.

كيف تعمل لغة سي؟

لغة سي هي لغة مترجمة Compiled Language، وهذا يعني أن عملية توليد البرنامج القابل للتشغيل من قبل المعالج تستوجب وجود مترجم يقوم بتحويل الشيفرة المصدرية من شكلها المكتوب بلغة سي إلى ملفٍ تنفيذيّ مكتوبٍ بلغة الآلة (للمزيد من التفاصيل، يمكن قراءة مقالنا المفصل حول المترجمات). وبشكلٍ مبسط، يمكن فهم عملية البرمجة باستخدام لغة سي عبر الشكل التالي:

بشيءٍ من التفصيل، فإن ما يحصل بالفعل هو أن المترجم يقوم بعملية مسح للشيفرة المصدرية والتأكد من خلوها من الأخطاء القواعدية والدلالية، ومن ثم سيتم توليد ملف كائني بصيغة .obj أو عدة ملفات كائنية، ويقوم برنامج آخر يدعى “الواصل Linker” بربط هذه الملفات مع بعضها البعض وتخصيص مساحة الذاكرة اللازمة لتشغيل البرنامج وإنشاء الملف التنفيذي بصيغة exe الذي يمكن تشغيله من قبل المعالج. تستوجب عملية إنشاء البرامج باستخدام لغة سي تكرار دورة العمل هذه في كل مرة، وأي تعديل على البرنامج سيتطلب إنشاء ملف تنفيذي جديد.

لغة سي: نظرة عامة على بنية البرنامج Program Structure

من أجل فهم كيفية كتابة برامج باستخدام لغة سي، سيكون من الجيد أخذ مثال برنامج بسيط، يتم عبره حساب مربع الأعداد من 1 وحتى 9 مع طباعة عبارة ترحيبية على الشاشة. علينا تذكر أن لغة سي هي لغة مترجمة وتتبع نموذج البرمجة الإجرائية، وهذا يفرض علينا إخبار المترجم بكل المعلومات التي يحتاجها من أجل توليد الشيفرة التنفيذية بشكلٍ صحيح.

نحن نريد أن نقوم بطباعة عبارة ترحيبية على الشاشة بالإضافة لطباعة مربع الأعداد من 1 وحتى 9، ولغة سي توفر مجموعة من التوابع المبنية مسبقاً Built-In Functions من أجل هذه الغاية (أي طباعة سلاسل محرفية على الشاشة) ضمن مكتبة الدخل والخرج المعيارية. هذا يقودنا إلى ضرورة تضمين ملف رأسي Header-File يتضمن تعليمة تدعى موجه ما قبل البرمجة Pre-Processing Directive والتي تخبر المترجم بضرورة تضمين الملف الرأسي المراد استخدامه في البرنامج، وبحالتنا هذه الملف الرأسي هو مكتبة الدخل والخرج المعيارية في لغة سي.

الآن سيتوجب علينا كتابة تعليمات البرنامج: طباعة عبارة ترحيبية على الشاشة ومن ثم حساب ناتج مربع الأعداد من 1 وحتى 9 وأخيراً طباعتها على الشاشة. هذا الأمر نستطيع تنفيذه في التابع الأساسيّ Main. ضمن التابع الأساسيّ هنالك خيارين: إما أن تقوم بكتابة التعليمات الخاصة بإجرائية حساب مربع الأعداد من 1 وحتى 9، أو نقوم كتابة تابع خاص يقوم بحساب مربع الأعداد ومن ثم نقوم باستدعائه ضمن التابع Main. هنا سنقوم بكتابة إجرائية حساب مربع الأعداد من 1 وحتى 9 ضمن التابع الأساسيّ بشكلٍ مباشر. النص البرمجي التالي يمثل برنامجاً مكتوباً بلغة سي من أجل حساب مربع الأعداد من 1 وحتى 9 وطباعتها على الشاشة، مع طباعة عبارة ترحيبية في البداية:

/**
 * Program Description: 
 * Calculate the square values of number from 1 to 9 and print it on the screen
 */

// Header-Files
#include <stdio.h>
#include <stdlib.h>

// Main function
int main(void)
{
	// Print a welcome message
	printf("*** C-Programming Simple Program ***\n");
	printf("*** Calculate the square value of numbers from 1 to 9 ***\n");
	printf("\n");

	// Procedure to calculate numbers from 1 to 9
	for (unsigned int index = 1; index < 10; index = index + 1)
	{
		printf("The square value of %d is : %d\n", index, (index*index));
	}

	return EXIT_SUCCESS;
}

ملاحظة: في البرنامج السابق، كل العبارات المسبوقة بإشارة // أو الموجودة ضمن كتلة محددة بالرموز /*…*/ تعتبر تعليقات توضيحية ولا علاقة لها بخوارزمية عمل البرنامج ويتم تجاهلها من قبل المترجم الذي يقوم بتوليد الشيفرة التنفيذية الخاصة بالبرنامج السابق.

بعد بناء البرنامج السابق باستخدام أحد بيئات التطوير البرمجية (أو عبر استدعاء المترجم ضمن موّجه الأوامر Command Prompt) سيتم توليد الشيفرة التنفيذية (ملف صيغة exe) والتي يمكن استدعائها من أجل تنفيذ محتوى البرنامج السابق. عند تنفيذ البرنامج السابق باستخدام أحد بيئات التطوير البرمجية سيظهر على شاشة الخرج Console الخرج التالي:

*** Simple C Program to calculate square number from 1 to 9 ***
The square number of 1 is : 1
The square number of 2 is : 4
The square number of 3 is : 9
The square number of 4 is : 16
The square number of 5 is : 25
The square number of 6 is : 36
The square number of 7 is : 49
The square number of 8 is : 64
The square number of 9 is : 81

استخدامات لغة سي

توفر سي للمبرمجين والمطورين قدرات متقدمة في مجال التحكم وبرمجة العتاد، ولذلك فهي مستخدمة على نطاقٍ واسع في مجال برمجة المتحكمات الصغرية والأنظمة المضمنة، كما أنها العمود الفقري في مجال برمجة أنظمة التشغيل وتطبيقات أنظمة التشغيل، وكمثال شهير على ذلك هو تطبيقات وبرامج شركة أدوبي Adobe الشهيرة التي تم تطوير الكثير منها بالاعتماد على سي جزئياً أو كلياً، كما أن المتصفح كروميوم Chromium (النسخة المجانية ومفتوحة المصدر لمتصفح كروم) مبنية بلغة سي، كما أن برنامج إدارة قواعد البيانات الشهير MySQL مطوّر باستخدام لغة سي، ولا ننسى المثال الأشهر وهو نواة نظام تشغيل لينوكس المكتوبة بالكامل باستخدام لغة سي (يمكن الاطلاع على الشيفرة المصدرية عبر هذا الرابط)، فضلاً عن أنظمة تشغيل ويندوز وماك أو إس وأندرويد التي تم الاعتماد على لغة سي من أجل بناء نواتها.

بعيداً عن عالم أنظمة التشغيل وتطبيقاتها، تمتلك سي أهمية كبيرة ومتزايدة في وقتنا الحاليّ مع توسع منتجات وتطبيقات إنترنت الأشياء، أي الأجهزة الذكية ذات استهلاك الطاقة المنخفضة والتي تتيح تنفيذ العديد من الأوامر عبر الإنترنت. تعتمد هذه الأجهزة في داخلها على متحكمات صغرية التي يمكن برمجتها باستخدام لغة سي (يمكن أيضاً برمجة المتحكمات الصغرية باستخدام سي بلس بلس أو باستخدام لغة التجميع).

أهمية لغة سي

يصادفني كثيراً السؤال: ما سبب تعلم لغة سي؟ لماذا علي أن أتعلم لغة سي؟ هل لا يزال هنالك أحد يستخدم هذه اللغة؟

لو أخذنا نظرة سريعة على لغات البرمجة التي يتم البحث عنها بشكلٍ متكرر، فإننا سنجد لغة مثل بايثون على رأس القائمة (بحسب إحصاءات موقع ستاتيستا لسنة 2020)، تليها جافا وجافاسكريبت، وعند الحديث عن التوجهات التقنية، فإن مجال الذكاء الاصطناعي وتطبيقات تعلم الآلة تحتل أيضاً اهتماماً كبيراً والتي من أجل برمجتها تُستخدم لغة بايثون بشكلٍ أساسيّ. ولكننا ننسى جميعاً نقطة هامة: المفسر الخاص بلغة بايثون مكتوب بلغة سي، وهذا يعني أنه في كل مرة يتم تنفيذ شيفرة بايثون، هنالك برنامج مكتوب بلغة سي يتولى مسؤولية تفسير النص البرمجي وتوليد شيفرة تنفيذية قابلة للتنفيذ (للمزيد حول هذا الموضوع يمكن الاطلاع على مقالنا التفصيلي حول المفسرات Interpreters). المثال السابق هو فقط لتوضيح أهمية سي كلغة قريبة من العتاد الحاسوبي؛ بدون سي لا يمكن تنفيذ العديد من البرامج والتطبيقات ولن تتواجد حتى الكثير من أنظمة التشغيل بالأساس. سي مهمة، في الواقع، سي مهمة أكثر مما يظن الكثيرون.

على صعيدٍ آخر، تعلّم لغة سي – كرأي شخصي – هو أمرٌ أساسيّ لأي شخص يود فهم آلية عمل الأنظمة الحاسوبية على نحوٍ صحيح. كما ذكرت في المقال، سي لغة قريبة من العتاد الحاسوبي وهي تتضمن العديد من الخصائص التي تتيح أموراً غير متوافرة في لغاتٍ أخرى مثل إدارة الذواكر. هذا الأمر يجعل تعلم وإتقان سي أصعب نسبياً من بعض اللغات الأخرى، إلا أن هذه الصعوبة لها فائدة كبيرة تكمن بالفهم والتعمق الإضافيّ الذي سيكتسبه المبرمج أو مهندس البرمجيات.

خلاصة Summary

  • سي هي إحدى أوائل لغات البرمجة عالية المستوى وتُعتبر حجر الأساس لكل لغات البرمجة الحديثة التي ظهرت لاحقاً (مثل سي بلس بلس، جافا، بايثون)
  • تدعم سي نموذج البرمجة الإجرائية ولا تدعم نموذج البرمجة كائنية التوّجه
  • تتميز سي بالسرعة الكبيرة بتنفيذ الشيفرة البرمجية، كما أنها غير معتمدة على الآلة (Machine Independent)، وتتيح قدرات متقدمة في إدارة الذواكر وبرمجة العتاد الحاسوبي
  • تستخدم سي في برمجة أنظمة التشغيل وتطبيقاتها وفي برمجة المترجمات للغات البرمجة الأخرى وفي مجال برمجة العتاد والأنظمة المضمنة وتطبيقات إنترنت الأشياء

مقالات ذات صلة

زر الذهاب إلى الأعلى