سؤال

ما هي التواقيع الصالحة للوظيفة الرئيسية في ج؟ أنا أعرف:

int main(int argc, char *argv[])

هل هناك آخرون صالحون؟

هل كانت مفيدة؟

المحلول

المعيار الحالي كما في وقت هذه الإجابة (C11) يذكر صراحة هذين:

int main(void);
int main(int argc, char* argv[]);

على الرغم من أنه يذكر عبارة "أو ما يعادلها" مع الحاشية التالية:

هكذا، int يمكن استبداله بـ typedef الاسم المحدد على أنه int, أو نوع من argv يمكن كتابتها باسم char ** argv, ، وهلم جرا.

بالإضافة إلى ذلك ، فإنه يوفر أيضًا المزيد من الاحتمالات (المعرفة من قبل التنفيذ).

القسم ذي الصلة (C11 القسم 5.1.2.2.1 ، ولكن هذا الجانب بالذات لم يتغير من C99):

تتم تسمية الوظيفة المسمى في بدء تشغيل البرنامج main. لا يعلن التنفيذ أي نموذج أولي لهذه الوظيفة. يجب تعريفه بنوع العودة int وبدون أي معلمات:

int main(void) { /* ... */ }

أو مع معلمتين (يشار إليه هنا باسم argc و argv, ، على الرغم من أنه قد يتم استخدام أي أسماء ، لأنها محلية في الوظيفة التي يتم الإعلان عنها):

int main(int argc, char *argv[]) { /* ... */ }

أو ما يعادلها؛ أو بطريقة أخرى محددة التنفيذ.

إذا تم الإعلان عنها ، فإن المعلمات إلى main يجب أن تطيع الوظيفة القيود التالية:

  • قيمة ال argc يجب أن تكون غير سالبة.

  • argv[argc] يجب أن يكون مؤشر فارغ.

  • إذا كانت قيمة argc أكبر من الصفر ، أعضاء المصفوفة argv[0] عبر argv[argc-1] يجب أن تحتوي شاملة على مؤشرات للسلاسل ، والتي يتم إعطاء قيم محددة من قبل التنفيذ من قبل بيئة المضيف قبل بدء تشغيل البرنامج. القصد من ذلك هو توفير معلومات البرنامج المحددة قبل بدء تشغيل البرنامج من مكان آخر في البيئة المستضافة. إذا كانت البيئة المضيفة غير قادرة على توفير سلاسل بأحرف في كل من الأحرف الكبيرة والصغيرة ، فيجب أن يضمن التنفيذ أن يتم استلام السلاسل في حالة صغيرة.

  • إذا كانت قيمة argc أكبر من الصفر ، وتشير السلسلة إلى argv[0] يمثل اسم البرنامج ؛ argv[0][0] يجب أن يكون الشخصية الفارغة إذا لم يكن اسم البرنامج متاحًا من بيئة المضيف. إذا كانت قيمة argc أكبر من واحد ، والسلاسل التي أشار إليها argv[1] عبر argv[argc-1] تمثل معلمات البرنامج.

  • المعلمات argc و argv والأوتار التي أشار إليها argv يجب تعديل Array من خلال البرنامج ، والاحتفاظ بقيمها الأخيرة بين بدء التشغيل وإنهاء البرنامج.

لاحظ أن هذا لبيئة مستضافة ، تلك التي تراها عادة في برامج C. البيئة القائمة بذاتها (مثل نظام مضمن) أقل تقييدًا ، كما هو مذكور في 5.1.2.1 من نفس المعيار:

في بيئة قائمة بذاتها (قد يتم تنفيذ برنامج C دون أي فائدة من نظام التشغيل) ، يتم تعريف اسم ونوع الوظيفة المسمى في بدء تشغيل البرنامج. أي مرافق مكتبة متاحة لبرنامج قائم بذاته ، بخلاف الحد الأدنى من المجموعة المطلوبة بموجب الفقرة 4 ، محددة للتنفيذ.

نصائح أخرى

قياسي ج

لبيئة مستضافة (هذه هي العادية) ، يقول معيار C99:

