มีความแตกต่างระหว่างreturn n
(ในmain
ฟังก์ชั่น) และexit(n)
ใน C หรือไม่? มันถูกกำหนดโดยมาตรฐาน C หรือ POSIX หรือขึ้นอยู่กับระบบปฏิบัติการหรือคอมไพเลอร์?
มีความแตกต่างระหว่างreturn n
(ในmain
ฟังก์ชั่น) และexit(n)
ใน C หรือไม่? มันถูกกำหนดโดยมาตรฐาน C หรือ POSIX หรือขึ้นอยู่กับระบบปฏิบัติการหรือคอมไพเลอร์?
คำตอบ:
ในกรณีส่วนใหญ่ไม่มีความแตกต่าง แต่นี่คือโปรแกรม C ที่มีแนวโน้มที่จะทำงานแตกต่างกันไปขึ้นอยู่กับว่ามันใช้return 0;
หรือexit(0);
:
#include <stdio.h>
#include <stdlib.h>
static char *message;
void cleanup(void) {
printf("message = \"%s\"\n", message);
}
int main(void) {
char local_message[] = "hello, world";
message = local_message;
atexit(cleanup);
#ifdef USE_EXIT
puts("exit(0);");
exit(0);
#else
puts("return 0;");
return 0;
#endif
}
เนื่องจากการatexit()
เรียกใช้exit(0);
หรือreturn 0;
ทำให้cleanup
ฟังก์ชันถูกเรียกใช้ ความแตกต่างคือถ้าโปรแกรมเรียกexit(0);
ใช้การล้างข้อมูลจะเกิดขึ้นในขณะที่ "เรียก" เพื่อmain()
ยังคงทำงานอยู่ดังนั้นlocal_message
วัตถุยังคงมีอยู่ การดำเนินการreturn 0;
แต่ทันทีที่ยุติการภาวนาของmain()
และจากนั้นจะเรียกcleanup()
ฟังก์ชั่น เนื่องจากการcleanup()
อ้างอิง (ผ่านmessage
ตัวชี้โกลบอล) ไปยังวัตถุที่ถูกจัดสรรในmain
เครื่องและไม่มีวัตถุนั้นอีกต่อไปพฤติกรรมจึงไม่ได้กำหนดไว้
นี่คือพฤติกรรมที่ฉันเห็นในระบบของฉัน:
$ gcc -DUSE_EXIT c.c -o c && ./c
exit(0);
message = "hello, world"
$ gcc c.c -o c && ./c
return 0;
message = ""
$
การรันโปรแกรมโดยไม่-DUSE_EXIT
สามารถทำอะไรได้รวมถึงการขัดข้องหรือการพิมพ์"hello, world"
(หากหน่วยความจำที่ใช้โดยlocal_message
ไม่เกิดการอุดตัน)
ในทางปฏิบัติแม้ว่าความแตกต่างนี้จะปรากฏขึ้นเฉพาะในกรณีที่วัตถุภายในกำหนดไว้main()
สามารถมองเห็นได้ภายนอกmain()
โดยการบันทึกพอยน์เตอร์ให้กับพวกเขา สิ่งนี้อาจเกิดขึ้นargv
ได้ (การทดลองในระบบของฉันแสดงให้เห็นว่าวัตถุที่ชี้ไปตามargv
และโดย*argv
ยังคงมีอยู่หลังจากกลับมาจากmain()
แต่คุณไม่ควรขึ้นอยู่กับสิ่งนั้น)
สำหรับ C
The Standard บอกว่าการส่งคืนจากการโทรเริ่มต้นไปยัง main นั้นเทียบเท่ากับการโทรออก อย่างไรก็ตามการคืนค่าจากหลักไม่สามารถทำงานได้หากข้อมูลภายในเครื่องถึงหลักอาจจำเป็นในระหว่างการล้างข้อมูล
สำหรับ C ++
เมื่อใช้ exit (0) เพื่อออกจากโปรแกรมจะไม่มีการเรียก destructors สำหรับวัตถุที่ไม่มีการกำหนดขอบเขตแบบโลคัล แต่จะเรียกว่า destructors หากใช้ return 0
โปรแกรม 1 - - ใช้ exit (0) เพื่อออก
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructor\n");
}
~Test(){
printf("Inside Test's Destructor");
getchar();
}
};
int main() {
Test t1;
// using exit(0) to exit from main
exit(0);
}
ผลลัพธ์: ตัวสร้างการทดสอบภายใน
โปรแกรม 2 - ใช้ผลตอบแทน 0 เพื่อออก
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructor\n");
}
~Test(){
printf("Inside Test's Destructor");
}
};
int main() {
Test t1;
// using return 0 to exit from main
return 0;
}
เอาท์พุท: สร้าง
การทดสอบภายในของ Destructor การทดสอบของ
บางครั้งการโทร destructors มีความสำคัญตัวอย่างเช่นถ้า destructor มีรหัสเพื่อปล่อยทรัพยากรเช่นไฟล์ปิด
โปรดทราบว่าวัตถุแบบคงที่จะถูกล้างออกแม้ว่าเราจะเรียก exit () ตัวอย่างเช่นดูโปรแกรมต่อไปนี้
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructor\n");
}
~Test(){
printf("Inside Test's Destructor");
getchar();
}
};
int main() {
static Test t1; // Note that t1 is static
exit(0);
}
เอาท์พุท: สร้าง
การทดสอบภายในของ Destructor การทดสอบของ
finally
คุ้มค่าสังเกตว่ามาตรฐาน C (C99) กำหนดสองประเภทของสภาพแวดล้อมการดำเนินการอิสระสิ่งแวดล้อมและHosted สิ่งแวดล้อม สภาพแวดล้อมอิสระคือสภาพแวดล้อม C ซึ่งไม่สนับสนุนไลบรารี C และมีไว้สำหรับแอปพลิเคชันแบบฝังและอื่น ๆ สภาพแวดล้อม AC ซึ่งสนับสนุนไลบรารี C เรียกว่าสภาพแวดล้อมแบบโฮสต์
C99 กล่าวว่าในการยกเลิกโปรแกรมสภาพแวดล้อมอิสระจะถูกกำหนดไว้ ดังนั้นถ้ากำหนดดำเนินการmain
, return n
และexit
พฤติกรรมของพวกเขาจะเป็นที่ที่กำหนดไว้ในการใช้งานที่
C99 กำหนดพฤติกรรมสภาพแวดล้อมที่โฮสต์เป็น,
หากประเภทส่งคืนของฟังก์ชั่นหลักเป็นประเภทที่เข้ากันได้กับมันกลับมาจากการโทรเริ่มต้นไปยังฟังก์ชั่นหลักเทียบเท่ากับการเรียกฟังก์ชั่นออกที่มีค่าส่งกลับโดยฟังก์ชั่นหลักเป็นอาร์กิวเมนต์ ถึง} ที่ยุติฟังก์ชั่นหลักส่งคืนค่า 0 หากชนิดส่งคืนไม่เข้ากันกับ int สถานะการเลิกจ้างที่ส่งคืนไปยังสภาพแวดล้อมโฮสต์จะไม่ได้รับการระบุ
จากมุมมองของมาตรฐาน C ไม่ใช่อย่างอื่นนอกเหนือจากreturn
การเป็นคำสั่งและexit()
เป็นฟังก์ชัน จะทำให้ฟังก์ชันใด ๆ ที่ลงทะเบียนด้วยatexit()
ถูกเรียกตามด้วยการสิ้นสุดของโปรแกรม
มีสองสถานการณ์ที่คุณต้องระวัง:
main()
สอบถามซ้ำใน ในขณะที่ไม่ค่อยได้เห็นในทางปฏิบัติมันเป็นเรื่องถูกกฎหมายใน C. (C ++ ห้ามอย่างชัดเจน)main()
ซ้ำ บางครั้งที่มีอยู่จะถูกเปลี่ยนชื่ออย่างอื่นและมีการเรียกใหม่main()
main()
การใช้งานexit()
จะเป็นการแนะนำบั๊กหากสิ่งใดสิ่งหนึ่งเกิดขึ้นหลังจากที่คุณได้เขียนรหัสโดยเฉพาะอย่างยิ่งหากไม่ยุติอย่างผิดปกติ เพื่อหลีกเลี่ยงปัญหาดังกล่าวจึงเป็นความคิดที่ดีที่คุณจะต้องปฏิบัติmain()
ตามหน้าที่และการใช้งานreturn
เมื่อคุณต้องการให้จบ