مقدمة: السؤال الرئيسي الذي يطرحه حتى المحترفون
\n\nهل تساءلت يومًا لماذا يبدأ كل برنامج في C++ بـ int main()، وليس بـ void main()؟ وماذا يحدث في الواقع عندما تكتب return 0؟ هذا السؤال هو من أشهر الأسئلة على Stack Overflow، حيث حصد آلاف المشاهدات ومئات التعليقات. قد يبدو موضوعًا بسيطًا، لكنه يخفي في طياته طبقة كاملة من التفاصيل الدقيقة التي تفصل بين C و C++، وكذلك بين المبتدئين والمطورين ذوي الخبرة.
في هذه المقالة، لن نقدم إجابة جافة فحسب. بل سنقوم بمقارنة المنهجيات في C و C++، ونحلل المعايير، ونعرض أمثلة حقيقية على الكود، ونشرح كيفية التعامل بشكل صحيح مع القيمة المُرجعة من main()، ليكون كودك ليس فقط قابلاً للعمل، بل أيضًا قابلاً للنقل. إذا كنت تدرس C++ أو تكتب به يوميًا، فهذه المقالة لك.
إجابة مختصرة: ما الذي يجب أن تُرجعه main() في C++؟
\n\nإذا كنت في عجلة من أمرك، إليك الجوهر: يجب أن تُرجع الدالة main() في C++ قيمة من نوع int. هذا مطلب صارم من المعيار (بدءًا من C++98 وحتى C++23). تُعلم القيمة المُرجعة نظام التشغيل ما إذا كان البرنامج قد اكتمل بنجاح أم لا.
إليك الكود الصحيح الأدنى:
\n\n#include <iostream>\n\nint main() {\n std::cout << "Hello, World!" << std::endl;\n return 0; // اكتمال ناجح\n}\n\nلكن هذا مجرد غيض من فيض. دعنا نتعمق أكثر.
\n\nلماذا int بالتحديد، وليس void؟ لمحة تاريخية
\n\nفي الإصدارات المبكرة جدًا من C (قبل معيار ANSI C)، لم يكن نوع main() محددًا بدقة. كانت العديد من المترجمات تسمح بكتابة void main()، وكان ذلك يعمل. ومع ذلك، مع ظهور التوحيد القياسي (C89/C90 لـ C و C++98 لـ C++)، تقرر أن main() يجب أن تُرجع رمز الإنهاء لنظام التشغيل.
لماذا؟ لأن البرامج النصية، وملفات Makefile، والبرامج الأخرى غالبًا ما تتحقق من كيفية انتهاء عمليتك. رمز الإرجاع 0 يعني "نجاح"، وأي قيمة غير صفرية تعني "خطأ" (أو نوع معين من الخطأ). إذا كانت main() من نوع void، فلن تتمكن من نقل هذه المعلومات.
في C++، الوضع أكثر صرامة. ينص معيار C++ (القسم [basic.start.main]) مباشرة: يجب أن يكون نوع main() هو int. أي إعلان آخر (مثل void main()) هو امتداد للمترجم ويجعل الكود غير قابل للنقل.
مقارنة C و C++: ما الفرق؟
\n\nعلى الرغم من أن كلا اللغتين تتطلبان int main()، إلا أن هناك عدة اختلافات رئيسية:
- \n
- الإرجاع الضمني للصفر في C++: إذا لم تكتب
returnفي نهايةmain()، فسيقوم C++ تلقائيًا بإدراجreturn 0. في C (بدءًا من C99) يعمل هذا أيضًا، لكن في المعايير القديمة (C89) كان غياب return يؤدي إلى سلوك غير محدد. \n - وسائط سطر الأوامر: في C++ يمكنك تعريف
int main(int argc, char* argv[])أوint main(). في C يوجد أيضًا خيار ثالث مع البيئة (char* envp[])، لكنه غير موحد في C++ (على الرغم من أن العديد من المترجمات تدعمه). \n - void main(): في C، قد تسمح بعض المترجمات (مثل تلك الخاصة بالأنظمة المدمجة) بـ
void main(). في C++، هذا خطأ فادح، ولن يتم تجميع الكود في الوضع الصارم. \n
مثال لـ C++ (يعمل دائمًا):
\n\nint main() {\n std::cout << "C++ سيعيد 0 تلقائيًا" << std::endl;\n // return 0; // يمكنك عدم كتابتها\n}\n\nمثال لـ C (يتطلب return صريحًا في المعايير القديمة):
\n\n#include <stdio.h>\n\nint main() {\n printf("في C89، يجب إرجاع 0 بشكل صريح\\n");\n return 0; // إلزامي\n}\n\nماذا تعني رموز الإرجاع؟ تحليل مع الأمثلة
\n\nرمز الإرجاع هو