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

لماذا ما زالت لغة C مهمة حتى اليوم؟
رغم أن لغة C قديمة نسبياً مقارنة بكثير من اللغات الحديثة، فإنها ما تزال حاضرة بقوة في مجالات الأنظمة، والبرمجيات المضمنة، والنوى، والأدوات منخفضة المستوى. ويعود ذلك إلى عدة أسباب:
- توفر تحكماً قريباً جداً من العتاد.
- تمنح أداءً عالياً وسرعة تنفيذ ممتازة.
- تُستخدم كأساس لفهم الذاكرة، والمعالجات، وآلية عمل البرامج.
- أثّرت في تصميم لغات كثيرة مثل
C++وJavaوJavaScriptوGo. - تُعتمد في بناء المترجمات، وأنظمة التشغيل، والأدوات البرمجية الحرجة.
نبذة تاريخية عن نشأة لغة C
الارتباط بتطوير نظام Unix
يصعب فهم لغة C دون الرجوع إلى قصة تطوير نظام التشغيل Unix. فقد ظهرت الحاجة إلى لغة فعالة وقريبة من النظام تساعد في بناء أدوات قوية وقابلة للنقل بين الأجهزة المختلفة.
من مشروع MULTICS إلى Unix
في ستينيات القرن الماضي، ظهرت أنظمة المشاركة الزمنية التي سمحت لعدة مستخدمين بالاستفادة من الحاسوب نفسه في الوقت ذاته. كان مشروع MULTICS محاولة طموحة لبناء نظام متقدم يتيح مشاركة الموارد والبيانات على نطاق واسع. ورغم أن المشروع حمل أفكاراً ثورية، فإنه كان معقداً ومكلفاً.
بعد انسحاب Bell Labs من المشروع، بدأ عدد من الباحثين، وعلى رأسهم Ken Thompson وDennis Ritchie، في التفكير بنظام أبسط وأخف، مستفيدين من الأفكار الناجحة في MULTICS ولكن بصورة عملية أقل تكلفة. ومن هنا بدأت البذور الأولى لنظام Unix.

البدايات مع لغة التجميع Assembly
في المراحل الأولى، كُتب جزء كبير من نظام Unix بلغة Assembly بسبب محدودية العتاد آنذاك، خصوصاً على جهاز DEC PDP-7. كانت هذه اللغة تمنح تحكماً مباشراً في الذاكرة والمعالج، لكنها صعبة الصيانة، وغير قابلة للنقل بسهولة بين الأجهزة المختلفة.

من BCPL وB إلى ولادة C
احتاج الفريق إلى لغة أعلى مستوى من Assembly وأكثر كفاءة من البدائل المتاحة آنذاك. جرى أولاً استخدام لغة BCPL، ثم طوّر Ken Thompson لغة B استناداً إليها. لكن لغة B لم تكن قوية بما يكفي للاستفادة الكاملة من قدرات جهاز PDP-11.
عندها جاء دور Dennis Ritchie الذي طوّر لغة C في أوائل السبعينيات، لتجمع بين قوة الأداء وقربها من العتاد، وبين مرونة اللغات الأعلى مستوى.

انتشار اللغة وتوحيد المعيار
في عام 1973 أُعيدت كتابة أجزاء كبيرة من شيفرة Unix بلغة C، وهو ما منح النظام قابلية نقل أعلى بين المنصات المختلفة. ومع تزايد شعبية اللغة، ظهرت نسخ متعددة من المترجمات، فبرزت الحاجة إلى توحيد معيار رسمي.
لهذا تشكّلت لجنة ANSI في عام 1983، وأُصدر معيار ANSI C المعروف باسم C89. ثم تبعته معايير أخرى مثل C90 وC99 وC11 وC17.

