مقدمة
في
تعليقاتي ، أشرت عدة مرات إلى كتاب أندرو تانباوم لتصميم وتنفيذ أنظمة التشغيل ،
ونسخته الأولى ، وكيف يتم تمثيل C فيه. وكانت هذه التعليقات دائما موضع اهتمام. قررت أن الوقت قد حان لنشر ترجمة لهذه المقدمة إلى C. انها لا تزال ذات صلة. على الرغم من أن هناك بالتأكيد أولئك الذين لم يسمعوا عن لغة البرمجة
PL / 1 ، وربما حتى عن نظام التشغيل
Minix .
هذا الوصف مثير للاهتمام أيضًا من الناحية التاريخية وفهم المدى الذي قطعته لغة C منذ نشأتها وصناعة تكنولوجيا المعلومات ككل.
أريد أن أحجز على الفور أن لغتي الثانية هي الفرنسية:

ولكن هذا يقابله 46 عاما من
الخبرة في البرمجة .
لذا ، دعونا نبدأ ، لقد حان دور أندرو تانباوم.
مقدمة في لغة C (ص. 350 - 362)
تم إنشاء لغة البرمجة C بواسطة Dennis Ritchie من AT&T Bell Laboratories كلغة برمجة عالية المستوى لتطوير نظام التشغيل UNIX. حاليا ، تستخدم اللغة على نطاق واسع في مختلف المجالات. يحظى C بشعبية خاصة لدى مبرمجي النظام لأنه يتيح لك كتابة البرامج ببساطة ودقة.
الكتاب الرئيسي الذي يصف لغة C هو كتاب Brian Kernigan وكتاب Dennis Ritchie بعنوان C Programming Language (1978). كتب بولون (1986) و Gehani (1984) و Hancock و Krieger (1986) و Harbison and Steele (1984) وكتبًا أخرى كتبًا عن اللغة C.
في هذا التطبيق ، سنحاول تقديم مقدمة كاملة إلى حد ما إلى C ، حتى يتمكن أولئك الذين هم على دراية باللغات عالية المستوى مثل Pascal أو PL / 1 أو Modula 2 من فهم معظم كود MINIX الوارد في هذا الكتاب. لا تتم مناقشة الميزات C غير المستخدمة في MINIX هنا. تم حذف العديد من النقاط الدقيقة. ينصب التركيز على قراءة برامج C ، بدلاً من كتابة التعليمات البرمجية.
A.1. أساسيات اللغة C
يتكون البرنامج C من مجموعة من الإجراءات (غالبًا ما تسمى الوظائف ، حتى لو لم تُرجع القيم). تحتوي هذه الإجراءات على إعلانات ومشغلين وعناصر أخرى تخبر الكمبيوتر معًا بما يجب القيام به. يوضح الشكل A-1 إجراءًا صغيرًا يتم فيه الإعلان عن ثلاثة متغيرات عدد صحيح وتخصيص قيم لها. اسم الإجراء هو الرئيسي. لا يحتوي الإجراء على معلمات رسمية ، كما يتضح من عدم وجود أي معرفات بين الأقواس الموجودة خلف اسم الإجراء. نص الإجراء محاط بأقواس ({}). يوضح هذا المثال أن C تحتوي على متغيرات ، ويجب الإعلان عن هذه المتغيرات قبل الاستخدام. لدى C أيضًا عوامل تشغيل ، في هذا المثال ، تكون هذه هي عوامل التعيين. يجب أن تنتهي جميع العبارات بفاصلة منقوطة (على عكس Pascal ، والذي يستخدم نقطتين بين الجمل ، وليس بعدهما).
تبدأ التعليقات بالأحرف "/ *" وتنتهي بالأحرف "* /" ويمكن أن تمتد إلى عدة أسطر.
main () { int i, j, k; i = 10; j = i + 015; k = j * j + 0xFF; } . Al. .
يحتوي الإجراء على ثلاثة ثوابت. ثابت 10 في المهمة الأولى
إنه ثابت عشري عادي. ثابت 015 هو ثابت ثماني
(يساوي 13 في العشرية). الثوابت الثماني دائما تبدأ من الصفر. ثابت 0xFF ثابت ست عشرية (يساوي 255 عشري). دائمًا ما تبدأ الثوابت الست عشرية بـ 0x. تستخدم الأنواع الثلاثة في C.
A.2. أنواع البيانات الأساسية
يحتوي C على نوعين رئيسيين من البيانات (المتغيرات): عدد صحيح وحرف ، تم إعلانهما int و char ، على التوالي. لا يوجد متغير منطقي منفصل. يستخدم المتغير int كمتغير منطقي. إذا كان هذا المتغير يحتوي على 0 ، فهذا يعني false / false ، وأي قيمة أخرى تعني true / true. يحتوي C أيضًا على أنواع الفاصلة العائمة ، لكن MINIX لا تستخدمها.
يمكنك تطبيق "صفات" قصيرة أو طويلة أو غير موقعة على نوع int يحدد نطاق القيم (نطاق يعتمد على المترجم). تستخدم معظم معالجات 8088 أعداد صحيحة 16 بت للأعداد الصحيحة int و short و 32 بت لـ int طويلة. يتراوح عدد الأعداد الصحيحة غير الموقعة (int غير الموقعة) على معالج 8088 من 0 إلى 65535 ، وليس من -32768 إلى +32767 ، كما هو الحال مع الأعداد الصحيحة الصحيحة (int). شخصية تأخذ 8 بت.
يُسمح أيضًا بمحدِّد السجل لكلٍ من int و char ، ويُعد تلميحًا إلى المحول البرمجي بضرورة وضع المتغير المُعلن في السجل حتى يعمل البرنامج بشكل أسرع.
تظهر بعض الإعلانات في الشكل. 2 -.
int i; short int z1, z2; / * */ char c; unsigned short int k; long flag_poll; register int r; . -2. .
يُسمح بالتحويل بين الأنواع. على سبيل المثال ، المشغل
flag_pole = i;
مسموح حتى لو كنت من النوع int و flag_pole طويلة. في كثير من الحالات
من الضروري أو المفيد فرض تحويلات بين أنواع البيانات. بالنسبة للتحويل القسري ، يكفي وضع النوع المستهدف بين قوسين أمام التعبير للتحويل. على سبيل المثال:
( (long) i);
يرشد إلى تحويل عدد صحيح i إلى وقت طويل قبل تمريره كمعلمة إلى الإجراء p ، الذي يتوقع المعلمة طويلة.
عند التحويل بين الأنواع ، انتبه إلى العلامة.
عند تحويل حرف إلى عدد صحيح ، تعامل بعض المترجمات الأحرف على أنها موقعة ، أي من - 128 إلى +127 ، بينما يعاملها الآخرون على أنها
غير موقعة ، أي من 0 إلى 255. في MINIX ، تعبيرات مثل
i = c & 0377;
الذي يحول من (حرف) إلى عدد صحيح ، ثم ينفذ AND
(علامة الضم) مع ثابت الثماني 0377. والنتيجة هي أن ارتفاع 8 بت
تم تعيينه على صفر ، مما يفرض c على اعتباره رقمًا غير موقَّعًا من 8 بتات ، في النطاق من 0 إلى 255.
A3. أنواع المركبات والمؤشرات
في هذا القسم ، سننظر في أربع طرق لإنشاء أنواع بيانات أكثر تعقيدًا: المصفوفات والهياكل والنقابات والمؤشرات. الصفيف هو مجموعة / مجموعة من العناصر من نفس النوع. جميع الصفائف في C تبدأ بالعنصر 0.
إعلان
int a [10];
يعلن الصفيف مع 10 أعداد صحيحة ليتم تخزينها في عناصر الصفيف من [0] إلى [9]. ثانياً ، يمكن أن تكون المصفوفات من ثلاثة أبعاد أو أكثر ، ولكنها غير مستخدمة في MINIX.
البنية عبارة عن مجموعة من المتغيرات ، عادةً من أنواع مختلفة. يشبه الهيكل في C السجل في Pascal. عامل
struct {int i; char c;} s;
تعلن s كهيكل يحتوي على عضوين ، الأعداد الصحيحة i والحرف c.
لتعيين العضو i في البنية s إلى 6 ، اكتب التعبير التالي:
si = 6;
حيث يشير مشغل النقطة إلى أن العنصر i ينتمي إلى البنية s.
الاتحاد هو أيضًا مجموعة من الأعضاء ، على غرار الهيكل ، باستثناء أنه في أي لحظة يمكن أن يكون واحد منهم فقط في اتحاد. إعلان
union {int i; char c;} u;
يعني أنه يمكنك الحصول على عدد صحيح أو حرف ، ولكن ليس كلاهما. يجب على المحول البرمجي تخصيص مساحة كافية للجمع بحيث يمكنه استيعاب أكبر عنصر تجميع (من وجهة نظر الذاكرة المشغولة). يتم استخدام النقابات في مكانين فقط في MINIX (لتعريف الرسالة على أنها وحدة من عدة هياكل مختلفة ، ولتعريف كتلة القرص على أنها وحدة كتلة البيانات ، كتلة i-node ، كتلة الكتالوج ، إلخ).
يتم استخدام المؤشرات لتخزين عناوين الجهاز في C. يتم استخدامها في كثير من الأحيان. يتم استخدام العلامة النجمية (*) للإشارة إلى مؤشر في الإعلانات. إعلان
int i, *pi, a [10], *b[10], **ppi;
تعلن عن عدد صحيح i ، مؤشر إلى رقم صحيح pi ، صفيف a من 10 عناصر ، صفيف b من 10 مؤشرات إلى أعداد صحيحة ، ومؤشر إلى مؤشر ppi إلى عدد صحيح.
قواعد بناء الجملة الدقيقة للإعلانات المعقدة التي تجمع بين المصفوفات والمؤشرات وأنواع أخرى معقدة إلى حد ما. لحسن الحظ ، تستخدم MINIX إعلانات بسيطة فقط.
يوضح الشكل A-3 إعلان صفيف z لهياكل جدول الهيكل ، لكل منها
ثلاثة أعضاء ، عدد صحيح i ، مؤشر cp للحرف والحرف c.
struct table { int i; / * */ char *cp, c; } z [20]; . - 3. .
صفائف الهياكل شائعة في MINIX. علاوة على ذلك ، يمكن تعريف جدول الاسم كهيكل جدول هيكلي يمكن استخدامه في الإعلانات اللاحقة. على سبيل المثال
register struct table *p;
تعلن p مؤشر إلى بنية جدول هيكلي وتقترح حفظه
في السجل. أثناء تنفيذ البرنامج ، يمكن أن تشير p ، على سبيل المثال ، z [4] أو
إلى أي عنصر آخر في z ، وكلها 20 عنصرًا هي بنيات جدول نوع الكتابة.
لجعل p مؤشر إلى z [4] ، اكتب فقط
p = &z[4];
حيث علامة الضم كعامل أحادي (أحادي) تعني "تأخذ عنوان ما يليه." انسخ قيمة العضو i إلى عدد صحيح متغير n
يمكن أن تتم البنية المشار إليها بواسطة p كما يلي:
n = p->i;
لاحظ أنه يتم استخدام السهم للوصول إلى عضو في الهيكل من خلال مؤشر. إذا استخدمنا المتغير z ، فعلينا استخدام عامل التشغيل dot:
n = z [4] .i;
الفرق هو أن z [4] عبارة عن بنية ، ويقوم عامل النقطة بتحديد العناصر
من الأنواع المركبة (الهياكل ، المصفوفات) مباشرة. باستخدام المؤشرات ، لا نختار مشاركًا مباشرةً. يرشد المؤشر إلى تحديد بنية أولاً ثم تحديد عضو في هذه البنية فقط.
في بعض الأحيان يكون من المناسب إعطاء اسم لنوع مركب. على سبيل المثال:
typedef unsigned short int unshort;
يعرّف unshort بأنها قصيرة غير موقعة (عدد صحيح قصير غير موقّع). الآن يمكن استخدام unshort في البرنامج كنوع رئيسي. على سبيل المثال
unshort ul, *u2, u3[5];
تعلن عن عدد صحيح غير موقّع قصير ، ومؤشر إلى عدد صحيح غير موقّع قصير ، و
مجموعة من الأعداد الصحيحة قصيرة غير الموقعة.
A4. مشغلي
الإجراءات في C تحتوي على تصريحات وبيانات. لقد رأينا بالفعل التصريحات ، لذلك سننظر الآن في المشغلين. الغرض من العوامل الشرطية والحلقة هو نفسه كما هو الحال في لغات أخرى. يوضح الشكل أ - 4 عدة أمثلة عليها. الشيء الوحيد الذي يستحق الاهتمام هو أن الأقواس المتعرجة تستخدم لمشغلي المجموعة ، بينما يحتوي البيان على نموذجين ، يشبه الثاني بيان تكرار Pascal.
يحتوي C أيضًا على عبارة for ، لكنها لا تبدو وكأنها عبارة في أي لغة أخرى. يحتوي البيان على النموذج التالي:
for (<>; <>; <>) ;
يمكن التعبير عن نفس الشيء خلال بيان الوقت:
<> while(<>) { <>; <> }
كمثال ، خذ بعين الاعتبار العبارة التالية:
for (i=0; i <n; i = i+l) a[i]=0;
يقوم عامل التشغيل هذا بتعيين أول عناصر n للصفيف من a إلى صفر. يبدأ تنفيذ المشغل بتعيين i إلى صفر (يتم ذلك خارج الحلقة). ثم يتم تكرار المشغل حتى i <n ، أثناء أداء المهمة وزيادة i. بالطبع ، بدلاً من المشغل الذي يقوم بتعيين قيمة للعنصر الحالي لصفيف صفري ، قد يكون هناك عامل (كتلة) مركب محاط بأقواس مجعدة.
if (x < 0) k = 3; if (x > y) { i = 2; k = j + l, } if (x + 2 <y) { j = 2; k = j - 1; } else { m = 0; } while (n > 0) { k = k + k; n = n - l; } do { / * while */ k = k + k; n = n - 1; } while (n > 0); . A-4. if while C.
لدى C أيضًا مشغل مشابه لمشغل الحالات في Pascal. هذا هو بيان التبديل. يظهر مثال في الشكل A-5. اعتمادًا على قيمة التعبير المحدد في التبديل ، يتم تحديد بيان حالة واحد أو آخر.
إذا كان التعبير لا يتطابق مع أي من عبارات الحالة ، يتم تحديد العبارة الافتراضية.
إذا كان التعبير غير مرتبط بأي عبارات حالة والبيان الافتراضي غائب ، يستمر التنفيذ من العبارة التالية بعد بيان التبديل.
تجدر الإشارة إلى أنه للخروج من كتلة الحالة ، استخدم عبارة الاستراحة. إذا لم يكن هناك بيان فاصل ، سيتم تنفيذ فقرة الحالة التالية.
switch (k) { case 10: i = 6; break; case 20: i = 2; k = 4; break; / * default* / default: j = 5; } . A-5. switch
بيان فاصل يعمل أيضا داخل لوالأثناء الحلقات. يجب أن نتذكر أنه إذا كانت عبارة الاستراحة داخل سلسلة من الحلقات المتداخلة ، فإن المخرجات تكون في مستوى واحد فقط للأعلى.
بيان ذات الصلة هو بيان المتابعة ، الذي لا يخرج من الحلقة ،
ولكن يسبب الانتهاء من التكرار الحالي وبداية التكرار التالي
على الفور. هذا هو في الأساس عودة إلى الجزء العلوي من الحلقة.
يحتوي C على إجراءات يمكن استدعاءها مع أو بدون معلمات.
وفقًا لكيرنيجان وريتشي (ص 121) ، لا يُسمح بنقل الصفائف ،
الهياكل أو الإجراءات كمعلمات ، على الرغم من تمرير المؤشرات إلى كل هذا
وسمحت. هل يوجد كتاب أم لا (سينبثق في ذاكرتي: - "إذا كانت هناك حياة على كوكب المريخ ، إذا لم تكن هناك حياة على كوكب المريخ") ، فإن العديد من المترجمين C يسمحون للهياكل كمعلمات.
اسم الصفيف ، إذا كان مكتوبًا بدون فهرس ، يعني مؤشرًا إلى صفيف ، مما يسهل نقل مؤشر الصفيف. وبالتالي ، إذا كان a هو اسم صفيف من أي نوع ، فيمكن نقله إلى g بالكتابة
g();
تنطبق هذه القاعدة على المصفوفات فقط ؛ ولا تنطبق هذه القاعدة على الهياكل.
يمكن للإجراءات إرجاع القيم عن طريق تنفيذ بيان الإرجاع. قد يحتوي هذا البيان على تعبير ، سيتم إرجاع نتائجه كقيمة للإجراء ، ولكن يمكن للمتصل تجاهل قيمة الإرجاع بأمان. إذا قام الإجراء بإرجاع قيمة ، فيتم كتابة قيمة الكتابة قبل اسم الإجراء ، كما هو موضح في الشكل. A-6. مثل المعلمات ، لا تستطيع الإجراءات إرجاع المصفوفات أو الهياكل أو الإجراءات ، ولكن يمكنها إرجاع المؤشرات إليها. تم تصميم هذه القاعدة من أجل تنفيذ أكثر كفاءة - تتوافق جميع المعلمات والنتائج دائمًا مع كلمة آلة واحدة (يتم تخزين العنوان فيها). المترجمون الذين يسمحون باستخدام الهياكل كمعلمات عادة ما يسمحون أيضًا باستخدامها كقيم إرجاع.
int sum (i, j) int i, j ; { return (i + j); } . -6. , .
C لا يوجد لديه المدمج في I / O. يتم تنفيذ المدخلات / المخرجات عن طريق استدعاء وظائف المكتبة ، وأكثرها شيوعا موضحة أدناه:
printf («x=% dy = %oz = %x \n», x, y, z);
المعلمة الأولى هي سلسلة الأحرف بين علامات اقتباس (في الواقع ، هذه مجموعة من الأحرف).
أي حرف لا يمثل نسبة مئوية يطبع ببساطة كما هو.
عند حدوث النسبة المئوية ، تتم طباعة المعلمة التالية في النموذج المحدد بواسطة الحرف الذي يتبع النسبة المئوية:
د - طباعة كعدد صحيح عشري
س - طباعة كعدد صحيح ثماني
ش - طباعة كعدد صحيح عشري غير موقعة
س - طباعة كعدد صحيح عرافة
s - طباعة كسلسلة من الأحرف
ج - طباعة كحرف واحد
يُسمح أيضًا بالحروف D و 0 و X للطباعة العشرية والثماني والسداسية عشرية للأرقام الطويلة.
A.5. التعبيرات
يتم إنشاء التعبيرات من خلال الجمع بين المعاملات والمعاملات.
العوامل الحسابية مثل + و - و العوامل العلائقية مثل <
و> مماثلة لنظرائهم في لغات أخرى. ٪ المشغل
استخدام معامل. تجدر الإشارة إلى أن عامل المساواة هو == ، ومشغل عدم المساواة هو! =. للتحقق مما إذا كانت أ و ب متساوية ، يمكنك كتابة مثل هذا:
if (a == b) <>;
C يتيح لك أيضًا دمج عامل التعيين مع المشغلين الآخرين ، لذلك
a += 4;
أي ما يعادل التسجيل
= + 4;
يمكن أيضًا الجمع بين المشغلين الآخرين بهذه الطريقة.
لدى C عوامل تشغيل لمعالجة أجزاء من الكلمة. كل التحولات والعمليات المنطقية bitwise مسموح بها. مشغلي التحول الأيمن والأيسر هم <<
و >> على التوالي. عوامل التشغيل المنطقية لـ Bitwise & | و ^ ، المنطقي AND (AND) ، بما في ذلك OR (OR) والحصري OR (XOP) ، على التوالي. إذا كان لدي قيمة 035 (ثماني) ، فإن التعبير i & 06 له القيمة 04 (ثماني). مثال آخر ، إذا كنت = 7 ، إذن
j = (i << 3) | 014;
واحصل على 074 لـ j.
مجموعة مهمة أخرى من المشغلين هي المشغلين الأحاديين ، يقبل كل منهم معامل واحد فقط. كمشغل أحادي ، يقوم علامة & يحصل على عنوان متغير.
إذا كان p هو مؤشر إلى عدد صحيح و i هو عدد صحيح ، فإن المشغل
p = &i;
يحسب العنوان i ويخزنه في المتغير p.
عكس أخذ عنوان هو عامل يأخذ المؤشر كمدخل ويحسب القيمة في ذلك العنوان. إذا قمنا بتخصيص العنوان i إلى المؤشر p ، فإن * p له نفس معنى i.
بمعنى آخر ، كمشغل أحادي ، يتبع النجمة مؤشر (أو
تعبير إعطاء مؤشر) وإرجاع قيمة العنصر الذي يشير إليه. إذا كان لدي قيمة 6 ، ثم المشغل
j = *;
سوف يعين ي الرقم 6.
المشغل! (علامة التعجب هي عامل التنفي) تُرجع 0 إذا كان معاملها غير صفري ، و 1 إذا كانت معاملتها تساوي 0.
يستخدم بشكل رئيسي في حالة البيانات ، على سبيل المثال
if (!x) k=0;
يتحقق قيمة س. إذا كانت x تساوي صفر (خطأ) ، عندئذ يتم تعيين القيمة 0 على k. في الواقع ، يكون العامل! يلغي الحالة التي تليها ، تمامًا مثل المشغل غير في Pascal.
عامل التشغيل ~ عامل مكمل bitwise. كل 0 في المعامل
يصبح 1 ، وكل 1 يصبح 0.
يبلغ مشغل sizeof عن حجم المعامل بالبايت. فيما يتعلق
صفيف من 20 عدد صحيح على جهاز كمبيوتر مع عدد صحيح 2 بايت ، على سبيل المثال sizeof سيكون لها قيمة 40.
المجموعة الأخيرة من المشغلين هي عوامل الزيادة والنقصان.
عامل
++;
يعني زيادة في ص. مقدار ص ستزداد يعتمد على نوعه.
أعداد صحيحة أو أحرف تزيد بمقدار 1 ، لكن مؤشرات زيادة بمقدار
حجم الكائن المشار إليه بهذه الطريقة ، إذا كان a a مجموعة من الهياكل ، و p هو مؤشر إلى أحد هذه الهياكل ، ونحن نكتب
p = &a[3];
لجعل ع نقطة إلى واحدة من الهياكل في مجموعة ، ثم بعد زيادة ص
سوف يشير إلى [4] بغض النظر عن حجم الهياكل. عامل
p--;
يشبه مشغل p ++ ، إلا أنه ينقص بدلاً من أن يزيد من قيمة المعامل.
في البيان
n = k++;
حيث كلا المتغيرين أعداد صحيحة ، يتم تعيين القيمة الأصلية k إلى n و
عندها فقط تزيد ك. في البيان
n = ++ k;
يزيد k أولاً ، ثم يتم تخزين قيمته الجديدة في n.
وبالتالي ، يمكن كتابة عامل التشغيل ++ (أو -) قبل أو بعد معامل التشغيل ، مما ينتج عنه قيم مختلفة.
البيان الأخير هو هذا؟ (علامة استفهام) التي تختار أحد البديلين
مفصولة القولون. على سبيل المثال ، المشغل ،
i = (x < y ? 6 : k + 1);
يقارن س مع ص. إذا كانت x أقل من y ، فعندئذ أحصل على القيمة 6 ؛ خلاف ذلك ، فإن المتغير i يحصل على القيمة k + 1. الأقواس اختيارية.
A6. هيكل البرنامج
يتكون البرنامج C من ملف واحد أو أكثر يحتوي على الإجراءات والإعلانات.
يمكن تجميع هذه الملفات بشكل فردي في ملفات الكائنات ، والتي يتم ربطها مع بعضها البعض (باستخدام رابط) لتشكيل برنامج قابل للتنفيذ.
بخلاف Pascal ، لا يمكن تداخل إعلانات الإجراءات ، لذلك تتم كتابتها جميعًا في "المستوى العلوي" في ملف البرنامج.
يُسمح بإعلان المتغيرات خارج الإجراءات ، على سبيل المثال ، في بداية الملف قبل الإعلان الأول للإجراء. هذه المتغيرات عالمية ، ويمكن استخدامها في أي إجراء خلال البرنامج ، ما لم تكن الكلمة الأساسية الثابتة تسبق الإعلان. في هذه الحالة ، لا يمكن استخدام هذه المتغيرات في ملف آخر. تنطبق نفس القواعد على الإجراءات. المتغيرات المعلنة داخل إجراء ما هي محلية للإجراء.
يمكن أن يصل الإجراء إلى عدد صحيح متغير v تم الإعلان عنه في ملف آخر (شريطة ألا يكون المتغير ثابتًا) ، معلنًا أنه خارجي:
extern int v;
يجب تعريف كل متغير عمومي مرة واحدة تمامًا بدون سمة extern من أجل تخصيص ذاكرة له.
يمكن تهيئة المتغيرات عند الإعلان عنها:
int size = 100;
يمكن أيضًا تهيئة المصفوفات والهياكل. المتغيرات العمومية التي لم تتم تهيئتها بشكل صريح تتلقى قيمة افتراضية هي صفر.
A7. ج المعالج
قبل نقل الملف المصدر إلى برنامج التحويل البرمجي C ، تتم معالجته تلقائيًا
برنامج يسمى المعالج. هذا هو إخراج المعالج ، لا
يتم تغذية البرنامج الأصلي إلى إدخال برنامج التحويل البرمجي. يؤدي المعالج
ثلاثة تحويلات أساسية في ملف قبل تمريرها إلى المترجم:
1. إدراج الملفات.
2. تعريف واستبدال وحدات الماكرو.
3. تجميع شرطي.
تبدأ جميع توجيهات المعالج الأولي بعلامة رقم (#) في العمود الأول.
عندما عرض التوجيه
#include "prog.h"
التقى قبل المعالج ، ويشمل ملف prog.h ، سطرا سطرا ، في
البرنامج ليتم تمريرها إلى المترجم. عندما يتم كتابة التوجيه #include كـ
#include <prog.h>
ثم يتم البحث في الملف المضمّن في الدليل / usr / include بدلاً من دليل العمل. من الممارسات الشائعة في C تجميع التصريحات التي تستخدمها عدة ملفات في ملف الرأس (عادةً مع اللاحقة .h) ، وإدراجها عند الضرورة.
يسمح المعالج المسبق أيضًا بتعريفات الماكرو. على سبيل المثال
#define BLOCK_SIZE 1024
يعرّف الماكرو BLOCK_SIZE ويعيّنه بقيمة 1024. من الآن فصاعدًا ،سيتماستبدال كل تواجد في سلسلة من 10 أحرف "BLOCK_SIZE" في الملف بسلسلة من 4 أحرف "1024" قبل أن يشاهد المترجم الملف بالبرنامج. حسب الاصطلاح ، تتم كتابة أسماء الماكرو بأحرف كبيرة. يمكن أن تحتوي وحدات الماكرو على معلمات ، لكن في الممارسة العملية قليل منها.الميزة الثالثة من المعالج الأولي هي الترجمة الشرطية. تحتوي MINIX على عدةأماكن حيث يتم كتابة التعليمات البرمجية خصيصًا للمعالج 8088 ، ويجب عدم تضمين هذا الرمز عند التحويل البرمجي لمعالج آخر. هذه الأقسام تبدو كالتالي: #ifdef i8088 < 8088> #endif
إذا تم تعريف الحرف i8088 ، فسيتم تضمين العبارات بين توجيهي المعالج السابق #ifdef i8088 و #endif في إخراج المعالج المسبق ؛ وإلا يتم تخطيها. استدعاء المترجم باستخدام الأمر cc -c -Di8088 prog.c
أو عن طريق تضمين بيان في البرنامج #define i8088
نحدد الرمز i8088 ، بحيث يتم تضمين كل الكود التابع لـ 8088. مع تطور MINIX ، قد تحصل على رمز خاص لـ 68000s ومعالجات أخرى سيتم معالجتها أيضًا.كمثال على كيفية عمل المعالج الأولي ، فكر في البرنامج الشكل. A-7 (a). يتضمن ملف prog.h واحد ، محتوياته كالتالي: int x; #define MAXAELEMENTS 100
تخيل أنه تم استدعاء المترجم بواسطة أمر cc -E -Di8088 prog.c
بعد مرور الملف من خلال المعالج الأولي ، سيكون الإخراج كما هو موضح في الشكل. A-7 (ب).هذا هو الإخراج ، وليس الملف المصدر ، الذي يعطى كمدخل إلى برنامج التحويل البرمجي C.
لاحظ أن المعالج الأولي قام بعمله وحذف جميع الأسطر التي تبدأ بعلامة #. إذا كان سيتم استدعاء المترجم مثل هذا cc -c -Dm68000 prog.c
ثم سيتم تضمين طباعة أخرى. إذا كان يطلق عليه مثل هذا: cc -c prog.c
ثم لن يتم تضمين الطباعة. (قد ينعكس القارئ على ما يمكن أن يحدث إذا تم استدعاء المترجم مع كل من أعلام -D-ags.)A8. التعابير
في هذا القسم ، سوف نلقي نظرة على العديد من التركيبات النموذجية لـ C ولكنها ليست شائعة في لغات البرمجة الأخرى. أولاً ، فكر في الحلقة: while (n--) *p++ = *q++;
عادة ما تكون المتغيرات p و q هما مؤشران للحرف ، و n هي عداد. تقوم الحلقة بنسخ سلسلة الحروف n من حيث تشير q إلى النقطة p. في كل تكرار للحلقة ، ينخفض العداد إلى أن يصل إلى 0 ، ويزداد كل مؤشر ، بحيث تشير إلى خلايا ذاكرة بالتسلسل برقم أعلى.تصميم مشترك آخر: for (i = 0; i < N; i++) a[i] = 0;
الذي يحدد أول عناصر N إلى 0. طريقة بديلة لكتابة هذه الحلقة هي كما يلي: for (p = &a[0]; p < &a[N]; p++) *p = 0;
في هذا البيان ، يتم تهيئة مؤشر عدد صحيح p للإشارة إلى عنصر الصفر الصفيف. تستمر الحلقة حتى تصل p إلى عنوان العنصر Nth للصفيف. يكون إنشاء المؤشر أكثر فاعلية من بناء الصفيف ، وبالتالي يتم استخدامه عادة.قد تظهر عوامل التشغيل في أماكن غير متوقعة. على سبيل المثال
if (a = f (x)) < >;
يقوم أولاً باستدعاء الدالة f ، ثم يعين نتيجة استدعاء الوظيفة ، ثميتحقق أخيرًا لمعرفة ما إذا كانت صحيحة (غير صفرية) أو خطأ (صفر). إذا كانت القيمة لا تساوي الصفر ، فإن الشرط يكون راضيًا. عامل
if (a = b) < >;
أيضًا ، أولاً ، قيمة المتغير b للمتغير a ، ثم يتحقق ما إذا كانت القيمة غير صفرية. وهذا المشغل مختلف تماما عن if (a == b) < >;
الذي يقارن اثنين من المتغيرات وينفذ المشغل إذا كانت متساوية.خاتمة
هذا كل شيء. لن تصدق كم استمتعت بإعداد هذا النص. كم تذكرت أنها مفيدة من لغة C نفسها. أتمنى أن تستمتع أيضًا بالانغماس في عالم اللغة C الرائع.