Apakah ada perbedaan antara return n
(dalam main
fungsi) dan exit(n)
dalam C? Apakah ini didefinisikan oleh standar C atau POSIX atau tergantung pada OS atau kompiler?
Apakah ada perbedaan antara return n
(dalam main
fungsi) dan exit(n)
dalam C? Apakah ini didefinisikan oleh standar C atau POSIX atau tergantung pada OS atau kompiler?
Jawaban:
Dalam kebanyakan kasus, tidak ada perbedaan, tetapi inilah program C yang cenderung berperilaku berbeda tergantung pada apakah ia menggunakan return 0;
atau 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
}
Karena atexit()
panggilan, salah satu exit(0);
atau return 0;
menyebabkan cleanup
fungsi dipanggil. Perbedaannya adalah bahwa jika program memanggil exit(0);
, pembersihan terjadi ketika "panggilan" main()
masih aktif, sehingga local_message
objek masih ada. Melaksanakan return 0;
, bagaimanapun, segera mengakhiri doa main()
dan kemudian memanggil cleanup()
fungsi. Karena cleanup()
merujuk (melalui message
penunjuk global ) ke objek yang dialokasikan secara lokal main
, dan objek itu tidak ada lagi, perilaku tidak terdefinisi.
Inilah perilaku yang saya lihat di sistem saya:
$ gcc -DUSE_EXIT c.c -o c && ./c
exit(0);
message = "hello, world"
$ gcc c.c -o c && ./c
return 0;
message = ""
$
Menjalankan program tanpa -DUSE_EXIT
bisa melakukan apa-apa, termasuk crash atau mencetak "hello, world"
(jika memori yang digunakan local_message
kebetulan tidak akan musnah).
Namun dalam praktiknya, perbedaan ini hanya muncul jika objek yang didefinisikan secara lokal di dalam main()
dibuat terlihat di luar main()
dengan menyimpan pointer ke sana. Ini masuk akal untuk terjadi argv
. (Eksperimen pada sistem saya menunjukkan bahwa objek yang ditunjukkan oleh argv
dan oleh *argv
terus ada setelah kembali dari main()
, tetapi Anda tidak harus bergantung pada itu.)
Untuk C
, Standar mengatakan bahwa pengembalian dari panggilan awal ke utama sama dengan panggilan keluar. Namun, pengembalian dari main tidak dapat diharapkan berfungsi jika data lokal ke main mungkin diperlukan selama pembersihan.
Untuk C ++
Ketika keluar (0) digunakan untuk keluar dari program, destruktor untuk objek non-statis yang dicakup secara lokal tidak dipanggil. Tetapi destruktor dipanggil jika return 0 digunakan.
Program 1 - - menggunakan exit (0) untuk keluar
#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);
}
Output: Konstruktor Inside Test
Program 2 - menggunakan return 0 untuk keluar
#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;
}
Output: Konstruktor
Inside Test Di dalam Destructor Test
Memanggil destruktor terkadang penting, misalnya, jika destruktor memiliki kode untuk melepaskan sumber daya seperti menutup file.
Perhatikan bahwa objek statis akan dibersihkan walaupun kita memanggil exit (). Sebagai contoh, lihat program berikut.
#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);
}
Output: Konstruktor
Inside Test Di dalam Destructor Test
finally
Perlu dicatat bahwa standar C (C99) mendefinisikan dua jenis lingkungan eksekusi, Freestanding Environment dan Hosted Environment . Lingkungan berdiri bebas adalah lingkungan C yang tidak mendukung perpustakaan C dan dimaksudkan untuk aplikasi yang disematkan dan sejenisnya. Lingkungan AC yang mendukung perpustakaan C disebut lingkungan Hosted.
C99 mengatakan, dalam penghentian program lingkungan Freestanding didefinisikan implementasi. Jadi, jika implementasi mendefinisikan main
,, return n
dan exit
, perilaku mereka seperti yang didefinisikan dalam implementasi itu.
C99 mendefinisikan perilaku lingkungan yang dihosting sebagai,
Jika tipe pengembalian fungsi utama adalah tipe yang kompatibel dengannya, pengembalian dari panggilan awal ke fungsi utama sama dengan memanggil fungsi keluar dengan nilai yang dikembalikan oleh fungsi utama sebagai argumennya; mencapai} yang menghentikan fungsi utama mengembalikan nilai 0. Jika tipe kembali tidak kompatibel dengan int, status terminasi yang dikembalikan ke lingkungan host tidak ditentukan.
Dari sudut pandang standar C, tidak benar-benar, selain return
sebagai pernyataan dan exit()
fungsi. Entah akan menyebabkan fungsi apa pun yang terdaftar dengan atexit()
dipanggil diikuti dengan penghentian program.
Ada beberapa situasi yang ingin Anda perhatikan:
main()
. Meskipun jarang terlihat dalam praktek, itu legal dalam C. (C ++ secara eksplisit melarangnya.)main()
. Terkadang yang sudah ada main()
akan diganti namanya menjadi sesuatu yang lain dan dipanggil oleh yang baru main()
.Penggunaan exit()
akan memperkenalkan bug jika salah satu dari itu terjadi setelah Anda menulis kode, terutama jika tidak berhenti secara tidak normal. Untuk menghindarinya, adalah ide yang baik untuk memiliki kebiasaan memperlakukan main()
sebagai fungsi itu dan menggunakannya return
ketika Anda ingin itu berakhir.