سؤال

هل ينبغي أن أستخدم exit() أو فقط return تصريحات في main()؟شخصيا أؤيد return البيانات لأنني أشعر أنها مثل قراءة أي وظيفة أخرى وأن التحكم في التدفق عندما أقرأ الكود يكون سلسًا (في رأيي).وحتى لو كنت أرغب في إعادة بناء main() وظيفة، وجود return يبدو وكأنه خيار أفضل من exit().

يفعل exit() افعل أي شيء خاص بذلك return لا؟

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

المحلول

في الواقع، هناك يكون فرق، لكنه دقيق.لها آثار أكثر على لغة C++، لكن الاختلافات مهمة.

عندما أتصل return في main(), ، سيتم استدعاء المدمرات للكائنات المحددة محليًا.إذا اتصلت exit(), لن يتم استدعاء أي أداة تدمير للكائنات المحددة محليًا! أعد قراءة ذلك. exit() لا يعود.هذا يعني أنه بمجرد أن أسميها ، لا يوجد "ظهور". لن يتم إتلاف أي كائنات قمت بإنشائها في هذه الدالة.في كثير من الأحيان لا يكون لهذا أي آثار، ولكن في بعض الأحيان يكون له آثار، مثل إغلاق الملفات (بالتأكيد تريد نقل جميع بياناتك إلى القرص؟).

لاحظ أن static سيتم تنظيف الأشياء حتى لو قمت بالاتصال exit().أخيرًا، لاحظ أنه إذا كنت تستخدم abort(), لن يتم تدمير أي كائنات.وهذا يعني أنه لن يتم استدعاء أي كائنات عامة أو كائنات ثابتة أو كائنات محلية مدمراتها.

توخي الحذر عند تفضيل الخروج على العودة.

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a

نصائح أخرى

وثمة فرق آخر: exit هو مكتبة قياسية الدالة بحيث تحتاج إلى تضمين رؤوس والارتباط مع المعيار مكتبة. لتوضيح (في C ++)، هذا هو برنامج صالح:

int main() { return 0; }

ولكن استخدام exit ستحتاج إلى ما يلي:

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

وبالاضافة الى هذا يضيف افتراض إضافية: أن يدعو exit من main لديه آثار جانبية نفس عودته صفر. كما أشار آخرون، وهذا يعتمد على نوع قابل للتنفيذ كنت بناء (أي هوية المتصل main). هل الترميز التطبيق الذي يستخدم C-وقت التشغيل؟ البرنامج المساعد مايا؟ خدمة ويندوز؟ سائق؟ وكل حالة تتطلب الأبحاث لمعرفة ما إذا exit ما يعادل return. IMHO باستخدام exit عند <م> يعني حقا return فقط يجعل رمز أكثر مربكة. OTOH، إذا كنت <م> حقا لا يعني exit، ثم بكل الوسائل استخدامها.

وهناك واحد على الأقل السبب في تفضيل exit: إذا كان أي من معالجات atexit بك تشير إلى بيانات آلية تخزين المدة في main، أو إذا كنت تستخدم setvbuf أو setbuf لتعيين واحد من مستوى تيارات و-storage- التلقائي عازلة مدة في main، ثم عودته من main تنتج سلوك غير معرف، ولكن الدعوة exit صالحة.

<ع> استخدام محتمل آخر (عادة ما تكون مخصصة لبرامج لعبة، ولكن) هو للخروج من برنامج مع دعوات متكررة من main.

وأنا دائما استخدام return لأن النموذج القياسي لmain() يقول أنه لا إرجاع int.

وقال ان بعض إصدارات معايير تعطي main المعاملة الخاصة وتفترض أن تقوم بإرجاع 0 اذا لم يكن هناك بيان return صريح. ونظرا لالبرمجية التالية:

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

وG ++ يولد إلا تحذيرا للfoo() ويتجاهل عودة المفقودة من main:

% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function

أنا بقوة ثانيا تعليق ر.حول استخدام الخروج () لتجنب وجود تخزين تلقائي في main() المستصلحة قبل انتهاء البرنامج فعليا.أ return X; بيان في main() لا يعادل بالضبط دعوة ل exit(X);, ، منذ التخزين الديناميكي لـ main() يختفي عندما main() يعود، لكنه لا يختفي إذا تم الاتصال به exit() يتم بدلا من ذلك.

علاوة على ذلك، في لغة C أو أي لغة تشبه لغة C أ return يلمح البيان بقوة للقارئ إلى أن التنفيذ سيستمر في وظيفة الاستدعاء، وفي حين أن استمرار التنفيذ هذا عادة ما يكون صحيحًا من الناحية الفنية إذا قمت بحساب روتين بدء تشغيل C الذي يطلق عليه main() وظيفة، انها ليست بالضبط ما أنت يعني عندما تقصد إنهاء العملية.