5.1.2.2.1 بدء تشغيل البرنامج

تتم تسمية الوظيفة المسمى في بدء تشغيل البرنامج main. لا يعلن التنفيذ أي نموذج أولي لهذه الوظيفة. يجب تعريفه بنوع العودة int وبدون أي معلمات:

int main(void) { /* ... */ }

أو مع معلمتين (يشار إليه هنا باسم argc و argv, ، على الرغم من أنه قد يتم استخدام أي أسماء ، لأنها محلية في الوظيفة التي يتم الإعلان عنها):

int main(int argc, char *argv[]) { /* ... */ }

أو ما يعادلها؛9) أو بطريقة أخرى محددة التنفيذ.

9) هكذا، int يمكن استبداله باسم typedef محدد على أنه int, أو نوع من argv يمكن كتابتها باسم char **argv, ، وهلم جرا.

تقول معايير C11 و C18 بشكل أساسي مثل معيار C99.

قياسي C ++

يقول المعيار C ++ 98:

3.6.1 الوظيفة الرئيسية [basic.start.main

1 يجب أن يحتوي البرنامج على وظيفة عالمية تسمى Main ، وهي البداية المحددة للبرنامج. [...

2 لا يجوز للتنفيذ سلفا الوظيفة الرئيسية. يجب ألا تكون هذه الوظيفة مثقلة. يجب أن يكون له نوع إرجاع من النوع int ، ولكن خلاف ذلك نوعه محدد. يجب أن تسمح جميع التطبيقات بالتعاريف التالية للمادة:

int main() { /* ... */ }

و

int main(int argc, char* argv[]) { /* ... */ }

يقول معيار C ++ بشكل صريح "يجب أن يكون [الوظيفة الرئيسية] نوعًا من نوع الإرجاع ، ولكن على خلاف ذلك ، فإن نوعه محدد" ، ويتطلب نفس التواقيع مثل معيار C. لذا ، لا يسمح "المعيار C ++ الفراغ" مباشرةً ، على الرغم من أنه لا يوجد شيء يمكن أن يفعله لوقف التنفيذ المطابق غير القياسي من السماح بدائل (ولا تنفيذ مطابق قياسي من السماح للبدائل بمثابة امتدادات للمعايير).

تقول معايير C ++ 03 و C ++ 11 و C ++ 14 و C ++ 17 بشكل أساسي مثل C ++ 98.

امتداد مشترك

من الناحية الكلاسيكية ، تدعم أنظمة UNIX البديل الثالث:

int main(int argc, char **argv, char **envp) { ... }

الوسيطة الثالثة هي قائمة من المؤشرات المنهارة الفارغة للسلاسل ، كل منها هو متغير بيئة له اسم ، علامة متساوية ، وقيمة (ربما فارغة). إذا لم تستخدم هذا ، فلا يزال بإمكانك الوصول إلى البيئة عبر "extern char **environ;'. لفترة طويلة ، لم يكن لديه رأس أعلن ذلك ، لكن معيار Posix 2008 يتطلب الآن إعلانه <unistd.h>.

يتم التعرف على ذلك بواسطة معيار C كامتداد شائع ، موثق في الملحق J:

J.5.1 حجج البيئة

1 في بيئة مستضافة ، تتلقى الوظيفة الرئيسية حجة ثالثة ، char *envp[]، هذا يشير إلى مجموعة من المؤشرات المنتهية char, ، يشير كل منها إلى سلسلة توفر معلومات حول البيئة لهذا التنفيذ للبرنامج (5.1.2.2.1).

Microsoft ج

ال Microsoft vs 2010 المترجم مثير للاهتمام. يقول موقع الويب:

بناء جملة الإعلان للما الرئيسية

 int main();

أو اختياريا ،

int main(int argc, char *argv[], char *envp[]);

بدلا من ذلك ، و main و wmain يمكن إعلان الوظائف على أنها عودة void (لا قيمة الإرجاع). إذا أعلنت main أو wmain كإرجاع باطل ، لا يمكنك إرجاع رمز الخروج إلى العملية الأصل أو نظام التشغيل باستخدام عبارة إرجاع. لإرجاع رمز الخروج عندما main أو wmain تم إعلانه void, ، يجب عليك استخدام exit وظيفة.

ليس من الواضح بالنسبة لي ما يحدث (ما يتم إرجاع رمز الخروج إلى الوالد أو o/s) عند برنامج مع void main() هل الخروج - وموقع الويب MS صامت أيضًا.

ومن المثير للاهتمام ، أن MS لا يصف النسخة المكونة من اثنين main() أن معايير C و C ++ تتطلب. إنه يصف فقط نموذج حجة ثلاثة حيث توجد الوسيطة الثالثة char **envp, ، مؤشر إلى قائمة متغيرات البيئة.

تسرد صفحة Microsoft أيضًا بعض البدائل الأخرى - wmain() الذي يتطلب سلاسل شخصية واسعة ، وبعضها أكثر.

إصدار Microsoft VS 2005 من هذه الصفحة لا يدرج void main() كبديل. ال الإصدارات من Microsoft vs 2008 فصاعدًا.

هو int main() كمثل int main(void)?

للحصول على تحليل مفصل ، راجع نهاية إجابتي ماذا يجب main() العودة في C و C ++. (يبدو أنني اعتبرت ذات مرة أن هذا السؤال يشير إلى C ++ ، على الرغم من أنه لم يفعل ولم يحدث أبدًا. في C ++ ، لا يوجد فرق بين int main() و int main(void) و int main() هو الاصطلاحي C ++.)

في C ، هناك فرق بين التدوينين ، لكنك تلاحظ ذلك فقط في الحالات الباطنية. على وجه التحديد ، هناك فرق إذا اتصلت main() وظيفة من الكود الخاص بك ، والتي سمحت للقيام بها في C ولا يُسمح لها بالقيام بها في C ++.

ال int main() التدوين لا يوفر نموذجًا أوليًا main(), ، لكن هذا يهم فقط إذا سميته بشكل متكرر. مع int main(), ، قد تكتب لاحقًا (في نفس الوظيفة ، أو في وظيفة أخرى) int rc = main("absolute", "twaddle", 2): وبشكل رسمي ، يجب ألا يشكو المترجم إلى حد رفض ترجمة الكود ، على الرغم من أنه قد يشتكي بشكل شرعي (يحذرك) من ذلك (واستخدامه -Werror مع GCC يحول التحذير إلى خطأ). إذا كنت تستخدم int main(void), ، الدعوة اللاحقة إلى main() يجب أن تولد خطأ - قلت إن الوظيفة لا تأخذ أي وسيطات ولكنها حاولت تقديم ثلاث. بالطبع ، لا يمكنك الاتصال بشكل شرعي main() قبل أن تعلن أو تحدده (ما لم تكن لا تزال تستخدم دلالات C90) - ولا يعلن التنفيذ نموذجًا أوليًا main(). NB: يوضح معيار C11 كليهما int main() و int main(void) في أمثلة مختلفة - كلاهما صالح في C ، على الرغم من وجود فرق دقيق بينهما.

يدعم Posix execve (), ، وهو ما يدعم بدوره

int main(int argc, char *argv[], char *envp[])

الوسيطة المضافة هي البيئة ، أي مجموعة من سلاسل اسم النموذج = القيمة.

http://en.wikipedia.org/wiki/main_function_(programming)#c_and_c.2b.2b

إلى جانب المعتاد int main(int argc, char *argv[]) و Posix int main(int argc, char **argv, char **envp), ، على Mac OS X يدعم أيضًا

int main(int argc, char* argv[], char* envp[], char* apple[]);

بالطبع هو ماك فقط.

على Windows هناك

int wmain(int argc, wchar_t* argv[], wchar_t* envp[]);

كما البديل Unicode (في الواقع ، شحن واسع). بالطبع هناك WinMain جدا.

int main(void)

تحت بعض نظام التشغيل (على سبيل المثال ، Windows) هذا صحيح أيضًا:

int main(int argc, char **argv, char **envp)

أين envp يعطي بيئة ، يمكن الوصول إليها من خلال getenv()

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top