أهم خصائص لغة C
1. فهم أعمق لكيفية عمل الحاسوب
تساعدك لغة C على استيعاب الذاكرة، والمؤشرات، وطريقة تنفيذ التعليمات، وكيفية تعامل البرنامج مع النظام. لهذا تُعد مدخلاً ممتازاً لمن يريد بناء أساس قوي في علوم الحاسوب.
2. سرعة وكفاءة عالية
تقترب لغة C كثيراً من طبقة العتاد، وهذا ما يجعلها فعالة جداً من ناحية الأداء. لذلك تُستخدم في التطبيقات التي تتطلب سرعة عالية أو استهلاكاً منخفضاً للموارد.
3. مرونة وتحكم مباشر
تمنح اللغة المبرمج قدرة كبيرة على إدارة الذاكرة والتعامل مع البيانات بدقة. هذه القوة مفيدة، لكنها تتطلب انضباطاً وفهماً جيداً لتجنب الأخطاء.
4. قابلية النقل
برامج C يمكن ترجمتها على أنظمة متعددة مع تعديلات محدودة، وهو ما جعلها خياراً مثالياً لبناء البرمجيات القابلة للعمل على منصات متنوعة.
5. تأثيرها على اللغات الحديثة
فهمك لبنية لغة C يسهل عليك تعلم لغات أخرى استلهمت منها مفاهيم الصياغة، وأنواع البيانات، والعوامل، والتحكم في التدفق.
أين تُستخدم لغة C؟
لغة C ليست مجرد لغة أكاديمية، بل تقف وراء عدد ضخم من الأنظمة والأجهزة التي نستخدمها يومياً. من أبرز مجالات استخدامها:
- أنظمة التشغيل مثل
Linuxوأجزاء منWindowsوmacOS. - تطوير النواة
Kernel Development. - الأنظمة المضمنة مثل الأجهزة المنزلية الذكية، والكاميرات، وأجهزة التتبع.
- المترجمات والمفسرات والأدوات البرمجية.
- قواعد البيانات مثل
MySQLوOracle. - المتصفحات وبعض أنظمة الملفات ومحركات الرسوميات.
- البرمجيات الصناعية والطبية والروبوتات والسيارات.
ما هو برنامج C؟
برنامج C هو ملف نصي عادي يحتوي على تعليمات مكتوبة بصياغة مفهومة للبشر، ثم يجري تحويلها إلى صيغة ثنائية يفهمها الحاسوب. كل لغة برمجة تفرض قواعدها الخاصة، ولغة C تعتمد على كلمات محجوزة، وقيم ثابتة، ومعرّفات يحددها المبرمج مثل أسماء المتغيرات والدوال.
ما هو المترجم Compiler؟
الحاسوب لا يفهم الشيفرة المكتوبة مباشرة، بل يفهم اللغة الثنائية فقط. هنا يأتي دور المترجم Compiler، وهو برنامج يحوّل الشيفرة المصدرية إلى تعليمات قابلة للتنفيذ.
لغة C لغة مترجمة، أي أن الشيفرة تُحوَّل أولاً إلى برنامج تنفيذي قبل تشغيلها، بخلاف اللغات المفسّرة التي تُنفَّذ تعليماتها سطراً بسطر أثناء التشغيل.
استخدام مترجم GCC لتشغيل برامج C
في أنظمة Linux وmacOS يتوفر غالباً مترجم GCC أو يمكن تثبيته بسهولة. وللتأكد من وجوده، استخدم الأمر التالي داخل الطرفية:
gcc --version

إنشاء مشروع بسيط
يمكنك إنشاء ملف أولي لتجربة اللغة بالأوامر التالية:
cd
mkdir cprogram
cd cprogram
touch hello.c
code .
هذا ينشئ مجلداً باسم cprogram وملفاً باسم hello.c ثم يفتحه في VS Code.
مراحل ترجمة برنامج C
عندما تشغّل الأمر gcc hello.c فأنت لا تقوم بخطوة واحدة فقط، بل بسلسلة من المراحل الداخلية:
- المعالجة المسبقة
Preprocessing - الترجمة إلى
Assembly - التجميع
Assembling - الربط
Linking
1. المعالجة المسبقة Preprocessing
في هذه المرحلة يتم التعامل مع التوجيهات التي تبدأ بالرمز # مثل #include. على سبيل المثال، عندما يقرأ المترجم السطر #include <stdio.h> فإنه يدرج محتوى الملف المطلوب قبل متابعة المراحل التالية.
كما تُزال التعليقات ويجري توسيع تعليمات macro إن وجدت.
gcc -E hello.c


2. الترجمة إلى لغة Assembly
بعد المعالجة المسبقة، تُحوَّل الشيفرة إلى ملف وسيط بلغة Assembly باستخدام أمر مثل:
gcc -S hello.c

3. التجميع Assembling
في هذه الخطوة تتحول تعليمات Assembly إلى ملف كائن Object File غالباً بامتداد .o. ويمكن تنفيذ ذلك بالأمر:
gcc -c hello.c