بعد كل شيء، إذا كنت تريد إنهاء برنامجك من داخل أي وظيفة أخرى باستثناء main() أنت يجب يتصل exit().القيام بذلك باستمرار في main() كما أنه يجعل التعليمات البرمجية الخاصة بك أكثر قابلية للقراءة، كما أنه يسهل على أي شخص إعادة تحليل التعليمات البرمجية الخاصة بك؛أي.الكود منسوخ من main() لبعض الوظائف الأخرى لن تسيء التصرف بسبب عرضي return تصريحات ذلك يجب لقد كان exit() المكالمات.

لذا، بدمج كل هذه النقاط معًا، فإن الاستنتاج هو أنه عادة سيئة, ، على الأقل بالنسبة لـ C، لاستخدام a return بيان لإنهاء البرنامج في main().

<اقتباس فقرة>   

هل خروج () القيام بأي شيء خاص "العودة" لا؟

ومع بعض المجمعين لمنصات شائعة، قد exit() ترجمة حجتها في القيمة خروج البرنامج في حين أن العائد من main() قد يكون مجرد تمرير قيمة مباشرة إلى البيئة المضيفة دون أي الترجمة.

وهذا المعيار يتطلب سلوك مماثل في هذه الحالات (على وجه التحديد، فإنه يقول عودته شيء أن يكون-int متوافقة من main() يجب أن يكون معادلا لدعوة exit() مع تلك القيمة). والمشكلة هي أن أنظمة تشغيل مختلفة والاتفاقيات المختلفة لتفسير القيم الخروج. على العديد من أنظمة (الكثير!)، 0 يعني نجاح وأي شيء آخر هو الفشل. ولكن على، ويقول، VMS، قيم غريبة يعني النجاح وحتى تلك تعني الفشل. إذا كنت إرجاع 0 من main()، فإن المستخدم VMS ترى رسالة سيئة عن حدوث انتهاك وصول. لم يكن هناك في الواقع انتهاك وصول - الذي كان مجرد رسالة القياسية المرتبطة رمز الفشل 0

وبعد ذلك جاء ANSI على طول وEXIT_SUCCESS المباركة وEXIT_FAILURE كوسائط هل يمكن تمريرها إلى exit(). يقول المعيار أيضا أن exit(0) يجب أن تتصرف بشكل مطابق لexit(EXIT_SUCCESS)، لذلك معظم تطبيقات تحدد EXIT_SUCCESS إلى 0.

والمعيار، وبالتالي، يضعك في مأزق على VMS، كما أنه لا يترك أي طريقة قياسية لإرجاع <م> الفشل التعليمات البرمجية التي يحدث لديهم قيمة 0.

وعصر أوائل 1990s VAX / VMS C مترجم بالتالي لم يفسر قيمة الإرجاع من main()، فإنه ببساطة عاد أي قيمة للبيئة المضيف. ولكن إذا كنت تستخدم exit() فإنه يفعل ما يتطلب المعيار: ترجمة EXIT_SUCCESS (أو 0) إلى رمز النجاح وEXIT_FAILURE إلى رمز فشل عام. لاستخدام EXIT_SUCCESS، أنت <م> قد لتمريرها إلى exit()، لا يمكن إعادته من main(). أنا لا أعرف ما إذا إصدارات أكثر حداثة من تلك مترجم الحفاظ ذلك السلوك.

وبرنامج C محمول يستخدم لتبدو مثل هذا:

#include <stdio.h>
#include <stdlib.h>

int main() {
  printf("Hello, World!\n");
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

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

في C يعود من main هو بالضبط نفس الدعوة exit بنفس القيمة.

القسم 5.1.2.2.3 من معيار ج تنص على:

إذا كان نوع إرجاع الوظيفة الرئيسية هو نوع متوافق مع int , العودة من الاستدعاء الأولي إلى الوظيفة الرئيسية تعادل استدعاء وظيفة الخروج بالقيمة التي تم إرجاعها بواسطة الرئيسي وظيفة كوسيطة لها;11) الوصول إلى } الذي ينهي ترجع الدالة main قيمة 0.إذا كان نوع الإرجاع هو غير متوافق مع int ، تم إرجاع حالة الإنهاء إلى البيئة المضيفة غير محددة.

تختلف قواعد C++ قليلاً كما هو مذكور في الإجابات الأخرى.

وهناك في الواقع هو الفرق بين exit(0) وreturn(0) في main - عندما يتم استدعاء الدالة main الخاص بك عدة مرات

.

والبرنامج التالي

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    return(0);
  printf("%d", main(argc - 1, argv));
}

وتشغيل ك

./program 0 0 0 0

هل تؤدي إلى الإخراج التالية:

00000

ولكن هذا واحد:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    exit(0);
  printf("%d", main(argc - 1, argv));
}

ولن طباعة أي شيء بغض النظر عن الحجج.

إذا كنت متأكدا من أن أحدا لن يطلق أي وقت مضى main بك صراحة أنه ليس من الناحية الفنية فرقا كبيرا في العام، ولكن للحفاظ على ضوحا exit كود سوف تبدو أفضل بكثير. إذا كنت لسبب ما تريد الاتصال main - يجب تعديله لاحتياجاتك

وفي معرض حديثه عن C.

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