C: البنية الأساسية
تعلّم بنية C الأساسية أشبه بتعلّم ضربات الحروف الصينية — أفقي، عمودي، انحناء يسار، انحناء يمين تبدو بسيطة، لكن كل قطعة كتابة جميلة مبنية منها.
1. بنية البرنامج
كل برنامج C يتقاسم هيكلًا ثابتًا. مهما تعقّد البرنامج، تبقى البنية الأساسية كما هي:
#include <stdio.h>
int main(void) {
return 0;
}
هذا هو أصغر برنامج C صالح — لا يفعل شيئًا، لكن بنيته مكتملة. لنشرحه:
(1) توجيهات المعالج الأولي
#include <stdio.h> هي توجيه معالج أولي. تبدأ بـ # وتُعالج قبل الترجمة.
#include— يُدرج محتوى ملف الرأس المحدد في هذا الموضع<stdio.h>— ملف رأس الإدخال/الإخراج القياسي، يحتوي على تعريفات printf و scanf وغيرهما من الدوال- أقواس الزاوية
<>تخبر المعالج بالبحث عن الرأس في مجلدات النظام
ستواجه ملفات رأس أخرى شائعة أيضًا:
| ملف الرأس | ما يوفّره |
|---|---|
<stdio.h> |
الإدخال/الإخراج (printf، scanf) |
<stdlib.h> |
أدوات عامة (malloc، exit) |
<math.h> |
الدوال الحسابية (sqrt، sin) |
<string.h> |
عمليات السلاسل (strlen، strcpy) |
<ctype.h> |
تصنيف الأحرف (isdigit، toupper) |
(2) الدالة main
int main(void) {
return 0;
}
int— الدالة تُرجع عددًا صحيحًاmain— اسم الدالة؛ تُحدد C أن تنفيذ البرنامج يبدأ من الدالة main(void)— قائمة مُعاملات فارغة، تعني أن الدالة لا تأخذ وسيطات{ }— جسم الدالة، محاط بأقواس معقوفةreturn 0— يُرجع 0 للدلالة على أن البرنامج انتهى بشكل طبيعي
main هي نقطة الدخول الوحيدة لبرنامج C. لا يمكنك امتلاك إلا دالة main واحدة — نظام التشغيل يستدعيها لبدء برنامجك.
(3) صيغ أخرى لـ main
قد ترى صيغة مختلفة لـ main في بعض الكتب:
int main(int argc, char *argv[])
هذه الصيغة يمكنها استقبال وسيطات سطر الأوامر، التي سنتناولها بالتفصيل لاحقًا. حاليًا، int main(void) هو كل ما تحتاجه.
void main(). هذا ليس معيار C وبعض المترجمات ستحذّر منه. استخدم دائمًا int main(void).
2. العبارات والفواصل المنقوطة
في C، الفاصلة المنقوطة ; تُحدّد نهاية العبارة. فكّر فيها كنقطة في نهاية الجملة — كما تحتاج الجملة نقطة، تحتاج العبارة فاصلة منقوطة.
int age = 18;
age = age + 1;
printf("عمري %d سنة\n", age);
كل سطر هو عبارة، ينتهي بفاصلة منقوطة.
خطأ شائع — نسيان الفاصلة المنقوطة:
int age = 18
المترجم لا يتعرّف على "أسطر جديدة" — بل يتعرّف فقط على الفواصل المنقوطة. نظريًا، يمكنك كتابة كل الشفرة في سطر واحد:
int age = 18; age = age + 1; printf("%d\n", age);
رغم أن هذا صالح لغويًا، إلا أنه لا يُنصح به أبدًا. أسلوب الشفرة الجيد يضع عبارة واحدة في كل سطر.
;
مفيدة في بعض الحالات الخاصة (مثل جسم حلقة فارغ)، لكن لا تحتاج للقلق بشأنها الآن.
3. كتل الشفرة
مجموعة من العبارات محاطة بأقواس معقوفة {} تكوّن كتلة شفرة (تُسمّى أيضًا عبارة مركّبة):
int main(void) {
int x = 10;
int y = 20;
int sum = x + y;
printf("المجموع = %d\n", sum);
return 0;
}
جسم الدالة main بالكامل هو كتلة شفرة واحدة. كتل الشفرة تُحدّد نطاق المتغير — المتغيرات المُعرّفة داخل كتلة لا يمكن الوصول إليها من خارجها.
كتل الشفرة يمكن أن تتداخل:
int main(void) {
int a = 1;
{
int b = 2;
printf("a + b = %d\n", a + b);
}
return 0;
}
الكتلة الداخلية يمكنها الوصول إلى a الخارجي، لكن الكتلة الخارجية لا يمكنها الوصول إلى b الداخلي.
4. دالة printf
printf هي دالة الإخراج الأكثر استخدامًا في C. الاسم مشتق من print formatted.
(1) الاستخدام الأساسي
printf("مرحباً بالعالم!\n");
المحتوى داخل علامتي الاقتباس المزدوجة يُسمّى سلسلة التنسيق ويُطبع كما هو (باستثناء محارف الهروب).
(2) محدّدات التنسيق
قوة printf تكمن في تنسيق قيم المتغيرات للإخراج:
int age = 18;
float height = 1.75f;
char grade = 'A';
printf("العمر: %d\n", age);
printf("الطول: %.2f\n", height);
printf("التقدير: %c\n", grade);
محدّدات التنسيق الشائعة:
| المحدّد | النوع | مثال على المخرجات |
|---|---|---|
%d |
int | 42 |
%f |
float / double | 3.140000 |
%.2f |
float (منزلتان عشريتان) | 3.14 |
%c |
char | A |
%s |
سلسلة نصية | hello |
%ld |
long | 100000 |
%x |
عدد صحيح سداسي عشري | 2a |
%o |
عدد صحيح ثماني | 52 |
%% |
علامة نسبة حرفية | % |
printf واحد — تقابل الوسيطات بالترتيب:
int a = 3, b = 4;
printf("%d + %d = %d\n", a, b, a + b);
(3) العرض والمحاذاة
printf("[%5d]\n", 42);
printf("[%-5d]\n", 42);
printf("[%05d]\n", 42);
[ 42]
[42 ]
[00042]
%5d— عرض أدنى 5، محاذاة لليمين%-5d— عرض أدنى 5، محاذاة لليسار%05d— عرض أدنى 5، حشو بالأصفار
5. محارف الهروب
بعض المحارف لا يمكن طباعتها مباشرة في سلسلة نصية (مثل سطر جديد أو جدولة)، لذا تُمثّل بـ محارف هروب تبدأ بشرطة مائلة خلفية \:
| محرف الهروب | المعنى | مثال |
|---|---|---|
\n |
سطر جديد | printf("A\nB") يطبع A و B في سطرين منفصلين |
\t |
جدولة أفقية | شائعة الاستخدام للإخراج المحاذى |
\\ |
شرطة مائلة خلفية حرفية | لطباعة \، اكتب \\ |
\" |
علامة اقتباس مزدوجة | لطباعة " داخل سلسلة نصية |
\' |
علامة اقتباس مفردة | لطباعة ' داخل حرف حرفي |
\0 |
المحرف الصفري | يُحدّد نهاية السلسلة النصية |
\r |
إرجاع المؤشر | ينقل المؤشر إلى بداية السطر |
\b |
تراجع | ينقل المؤشر موضعًا واحدًا لليسار |
printf("C:\\Users\\admin\\file.txt\n");
C:\Users\admin\file.txt
6. التعليقات
التعليقات هي ملاحظات للبشر — المترجم يتجاهلها تمامًا. التعليقات الجيدة تجعل الشفرة أسهل فهمًا.
(1) تعليقات سطر واحد
أدخل C99 تعليقات سطر واحد بأسلوب //. كل شيء من // إلى نهاية السطر هو تعليق:
int score = 100;
(2) تعليقات متعددة الأسطر
التعليقات بأسلوب /* */ يمكنها أن تمتد عبر عدة أسطر:
/*
* هذا البرنامج يحسب
* مجموع عددين
*/
#include <stdio.h>
int main(void) {
int a = 10;
int b = 20;
printf("%d\n", a + b);
return 0;
}
(3) أفضل ممارسات التعليقات
يجب أن تشرح التعليقات لماذا (السبب)، لا ماذا (الواضح). الشفرة نفسها تخبرك بماذا — التعليقات يجب أن تُضيف القصد التصميمي والقرارات التي لا تستطيع الشفرة التعبير عنها.
تعليق جيد:
int max_retries = 3;
تعليق غير ضروري (الشفرة تشرح كل شيء بالفعل):
int x = 10;
/*
/* تعليق متداخل */
*/
الـ */ الداخلية تُغلق التعليق الخارجي قبل أوانه، تاركة الـ */ المتبقية كخطأ في الصياغة.
7. المُعرّفات والكلمات المفتاحية
(1) قواعد تسمية المُعرّفات
المُعرّفات هي الأسماء التي تنشئها بنفسك (أسماء المتغيرات، أسماء الدوال، إلخ). يجب أن تتبع هذه القواعد:
- يمكن أن تحتوي فقط على أحرف (a-z، A-Z) وأرقام (0-9) وشرطات سفلية (_)
- يجب أن تبدأ بحرف أو شرطة سفلية — لا يمكن أن تبدأ برقم
- حساسة لحالة الأحرف (
ageوAgeمُعرّفان مختلفان) - لا يمكن استخدام كلمات C المفتاحية
أسماء صالحة: age، student_name، _count، MAX_SIZE
أسماء غير صالحة: 2name (تبدأ برقم)، my-age (تحتوي على شرطة)، int (كلمة مفتاحية)
(2) اصطلاحات التسمية
| الأسلوب | الصيغة | حالة الاستخدام | مثال |
|---|---|---|---|
| snake_case | أحرف صغيرة + شرطات سفلية | أسماء المتغيرات، أسماء الدوال | student_count |
| UPPER_CASE | أحرف كبيرة + شرطات سفلية | الثوابت | MAX_BUFFER_SIZE |
| CamelCase | حرف كبير لبداية كل كلمة | أسماء الأنواع المخصصة | StudentInfo |
C تقليديًا تستخدم snake_case، بخلاف Java/C# التي تفضّل camelCase. الأهم هو الاتساق داخل المشروع.
(3) كلمات C99 المفتاحية
C99 تمتلك 37 كلمة مفتاحية، جميعها بأحرف صغيرة:
| الفئة | الكلمات المفتاحية |
|---|---|
| أنواع البيانات | char short int long float double void signed unsigned _Bool _Complex _Imaginary |
| سير التحكم | if else switch case default for while do break continue goto return |
| أصناف التخزين | auto extern static register typedef inline |
| البُنى | struct union enum |
| أخرى | const volatile sizeof restrict |
لا تحتاج لحفظها — ستصبح طبيعة ثانية مع الممارسة. المهم أن تعرف أن الكلمات المفتاحية لا يمكن استخدامها كمُعرّفات.
▶ مثال
لنجمّع كل شيء من هذا الفصل في برنامج يُظهر البنية الأساسية:
#include <stdio.h>
int main(void) {
printf("=== معلومات الطالب ===\n");
printf("الاسم:\t%s\n", "أحمد");
printf("العمر:\t%d\n", 20);
printf("الدرجة:\t%.1f\n", 95.5);
printf("التقدير:\t%c\n", 'A');
printf("======================\n");
return 0;
}
=== معلومات الطالب ===
الاسم: أحمد
العمر: 20
الدرجة: 95.5
التقدير: A
======================
يُظهر هذا البرنامج: توجيه المعالج الأولي #include، بنية الدالة main، إخراج printf المنسّق، سطر جديد \n، محاذاة الجدولة \t، وأربع محدّدات تنسيق شائعة (%d، %.1f، %c، %s).
❓ أسئلة شائعة
📖 ملخص
- هيكل برنامج C: رأس
#include+ دالةint main(void)+return 0 - الفواصل المنقوطة تُحدّد نهاية العبارات؛ كل عبارة يجب أن تنتهي بواحدة
- الأقواس المعقوفة
{}تكوّن كتل شفرة وتُحدّد نطاق المتغيرات - printf يستخدم محدّدات التنسيق لإخراج أنواع بيانات مختلفة:
%d،%f،%c،%s - محارف الهروب تبدأ بـ
\:\nلسطر جديد،\tلجدولة،\\لشرطة مائلة خلفية حرفية
📝 تمارين
- اكتب برنامجًا يستخدم printf لعرض بطاقتك الشخصية (الاسم، العمر، الهواية)، باستخدام
\tللمحاذاة - اكتب برنامجًا يستدعي printf مرة واحدة فقط لإخراج التالي (باستخدام محارف الهروب للأسطر الجديدة والجدولة): الاسم أحمد، العمر 25، المدينة القاهرة
- اكتب عمدًا تعليقًا متعدد الأسطر متداخلًا في شفرتك ولاحظ رسالة خطأ المترجم