4. الربط Linking
أخيراً، تُربط ملفات الكائن مع المكتبات والملفات الأخرى لإنشاء ملف تنفيذي نهائي مثل a.out أو اسم مخصص تختاره أنت:
gcc -o hello hello.c
./hello


برنامج Hello World في لغة C
يُستخدم برنامج Hello World عادة كأول تجربة عملية للتأكد من إعداد البيئة البرمجية بشكل صحيح وفهم البنية الأساسية للغة.

#include <stdio.h>
int main(void)
{
// print hello world to the screen
printf("Hello world\n");
}
ما الذي يحدث داخل هذا البرنامج؟
#include <stdio.h>: يضيف مكتبة الإدخال والإخراج القياسية.int main(void): نقطة بداية تنفيذ البرنامج.//: بداية تعليق لا يُنفَّذ.printf(): دالة تطبع النص على الشاشة.\n: محرف هروب للانتقال إلى سطر جديد.
الملفات الرأسية Header Files
الملفات الرأسية هي ملفات تنتهي غالباً بالامتداد .h وتحتوي على تعريفات وتصريحات تمكّن برنامجك من استخدام دوال جاهزة. من أشهرها stdio.h التي تتيح دوال الإدخال والإخراج مثل printf().
المتغيرات في لغة C
المتغير هو مساحة في الذاكرة تحمل اسماً وتُستخدم لتخزين قيمة يمكن أن تتغير أثناء تنفيذ البرنامج. تخيّله كصندوق له اسم ومحتوى داخلي.
التصريح والإسناد والتهيئة
#include <stdio.h>
int main(void)
{
int n = 27;
}
في المثال السابق:
int: نوع البيانات.n: اسم المتغير.=: عامل الإسناد.27: القيمة.
الفرق بين التصريح والتهيئة مهم:
int n; // declaration
int n = 27; // initialization
التصريح declaration يعني إنشاء المتغير وتحديد نوعه، أما التهيئة initialization فتعني منحه قيمة أولية عند إنشائه.
إعادة الإسناد
int age = 27;
age = 37;
قواعد تسمية المتغيرات
- يجب أن يبدأ الاسم بحرف أو بشرطة سفلية
_. - يمكن أن يحتوي على أحرف وأرقام وشرطة سفلية فقط.
- الأسماء حساسة لحالة الأحرف، لذا
ageتختلف عنAge.
نطاق المتغير Scope
يشير النطاق إلى المكان الذي يكون فيه المتغير مرئياً وقابلاً للاستخدام.
- نطاق محلي: إذا كان داخل دالة أو كتلة
{}. - نطاق عام: إذا عُرِّف خارج الدوال.
أنواع البيانات الأساسية في لغة C
تحدد أنواع البيانات شكل القيم التي يخزنها البرنامج وحجم الذاكرة المخصصة لها. فيما يلي أشهر الأنواع:
| النوع | الوصف المختصر |
|---|---|
char |
لتخزين حرف واحد. |
int |
لتخزين الأعداد الصحيحة. |
short int |
عدد صحيح بحجم أصغر. |
long int |
عدد صحيح بحجم أكبر. |
long long int |
لتخزين أعداد صحيحة كبيرة جداً. |
float |
عدد عشري بدقة مفردة. |
double |
عدد عشري بدقة أعلى. |
long double |
عدد عشري بحجم أكبر. |
void |
يعني عدم وجود قيمة. |
يمكن أيضاً استخدام المعدّلين signed وunsigned لتغيير نطاق القيم الممكنة لبعض الأنواع.
رموز التنسيق في printf()
تُستخدم رموز التنسيق لتحديد نوع البيانات التي ستُطبع:
#include <stdio.h>
int main(void)
{
int age = 27;
printf("My age is %i\n", age);
}
| رمز التنسيق | نوع البيانات |
|---|---|
%c |
char |
%i أو %d |
int |
%u |
unsigned int |
%f |
float |
%lf |
double |
%Lf |
long double |
العوامل Operators في لغة C
العوامل الحسابية
+للجمع-للطرح*للضرب/للقسمة%لإيجاد باقي القسمة
عامل الإسناد
العامل = يضع قيمة في متغير. وهناك صيغ مختصرة للتحديث مثل:
x = x + 1x += 1x++
وبالمثل يمكن استخدام -- أو -= للتنقيص.
العوامل المنطقية
&&: و المنطقيةAND||: أو المنطقيةOR!: النفي المنطقيNOT
عوامل المقارنة
>أكبر من>=أكبر من أو يساوي<أصغر من<=أصغر من أو يساوي==يساوي!=لا يساوي
الدوال Functions في لغة C
الدالة هي وحدة سلوكية قابلة لإعادة الاستخدام، تنفّذ مهمة محددة وقد تستقبل مدخلات وتعيد مخرجات.
مدخلات الدالة Arguments
المدخلات التي تستقبلها الدالة تسمى arguments. مثال:
printf("Hello world!");
النص داخل الأقواس هو وسيطة تُمرَّر إلى الدالة printf().
القيمة المعادة Return Value
بعض الدوال تطبع فقط، وبعضها تعيد قيمة يمكن تخزينها في متغير واستخدامها لاحقاً.
تعريف دالة في C
عند تعريف دالة نحتاج عادة إلى:
- نوع القيمة المعادة.
- اسم الدالة.
- المعاملات
parametersإن وجدت.
void say_hi(void)
{
printf("hello");
}
int square(int n)
{
return n * n;
}
استدعاء الدوال
#include <stdio.h>
int square(int x)
{
return x * x;
}
int main(void)
{
printf("%i\n", square(2));
printf("%i\n", square(4));
printf("%i\n", square(8));
}
التعابير المنطقية Boolean Expressions
التعبير المنطقي هو تعبير تكون نتيجته إما true أو false. في لغة C، تُعامل القيمة غير الصفرية على أنها صحيحة، بينما تمثل 0 القيمة الخاطئة.
تُستخدم هذه التعابير كثيراً في التحكم في التدفق، مثل الشروط والحلقات.
الجمل الشرطية Conditional Statements
تسمح الجمل الشرطية للبرنامج باتخاذ قرار وفقاً لنتيجة مقارنة معينة.
#include <stdio.h>
int main(void)
{
int x = 2;
int y = 3;
if (x < y)
{
printf("x is less than y");
}
}
يمكن استخدام else وelse if لبناء فروع أكثر:
#include <stdio.h>
int main(void)
{
int x = 2;
int y = 2;
if (x < y)
{
printf("x is less than y");
}
else if (x > y)
{
printf("x is greater than y");
}
else
{
printf("x is equal to y");
}
}
الحلقات Loops في لغة C
الحلقة تتيح تكرار مجموعة تعليمات عدة مرات وفق شرط معين.
حلقة while
#include <stdio.h>
int main(void)
{
int i = 0;
while (i < 10)
{
printf("Hello world\n");
i++;
}
}
تتحقق حلقة while من الشرط أولاً، ثم تنفذ الكود إذا كان الشرط صحيحاً.
حلقة do-while
#include <stdio.h>
int main(void)
{
int i = 10;
do
{
printf("the value of i: %i\n", i);
i++;
}
while (i < 20);
}
هذه الحلقة تنفذ الكود مرة واحدة على الأقل، ثم تتحقق من الشرط.
نصائح عملية للمبتدئين في تعلم C
- ابدأ ببرامج صغيرة جداً وركّز على فهم الأساسيات قبل الانتقال إلى المؤشرات وإدارة الذاكرة.
- جرّب كتابة الشيفرة بنفسك بدلاً من الاكتفاء بالقراءة.
- افهم أخطاء المترجم جيداً، فهي جزء أساسي من عملية التعلم.
- تعلّم الفرق بين التصريح
declarationوالتهيئةinitializationونطاق المتغيراتscope. - مارس بناء دوال بسيطة، ثم انتقل إلى المشاريع الصغيرة مثل الآلة الحاسبة النصية أو برامج معالجة النصوص.
مصادر مقترحة للاستمرار
- كتاب
The C Programming Language. - كتاب
Programming in C. - دورات تمهيدية في علوم الحاسوب مثل
CS50. - فيديوهات تطبيقية تشرح لغة
Cخطوة بخطوة.
الخلاصة التقنية
لغة C ليست مجرد لغة برمجة قديمة، بل هي حجر أساس لفهم البرمجة من منظور عميق وعملي. تعلّمها يمنحك تصوراً أوضح عن طريقة عمل الحاسوب، ويقوّي قدرتك على فهم الذاكرة، والأداء، وبنية الأنظمة. قد تبدو أصعب من بعض اللغات الحديثة في البداية، لكنها من أكثر اللغات فائدة لمن يريد بناء قاعدة تقنية صلبة والانطلاق لاحقاً إلى مجالات متقدمة مثل الأنظمة المضمنة، وأنظمة التشغيل، والمترجمات.