Apa yang harus main () kembali dalam C dan C ++?

694

Apa cara yang benar (paling efisien) untuk mendefinisikan main()fungsi dalam C dan C ++ - int main()atau void main()- dan mengapa? Jika int main()kemudian return 1atau return 0?


Ada banyak duplikat dari pertanyaan ini, termasuk:

Terkait:

Joel
sumber
28
Saya masih berpikir itu cukup kabur juga. Tentukan "paling efisien" untuk saya. Efisien dalam arti apa? Dalam arti mengambil lebih sedikit memori? Dalam arti berlari lebih cepat? Saya dapat melihat jawaban yang bermanfaat tetapi saya masih berpikir pertanyaannya diutarakan dengan buruk.
Onorio Catenacci
7
Pish posh, konteks efisien jelas di sini, terutama dengan contoh-contoh (yang mungkin ada untuk memperjelas definisi 'efisien'). Semoga penyangga yang malang tidak merangkak ke lubang dan menyesali pertanyaannya sepenuhnya. Bisa dikatakan, terlepas dari void atau int, nilai dikembalikan, sehingga tidak berdampak pada ukuran file, operasi yang dijalankan, atau memori yang dialokasikan. Dan orang-orang, di sebagian besar OS, cenderung mengembalikan 0 pada kesuksesan, dan sesuatu yang lain pada -lain- sukses, atau kegagalan - tetapi tidak ada standar. Pada akhirnya, tidak ada perbedaan dalam efisiensi dengan cara yang jelas.
Kit10
"benar (paling efisien)" tidak masuk akal. Efisien adalah satu hal, benar adalah hal lain. maindisebut sekali (dan dalam C ++ hanya bisa disebut sekali: tidak ada rekursi). Jika Anda tidak ingin eksekusi menghabiskan banyak waktu main, maka jangan sering-sering memanggil program: buatlah program mengimplementasikan pengulangan.
Kaz
2
Saya merasa menarik bahwa tidak ada jawaban, sejauh yang saya tahu, memberikan contoh yang berfungsi penuh, termasuk #includepernyataan
puk
3
Nilai pengembalian tidak masuk akal pada platform tanpa OS. Anda tidak akan kembali ke apa pun. Jika Anda menekan returnmasuk main(...)pada perangkat tertanam, sistem Anda masuk ke keadaan tidak terduga dan mesin cuci Anda akan menjadi sadar diri dan mencoba untuk membunuh Anda. Jadi, kami gunakan void main()dalam kasus itu. Ini adalah praktik standar industri dalam bare-metal tertanam.
3Dave

Jawaban:

569

Nilai kembali untuk mainmenunjukkan bagaimana program keluar. Keluar normal diwakili oleh nilai balik 0 dari main. Keluaran abnormal ditandai oleh pengembalian bukan nol, tetapi tidak ada standar untuk bagaimana kode bukan nol ditafsirkan. Sebagaimana dicatat oleh orang lain, void main()dilarang oleh standar C ++ dan tidak boleh digunakan. Tanda maintangan C ++ yang valid adalah:

int main()

dan

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

yang setara dengan

int main(int argc, char** argv)

Perlu juga dicatat bahwa dalam C ++, int main()dapat dibiarkan tanpa pernyataan-kembali, di mana pada saat itu default untuk mengembalikan 0. Ini juga benar dengan program C99. Apakah return 0;harus dihilangkan atau tidak terbuka untuk diperdebatkan. Kisaran tanda tangan utama program C yang valid jauh lebih besar.

Efisiensi bukan masalah dengan mainfungsi. Ini hanya dapat dimasukkan dan dibiarkan satu kali (menandai awal dan penghentian program) sesuai dengan standar C ++. Untuk C, masuk kembali main()diperbolehkan, tetapi harus dihindari.

workmad3
sumber
69
utama DAPAT dimasukkan / dibiarkan berulang kali, tetapi program itu mungkin tidak akan memenangkan penghargaan desain apa pun;)
korona
13
C99 juga memiliki fitur salah C ++ yang mencapai akhir fungsi main () sama dengan mengembalikan 0 - jika main () didefinisikan untuk mengembalikan tipe yang kompatibel dengan int (bagian 5.1.2.2.3).
Jonathan Leffler
62
masuk kembali utama tidak valid C ++. Secara eksplisit dalam standar, 3.6.1.3 menyatakan 'utama tidak boleh digunakan dalam suatu program'
workmad3
117
stdlib.h menyediakan EXIT_SUCCESS dan EXIT_FAILURE untuk tujuan ini
Clay
20
0 dan bukan nol adalah benar tetapi sama sekali tidak berarti bagi seseorang yang membaca kode Anda. Pertanyaan ini adalah bukti bahwa orang tidak tahu kode apa yang valid / tidak valid. EXIT_SUCCESS / EXIT_FAILURE jauh lebih jelas.
JaredPar
169

Jawaban yang diterima tampaknya ditargetkan untuk C ++, jadi saya pikir saya akan menambahkan jawaban yang berkaitan dengan C, dan ini berbeda dalam beberapa cara.

ISO / IEC 9899: 1989 (C90):

main() harus dinyatakan sebagai:

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

Atau setara. Misalnya, int main(int argc, char *argv[])setara dengan yang kedua. Selanjutnya, inttipe pengembalian dapat dihilangkan karena merupakan default.

Jika suatu implementasi mengizinkannya, main()dapat dideklarasikan dengan cara lain, tetapi ini membuat implementasi program didefinisikan, dan tidak lagi sesuai secara ketat.

Standar ini mendefinisikan 3 nilai untuk pengembalian yang benar-benar sesuai (yaitu, tidak bergantung pada implementasi perilaku yang ditetapkan): 0dan EXIT_SUCCESSuntuk penghentian yang berhasil, dan EXIT_FAILUREuntuk penghentian yang tidak berhasil. Nilai-nilai lain tidak standar dan implementasi didefinisikan. main()harus memiliki returnpernyataan eksplisit di bagian akhir untuk menghindari perilaku yang tidak terdefinisi.

Akhirnya, tidak ada yang salah dari sudut pandang standar dengan menelepon main()dari suatu program.

ISO / IEC 9899: 1999 (C99):

Untuk C99, semuanya sama seperti di atas kecuali:

  • The inttipe kembali tidak dapat dihilangkan.
  • Anda dapat menghilangkan pernyataan kembali dari main(). Jika Anda melakukannya, dan main()selesai, ada yang tersirat return 0.
Chris Young
sumber
1
@Lundin Saya tidak berpikir Anda perlu kutipan untuk mengatakan bahwa seseorang diizinkan membuat kompiler yang menerima program yang tidak sesuai standar, atau memiliki kompiler yang tidak sesuai standar. Itu pengetahuan umum dan akal sehat
KABoissonneault
4
@KABoissonneault Perilaku yang didefinisikan oleh implementasi adalah istilah dari standar, sebagai lawan dari perilaku yang sepenuhnya tidak terdokumentasi. Jika Anda menerapkan sesuatu yang terdaftar sebagai perilaku yang ditentukan implementasi, Anda masih mengikuti standar. Dalam hal ini C89 yang dikutip, tidak mencantumkan perilaku yang didefinisikan implementasi, sehingga perlu kuotasi, untuk membuktikan bahwa ia tidak hanya mengada-ada.
Lundin
1
@Lundin Anda melihat ini dengan cara yang salah. Yang kita bicarakan bukanlah perilaku yang ditentukan implementasi, kita berbicara tentang implementasi yang menyimpang dari standar jika mereka memilihnya. Ini lebih seperti seorang anak yang tidak mematuhi orang tua mereka: Anda tidak perlu kutipan dari orang tua untuk memberi tahu Anda dengan cara apa seorang anak dapat menentang apa yang dikatakan orang tua. Anda hanya tahu bahwa saat anak memilih untuk melakukannya, mereka tidak lagi patuh dengan guildelines orang tua mereka
KABoissonneault
2
@ KABoissonneault Bagian yang saya kutip dalam komentar saya jelas tentang perilaku implementasi-didefinisikan (sebagai lawan dari ekstensi kompiler non-standar .) Jadi saya berbicara tentang perilaku implementasi-didefinisikan. Jika Anda memiliki monolog tentang sesuatu yang lain, semoga beruntung dengan itu.
Lundin
1
@Lundin Saya kira kata-kata dalam kutipan membingungkan (bagian di mana mereka mengatakan "tapi ini membuat implementasi program didefinisikan") tetapi saya cukup yakin orang itu berbicara tentang perilaku non-standar (seperti dikatakan dalam "Jika suatu implementasi mengizinkannya "dan" dan tidak lagi secara ketat menyesuaikan [dengan standar] ") sebagai kebalikan dari perilaku aktual implementasi yang didefinisikan. Orang itu pasti harus menulis ulang jawaban mereka, tetapi saya masih tidak berpikir bahwa kutipan dari standar diperlukan untuk itu
KABoissonneault
117

Standar C - Lingkungan yang Diinangi

Untuk lingkungan yang dihosting (itu yang normal), standar C11 (ISO / IEC 9899: 2011) mengatakan:

5.1.2.2.1 Startup program

Fungsi yang dipanggil saat startup program dinamai main. Implementasi menyatakan tidak ada prototipe untuk fungsi ini. Ini harus didefinisikan dengan tipe pengembalian intdan tanpa parameter:

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

atau dengan dua parameter (disebut di sini sebagai argcdan argv, meskipun nama apa pun dapat digunakan, karena mereka lokal untuk fungsi di mana mereka dinyatakan):

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

atau setara; 10) atau dengan cara lain yang ditentukan implementasi.

Jika dinyatakan, parameter ke fungsi utama harus mematuhi batasan berikut:

  • Nilai argcharus tidak negatif.
  • argv[argc] akan menjadi pointer nol.
  • Jika nilai argclebih besar dari nol, anggota array argv[0]melalui argv[argc-1]inklusif harus berisi pointer ke string, yang diberi nilai-nilai implementasi-didefinisikan oleh lingkungan host sebelum startup program. Maksudnya adalah untuk menyediakan informasi program yang ditentukan sebelum memulai program dari tempat lain di lingkungan yang dihosting. Jika lingkungan host tidak mampu menyediakan string dengan huruf besar dan kecil, implementasi harus memastikan bahwa string diterima dalam huruf kecil.
  • Jika nilai argclebih besar dari nol, string yang ditunjuk oleh argv[0] mewakili nama program; argv[0][0]akan menjadi karakter nol jika nama program tidak tersedia dari lingkungan host. Jika nilai argclebih besar dari satu, string yang ditunjuk oleh argv[1]melalui argv[argc-1] mewakili parameter Program.
  • Parameter argcdan argvdan string yang ditunjukkan oleh argvarray harus dapat dimodifikasi oleh program, dan mempertahankan nilai-nilai yang terakhir disimpan antara startup dan penghentian program.

10) Dengan demikian, intdapat diganti dengan nama typedef didefinisikan sebagai int, atau jenis argvdapat ditulis sebagai char **argv, dan seterusnya.

Pengakhiran program dalam C99 atau C11

Nilai yang dikembalikan dari main()ditransmisikan ke 'lingkungan' dengan cara yang ditentukan implementasi.

5.1.2.2.3 Pengakhiran program

1 Jika tipe pengembalian mainfungsi adalah tipe yang kompatibel dengan int, pengembalian dari panggilan awal ke mainfungsi setara dengan memanggil exitfungsi dengan nilai yang dikembalikan oleh mainfungsi sebagai argumennya; 11) mencapai }yang mengakhiri mainfungsi mengembalikan nilai 0. Jika jenis kembali tidak kompatibel dengan int, status penghentian kembali ke lingkungan host tidak ditentukan.

11) Sesuai dengan 6.2.4, masa hidup objek dengan durasi penyimpanan otomatis yang dinyatakan dalam main akan berakhir pada kasus sebelumnya, bahkan di mana mereka tidak akan memiliki dalam yang terakhir.

Catatan yang 0diamanatkan sebagai 'sukses'. Anda dapat menggunakan EXIT_FAILUREdan EXIT_SUCCESSdari <stdlib.h>jika Anda mau, tetapi 0 sudah mapan, dan begitu juga 1. Lihat juga kode Keluar lebih besar dari 255 - mungkin? .

Di C89 (dan karenanya di Microsoft C), tidak ada pernyataan tentang apa yang terjadi jika main()fungsi kembali tetapi tidak menentukan nilai kembali; oleh karena itu mengarah pada perilaku yang tidak terdefinisi.

7.22.4.4 exitFungsi

¶5 Akhirnya, kontrol dikembalikan ke lingkungan host. Jika nilai statusnol atau EXIT_SUCCESS, bentuk yang ditentukan implementasi status pemutusan berhasil dikembalikan. Jika nilainya statusadalah EXIT_FAILURE, bentuk pemutusan status yang ditentukan implementasi tidak dikembalikan. Kalau tidak, status yang dikembalikan ditentukan oleh implementasi.

Standar C ++ - Lingkungan yang Diinangi

Standar C ++ 11 (ISO / IEC 14882: 2011) mengatakan:

3.6.1 Fungsi utama [basic.start.main]

¶1 Suatu program harus mengandung fungsi global yang disebut main, yang merupakan awal dari program yang ditunjuk. [...]

¶2 Suatu implementasi tidak akan menentukan fungsi utama. Fungsi ini tidak akan kelebihan beban. Ini harus memiliki tipe pengembalian tipe int, tetapi jika tidak jenisnya implementasi didefinisikan. Semua implementasi harus memungkinkan kedua definisi utama berikut:

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

dan

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

Dalam bentuk yang terakhir argcharus ada sejumlah argumen yang diteruskan ke program dari lingkungan di mana program dijalankan. Jika argcbukan nol, argumen ini harus disertakan argv[0] melalui argv[argc-1]sebagai penunjuk ke karakter awal string multibyte yang diakhiri null (NTMBS) (17.5.2.1.4.2) dan argv[0]harus menjadi penunjuk ke karakter awal NTMBS yang mewakili nama yang digunakan untuk aktifkan program atau "". Nilai argcharus tidak negatif. Nilai argv[argc] harus 0. [Catatan: Disarankan agar parameter lebih lanjut (opsional) ditambahkan setelahnya argv. —Kirim catatan]

¶3 Fungsi maintidak akan digunakan dalam suatu program. Linkage (3.5) dari maindidefinisikan oleh implementasi. [...]

¶5 Pernyataan kembali pada main memiliki efek meninggalkan fungsi utama (menghancurkan objek dengan durasi penyimpanan otomatis) dan memanggil std::exitdengan nilai kembali sebagai argumen. Jika kontrol mencapai ujung main tanpa menemui pernyataan pengembalian, efeknya adalah menjalankan

return 0;

Standar C ++ secara eksplisit mengatakan "Ini [fungsi utama] harus memiliki tipe tipe pengembalian int, tetapi jika tidak tipe implementasinya didefinisikan", dan memerlukan dua tanda tangan yang sama dengan standar C yang akan didukung sebagai opsi. Jadi 'void main ()' secara langsung tidak diizinkan oleh standar C ++, meskipun tidak ada yang bisa dilakukan untuk menghentikan implementasi non-standar yang memungkinkan alternatif. Perhatikan bahwa C ++ melarang pengguna menelepon main(tetapi standar C tidak).

Ada sebuah paragraf dari §18.5 Start dan terminasi di C ++ 11 standar yang identik dengan paragraf dari §7.22.4.4 The exitfungsi dalam standar C11 (dikutip di atas), terpisah dari catatan kaki (yang hanya dokumen yang EXIT_SUCCESSdan EXIT_FAILUREdidefinisikan dalam <cstdlib>).

Standar C - Ekstensi Umum

Secara klasik, sistem Unix mendukung varian ketiga:

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

Argumen ketiga adalah daftar null yang diakhiri dari pointer ke string, yang masing-masing merupakan variabel lingkungan yang memiliki nama, tanda sama dengan, dan nilai (mungkin kosong). Jika Anda tidak menggunakan ini, Anda masih bisa masuk ke lingkungan melalui ' extern char **environ;'. Variabel global ini unik di antara mereka yang ada di POSIX karena tidak memiliki header yang menyatakannya.

Ini diakui oleh standar C sebagai perpanjangan umum, yang didokumentasikan dalam Lampiran J:

J.5.1 Argumen lingkungan

¶1 Dalam lingkungan yang dihosting, fungsi utama menerima argumen ketiga char *envp[],, yang menunjuk ke array pointer yang diakhiri dengan null char, masing-masing menunjuk ke string yang memberikan informasi tentang lingkungan untuk pelaksanaan program ini (5.1. 2.2.1).

Microsoft C

The Microsoft VS 2010 compiler menarik. Situs web mengatakan:

Sintaks deklarasi untuk main adalah

 int main();

atau, secara opsional,

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

Atau, fungsi maindan wmaindapat dinyatakan sebagai kembali void(tidak ada nilai balik). Jika Anda menyatakan mainatau wmainsebagai batal kembali, Anda tidak dapat mengembalikan kode keluar ke proses induk atau sistem operasi dengan menggunakan pernyataan kembali. Untuk mengembalikan kode keluar saat mainatau wmaindinyatakan sebagai void, Anda harus menggunakan exitfungsi ini.

Tidak jelas bagi saya apa yang terjadi (kode keluar apa yang dikembalikan ke induk atau OS) ketika program dengan void main()apakah keluar - dan situs web MS juga diam.

Menariknya, MS tidak meresepkan versi dua argumen main()yang dibutuhkan oleh standar C dan C ++. Ini hanya menentukan bentuk argumen tiga di mana argumen ketiga adalah char **envp, pointer ke daftar variabel lingkungan.

Halaman Microsoft juga mencantumkan beberapa alternatif lain - wmain()yang mengambil string karakter lebar, dan beberapa lagi.

Microsoft Visual Studio 2005 versi halaman ini tidak daftar void main()sebagai alternatif. The versi dari Microsoft Visual Studio 2008 dan seterusnya lakukan.

Standar C - Lingkungan Berdiri Bebas

Seperti disebutkan sebelumnya, persyaratan di atas berlaku untuk lingkungan yang dihosting. Jika Anda bekerja dengan lingkungan yang berdiri sendiri (yang merupakan alternatif untuk lingkungan yang dihosting), maka standar memiliki lebih sedikit untuk dikatakan. Untuk lingkungan yang berdiri sendiri, fungsi yang dipanggil saat startup program tidak perlu dipanggil maindan tidak ada batasan pada tipe pengembaliannya. Standar mengatakan:

5.1.2 Lingkungan eksekusi

Dua lingkungan eksekusi didefinisikan: berdiri bebas dan dihosting. Dalam kedua kasus, startup program terjadi ketika fungsi C yang ditunjuk dipanggil oleh lingkungan eksekusi. Semua objek dengan durasi penyimpanan statis harus diinisialisasi (diatur ke nilai awal) sebelum memulai program. Cara dan waktu inisialisasi tersebut tidak ditentukan. Pengakhiran program mengembalikan kontrol ke lingkungan eksekusi.

5.1.2.1 Lingkungan berdiri bebas

Dalam lingkungan yang berdiri sendiri (di mana eksekusi program C dapat terjadi tanpa manfaat dari sistem operasi), nama dan jenis fungsi yang dipanggil saat startup program ditentukan oleh implementasi. Fasilitas perpustakaan apa pun yang tersedia untuk program berdiri bebas, selain dari set minimal yang disyaratkan oleh klausul 4, ditentukan oleh implementasi.

Efek penghentian program dalam lingkungan yang berdiri sendiri ditentukan oleh implementasi.

Referensi silang ke ayat 4 Kesesuaian mengacu pada ini:

¶5 Program yang sangat sesuai hanya akan menggunakan fitur-fitur bahasa dan perpustakaan yang ditentukan dalam Standar Internasional ini. 3) Ini tidak akan menghasilkan output tergantung pada perilaku yang tidak ditentukan, tidak ditentukan, atau ditentukan implementasi, dan tidak boleh melebihi batas implementasi minimum.

¶6 Dua bentuk implementasi yang sesuai dihosting dan berdiri bebas . Sebuah implementasi host sesuai akan menerima program secara ketat sesuai. Sebuah implementasi berdiri bebas sesuai akan menerima program secara ketat sesuai di mana penggunaan fitur-fitur tertentu dalam klausa perpustakaan (klausul 7) hanya terbatas pada isi dari header standar <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, dan <stdnoreturn.h>. Implementasi yang sesuai mungkin memiliki ekstensi (termasuk fungsi pustaka tambahan), asalkan mereka tidak mengubah perilaku program yang benar-benar sesuai. 4)

¶7 Program yang sesuai adalah yang dapat diterima untuk implementasi yang sesuai. 5)

3) Program yang benar-benar sesuai dapat menggunakan fitur bersyarat (lihat 6.10.8.3) asalkan penggunaannya dijaga oleh arahan preprocessing inklusi bersyarat yang sesuai menggunakan makro terkait. Sebagai contoh:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4) Ini menyiratkan bahwa implementasi yang sesuai cadangan tidak ada pengidentifikasi selain yang secara eksplisit dicadangkan dalam Standar Internasional ini.

5) Program yang benar-benar sesuai dimaksudkan agar portabel secara maksimal di antara implementasi yang sesuai. Program yang sesuai mungkin tergantung pada fitur non-portabel dari implementasi yang sesuai.

Terlihat bahwa satu-satunya header yang diperlukan untuk lingkungan yang berdiri sendiri yang benar-benar mendefinisikan fungsi apa pun adalah <stdarg.h>(dan bahkan yang mungkin - dan seringkali - hanya makro).

Standar C ++ - Lingkungan Berdiri Bebas

Sama seperti standar C yang mengenali lingkungan yang di-host dan berdiri bebas, demikian juga standar C ++. (Kutipan dari ISO / IEC 14882: 2011.)

1.4 Kepatuhan implementasi [intro.compliance]

¶7 Dua jenis implementasi didefinisikan: implementasi yang di-host dan implementasi yang berdiri sendiri . Untuk implementasi yang dihosting, Standar Internasional ini mendefinisikan set perpustakaan yang tersedia. Implementasi berdiri bebas adalah implementasi di mana eksekusi dapat berlangsung tanpa manfaat dari sistem operasi, dan memiliki seperangkat perpustakaan yang didefinisikan implementasi yang mencakup perpustakaan dukungan bahasa tertentu (17.6.1.3).

¶8 Implementasi yang sesuai mungkin memiliki ekstensi (termasuk fungsi perpustakaan tambahan), asalkan mereka tidak mengubah perilaku dari setiap program yang dibentuk dengan baik. Implementasi diperlukan untuk mendiagnosis program yang menggunakan ekstensi tersebut yang bentuknya tidak sesuai dengan Standar Internasional ini. Namun, setelah melakukannya, mereka dapat menyusun dan menjalankan program-program tersebut.

Each9 Setiap implementasi harus menyertakan dokumentasi yang mengidentifikasi semua konstruksi yang didukung kondisional yang tidak mendukung dan mendefinisikan semua karakteristik khusus lokal. 3

3) Dokumentasi ini juga mendefinisikan perilaku yang ditentukan implementasi; lihat 1.9.

17.6.1.3 Implementasi berdiri bebas [kepatuhan]

Dua jenis implementasi didefinisikan: di-host dan berdiri bebas (1.4). Untuk implementasi yang dihosting, Standar Internasional ini menjelaskan kumpulan tajuk yang tersedia.

Implementasi berdiri bebas memiliki set header yang ditentukan implementasi. Set ini harus mencakup setidaknya header yang ditunjukkan pada Tabel 16.

Versi disediakan dari header <cstdlib>wajib menyatakan setidaknya fungsi abort, atexit, at_quick_exit, exit, dan quick_exit(18,5). Header lain yang tercantum dalam tabel ini harus memenuhi persyaratan yang sama seperti untuk implementasi yang di-host.

Tabel 16 - header C ++ untuk implementasi freestanding

Subclause                           Header(s)
                                    <ciso646>
18.2  Types                         <cstddef>
18.3  Implementation properties     <cfloat> <limits> <climits>
18.4  Integer types                 <cstdint>
18.5  Start and termination         <cstdlib>
18.6  Dynamic memory management     <new>
18.7  Type identification           <typeinfo>
18.8  Exception handling            <exception>
18.9  Initializer lists             <initializer_list>
18.10 Other runtime support         <cstdalign> <cstdarg> <cstdbool>
20.9  Type traits                   <type_traits>
29    Atomics                       <atomic>

Bagaimana dengan menggunakan int main()di C?

Standar §5.1.2.2.1 dari standar C11 menunjukkan notasi yang disukai -  int main(void)- tetapi ada juga dua contoh dalam standar yang menunjukkan int main(): §6.5.3.4 ¶8 dan §6.7.6.3 ¶20 . Sekarang, penting untuk dicatat bahwa contoh tidak 'normatif'; mereka hanya ilustratif. Jika ada bug dalam contoh, mereka tidak secara langsung mempengaruhi teks utama standar. Yang mengatakan, mereka sangat menunjukkan perilaku yang diharapkan, jadi jika standar termasuk int main()dalam contoh, itu menunjukkan bahwa int main()tidak dilarang, bahkan jika itu bukan notasi yang disukai.

6.5.3.4 The sizeofdan _Alignofoperator

...

¶8 CONTOH 3 Dalam contoh ini, ukuran array panjang variabel dihitung dan dikembalikan dari suatu fungsi:

#include <stddef.h>

size_t fsize3(int n)
{
    char b[n+3]; // variable length array
    return sizeof b; // execution time sizeof
}
int main()
{
    size_t size;
    size = fsize3(10); // fsize3 returns 13
    return 0;
}
Jonathan Leffler
sumber
@ Davidvidow: Definisi fungsi seperti int main(){ … }tidak menentukan bahwa fungsi tidak memerlukan argumen, tetapi tidak menyediakan prototipe fungsi, AFAICT. Untuk main()itu jarang ada masalah; itu berarti bahwa jika Anda memiliki panggilan rekursif main(), argumen tidak akan diperiksa. Untuk fungsi lain, ini lebih merupakan masalah - Anda benar-benar membutuhkan prototipe dalam ruang lingkup ketika fungsi dipanggil untuk memastikan bahwa argumennya benar.
Jonathan Leffler
1
@ Davidvidowling: Anda biasanya tidak menelepon main()secara rekursif, di luar tempat-tempat seperti IOCCC. Saya punya program pengujian yang melakukannya - terutama untuk hal-hal baru. Jika Anda memiliki int i = 0; int main() { if (i++ < 10) main(i, i * i); return 0; }dan mengkompilasi dengan GCC dan tidak termasuk -Wstrict-prototypes, itu mengkompilasi dengan bersih di bawah peringatan ketat. Jika itu main(void), gagal dikompilasi.
Jonathan Leffler
61

Saya percaya itu main()harus kembali EXIT_SUCCESSatau EXIT_FAILURE. Mereka didefinisikan dalamstdlib.h

dmityugov
sumber
20
0 juga standar.
Chris Young
2
@ ChrisYoung Ada EXIT_SUCCESSdan EXIT_FAILUREkarena beberapa sistem operasi bersejarah (VMS?) Menggunakan angka yang berbeda dari 0 untuk menunjukkan kesuksesan. Ini 0 di mana-mana saat ini.
fuz
5
@ FuZxxl Anda benar, tetapi itu tidak bertentangan dengan komentar saya. EXIT_SUCCESS memang bisa bukan nol, tetapi standar (C89, C99, C11) semua mendefinisikan 0 (serta EXIT_SUCCESS) juga menjadi bentuk yang ditentukan implementasi dari status pemutusan yang berhasil.
Chris Young
2
@ FUZxxl: Memang benar VMS menggunakan nilai ganjil (seperti 1) untuk menunjukkan keberhasilan dan nilai genap (seperti 0) untuk menunjukkan kegagalan. Sayangnya, standar ANSI C asli ditafsirkan berarti bahwa EXIT_SUCCESS harus 0, jadi mengembalikan EXIT_SUCCESS dari main mendapatkan perilaku yang salah pada VMS. Hal portabel yang dapat dilakukan untuk VMS adalah menggunakan exit(EXIT_SUCCESS), yang selalu melakukan hal yang benar.
Adrian McCarthy
1
5.1.2.2.3 "Jika tipe pengembalian fungsi utama adalah tipe yang kompatibel dengan int, pengembalian dari panggilan awal ke fungsi utama setara dengan memanggil fungsi keluar dengan nilai yang dikembalikan oleh fungsi utama sebagai argumennya; 11) mencapai} yang menghentikan fungsi utama mengembalikan nilai 0. "
Lundin
38

Perhatikan bahwa standar C dan C ++ mendefinisikan dua jenis implementasi: berdiri bebas dan dihosting.

  • Lingkungan yang diinangi C90

    Formulir yang diizinkan 1 :

    int main (void)
    int main (int argc, char *argv[])
    
    main (void)
    main (int argc, char *argv[])
    /*... etc, similar forms with implicit int */

    Komentar:

    Dua yang pertama secara eksplisit dinyatakan sebagai bentuk yang diizinkan, yang lain secara implisit diizinkan karena C90 diizinkan "int implisit" untuk tipe kembali dan parameter fungsi. Tidak ada formulir lain yang diizinkan.

  • Lingkungan berdiri bebas C90

    Bentuk atau nama utama apa pun diizinkan 2 .

  • Lingkungan yang diinangi C99

    Formulir yang diizinkan 3 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */

    Komentar:

    C99 menghapus "implisit int" sehingga main()tidak lagi valid.

    Kalimat aneh dan ambigu "atau dalam beberapa cara lain yang ditentukan implementasi" telah diperkenalkan. Ini dapat diartikan sebagai "parameter untuk int main()dapat bervariasi" atau sebagai "utama dapat memiliki bentuk yang ditentukan implementasi".

    Beberapa kompiler telah memilih untuk menafsirkan standar dengan cara yang terakhir. Dapat diperdebatkan, seseorang tidak dapat dengan mudah menyatakan bahwa mereka tidak benar-benar menyesuaikan diri dengan mengutip standar itu sendiri, karena itu ambigu.

    Namun, untuk mengizinkan bentuk yang benar-benar liar main()mungkin (?) Bukan maksud dari kalimat baru ini. Dasar pemikiran C99 (bukan normatif) menyiratkan bahwa kalimat mengacu pada parameter tambahan ke int main 4 .

    Namun bagian untuk penghentian program lingkungan yang dihosting kemudian melanjutkan perdebatan tentang kasus di mana main tidak kembali ke 5 . Meskipun bagian itu tidak normatif untuk bagaimana utama harus dideklarasikan, itu pasti menyiratkan bahwa utama dapat dinyatakan dengan cara yang sepenuhnya implementasi yang ditetapkan bahkan pada sistem host.

  • C99 lingkungan berdiri bebas

    Bentuk atau nama utama apa pun diizinkan 6 .

  • Lingkungan host C11

    Formulir yang diizinkan 7 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
  • C11 lingkungan berdiri bebas

    Bentuk atau nama utama apa pun diizinkan 8 .


Catatan yang int main()tidak pernah terdaftar sebagai formulir yang valid untuk implementasi C yang di-host di salah satu versi di atas. Dalam C, tidak seperti C ++, ()dan (void)memiliki arti yang berbeda. Yang pertama adalah fitur usang yang dapat dihapus dari bahasa. Lihat C11 arah bahasa masa depan:

6.11.6 Deklarator fungsi

Penggunaan deklarator fungsi dengan tanda kurung kosong (bukan deklarator tipe parameter format prototipe) adalah fitur usang.


  • C ++ 03 lingkungan yang diinangi

    Formulir yang diizinkan 9 :

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

    Komentar:

    Perhatikan tanda kurung kosong di formulir pertama. C ++ dan C berbeda dalam hal ini, karena dalam C ++ ini berarti bahwa fungsi tidak mengambil parameter. Tetapi dalam C itu berarti bahwa ia dapat mengambil parameter apa pun.

  • C ++ 03 lingkungan berdiri bebas

    Nama fungsi yang dipanggil saat startup ditentukan oleh implementasi. Jika diberi nama main()harus mengikuti formulir 10 yang dinyatakan :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
  • C ++ 11 lingkungan yang diinangi

    Formulir yang diizinkan 11 :

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

    Komentar:

    Teks standar telah diubah tetapi memiliki arti yang sama.

  • C ++ 11 lingkungan berdiri bebas

    Nama fungsi yang dipanggil saat startup ditentukan oleh implementasi. Jika diberi nama main()harus mengikuti formulir yang dinyatakan 12 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])

Referensi

  1. ANSI X3.159-1989 2.1.2.2 Lingkungan yang dihosting. "Program startup"

    Fungsi yang dipanggil saat startup program bernama main. Implementasi menyatakan tidak ada prototipe untuk fungsi ini. Ini harus didefinisikan dengan tipe pengembalian int dan tanpa parameter:

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

    atau dengan dua parameter (disebut di sini sebagai argc dan argv, meskipun nama apa pun dapat digunakan, karena mereka lokal ke fungsi di mana mereka dinyatakan):

    int main(int argc, char *argv[]) { /* ... */ }
  2. ANSI X3.159-1989 2.1.2.1 Lingkungan berdiri bebas:

    Dalam lingkungan yang berdiri sendiri (di mana eksekusi program C dapat terjadi tanpa manfaat dari sistem operasi), nama dan jenis fungsi yang dipanggil saat startup program ditentukan oleh implementasi.

  3. ISO 9899: 1999 5.1.2.2 Lingkungan yang dihosting -> 5.1.2.2.1 Startup program

    Fungsi yang dipanggil saat startup program bernama main. Implementasi menyatakan tidak ada prototipe untuk fungsi ini. Ini harus didefinisikan dengan tipe pengembalian int dan tanpa parameter:

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

    atau dengan dua parameter (disebut di sini sebagai argc dan argv, meskipun nama apa pun dapat digunakan, karena mereka lokal ke fungsi di mana mereka dinyatakan):

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

    atau setara; 9) atau dengan cara lain yang ditentukan implementasi.

  4. Dasar Pemikiran untuk Standar Internasional - Bahasa Pemrograman - C, Revisi 5.10. 5.1.2.2 Hosted environment -> 5.1.2.2.1 Startup program

    Perilaku argumen terhadap main, dan interaksi keluar, main dan atexit (lihat §7.20.4.2) telah dikodifikasi untuk mengekang beberapa variasi yang tidak diinginkan dalam representasi string argv, dan dalam arti nilai yang dikembalikan oleh main.

    Spesifikasi argc dan argv sebagai argumen utama mengakui praktik sebelumnya yang luas. argv [argc] diperlukan untuk menjadi null pointer untuk memberikan pemeriksaan yang berlebihan untuk akhir daftar, juga atas dasar praktik umum.

    main adalah satu-satunya fungsi yang dapat dideklarasikan dengan baik dengan nol atau dua argumen. (Jumlah argumen fungsi lain harus sama persis antara doa dan definisi.) Kasus khusus ini hanya mengakui praktik luas dari meninggalkan argumen ke utama ketika program tidak mengakses string argumen program. Sementara banyak implementasi mendukung lebih dari dua argumen utama, praktik seperti itu tidak diberkati atau dilarang oleh Standar; sebuah program yang mendefinisikan utama dengan tiga argumen tidak sepenuhnya sesuai (lihat §J.5.1.).

  5. ISO 9899: 1999 5.1.2.2 Lingkungan yang dihosting -> 5.1.2.2.3 Pengakhiran program

    Jika tipe kembalinya fungsi utama adalah tipe yang kompatibel dengan int, pengembalian dari panggilan awal ke fungsi utama sama dengan memanggil fungsi keluar dengan nilai yang dikembalikan oleh fungsi utama sebagai argumennya; 11) mencapai }yang mengakhiri fungsi utama mengembalikan nilai 0. Jika tipe kembali tidak kompatibel dengan int, status terminasi yang dikembalikan ke lingkungan host tidak ditentukan.

  6. ISO 9899: 1999 5.1.2.1 Lingkungan berdiri bebas

    Dalam lingkungan yang berdiri sendiri (di mana eksekusi program C dapat terjadi tanpa manfaat dari sistem operasi), nama dan jenis fungsi yang dipanggil saat startup program ditentukan oleh implementasi.

  7. ISO 9899: 2011 5.1.2.2 Hosted environment -> 5.1.2.2.1 Startup program

    Bagian ini identik dengan C99 yang dikutip di atas.

  8. ISO 9899: 1999 5.1.2.1 Lingkungan berdiri bebas

    Bagian ini identik dengan C99 yang dikutip di atas.

  9. ISO 14882: 2003 3.6.1 Fungsi utama

    Suatu implementasi tidak akan menentukan fungsi utama. Fungsi ini tidak akan kelebihan beban. Ia harus memiliki tipe pengembalian tipe int, tetapi jika tidak jenisnya ditentukan implementasi. Semua implementasi harus memungkinkan kedua definisi utama berikut:

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

    dan

    int main(int argc, char* argv[]) { /* ... */ }
  10. ISO 14882: 2003 3.6.1 Fungsi utama

    Ini adalah implementasi yang ditentukan apakah suatu program dalam lingkungan berdiri bebas diperlukan untuk mendefinisikan fungsi utama.

  11. ISO 14882: 2011 3.6.1 Fungsi utama

    Suatu implementasi tidak akan menentukan fungsi utama. Fungsi ini tidak akan kelebihan beban. Ia harus memiliki tipe pengembalian tipe int, tetapi jika tidak jenisnya ditentukan implementasi. Semua implementasi harus memungkinkan keduanya

    - fungsi dari () pengembalian int dan

    - fungsi (int, pointer ke pointer ke char) mengembalikan int

    sebagai jenis utama (8.3.5).

  12. ISO 14882: 2011 3.6.1 Fungsi utama

    Bagian ini identik dengan C ++ 03 yang dikutip di atas.

Lundin
sumber
Satu pertanyaan: Apakah standar C ++ berarti bahwa tanda tangan dari fungsi startup di lingkungan bebas menentukan implementasi juga didefinisikan? Sebagai contoh, suatu implementasi bisa mendefinisikan fungsi startup menjadi: int my_startup_function ()atau int my_startup_function (int argc, char *argv[])tetapi dapatkah itu, misalnya: char my_startup_function (long argc, int *argv[])sebagai fungsi startup juga? Saya kira tidak, bukan? Juga, bukankah itu ambigu juga?
Utku
@Utku Ini dapat memiliki tanda tangan apa saja, asalkan tidak dinamai main()karena dengan itu harus menggunakan salah satu tanda tangan yang terdaftar. Saya akan membayangkan yang paling umum adalah void my_startup_function (), karena tidak masuk akal untuk kembali dari program pada sistem berdiri bebas.
Lundin
1
Saya melihat. Tetapi jika diizinkan untuk menggunakan nama dan tanda tangan apa pun untuk fungsi startup, mengapa tidak mengizinkan untuk menggunakan tanda tangan yang berbeda mainjuga? Maaf kalau itu bukan pertanyaan cerdas tapi saya tidak bisa memahami alasan di baliknya.
Utku
@Utku C dan C ++ berbeda di sana. Adapun mengapa C ++ menegakkan ini, saya tidak tahu, tidak ada alasan. Saya menduga pelakunya utama (pun intended) adalah Stroustrup yang sejak awal menyatakan bahwa utama harus kembali ke periode. Karena ketika ia membuat versi C ++ pertama, ia hanya digunakan untuk sistem yang dihosting. Dalam posting terkait, Stroustrup tampaknya masih lupa tentang keberadaan implementasi berdiri bebas: misalnya, ia mengabaikan merujuk ke sub bab implementasi host dari standar C, mengabaikan keberadaan bab 5.1.2.1.
Lundin
1
Hal penting tentang rancangan standar C11 adalah bahwa meskipun func()dianggap usang, rancangan itu sendiri menggunakan int main()contoh-contohnya sendiri.
Antti Haapala
29

Kembalikan 0 pada kesuksesan dan bukan nol untuk kesalahan. Ini adalah standar yang digunakan oleh skrip UNIX dan DOS untuk mencari tahu apa yang terjadi dengan program Anda.

Lou Franco
sumber
8

main() di C89 dan K&R C jenis pengembalian tidak ditentukan default ke 'int`.

return 1? return 0?
  1. Jika Anda tidak menulis pernyataan pengembalian int main(), penutupan {akan mengembalikan 0 secara default.

  2. return 0atau return 1akan diterima oleh proses induk. Dalam sebuah shell ia masuk ke variabel shell, dan jika Anda menjalankan program Anda membentuk sebuah shell dan tidak menggunakan variabel itu maka Anda tidak perlu khawatir tentang nilai pengembalian main().

Lihat Bagaimana saya bisa mendapatkan apa fungsi utama saya telah kembali? .

$ ./a.out
$ echo $?

Dengan cara ini Anda dapat melihat bahwa itu adalah variabel $?yang menerima byte paling signifikan dari nilai pengembalian main().

Dalam skrip Unix dan DOS, return 0keberhasilan dan non-nol untuk kesalahan biasanya dikembalikan. Ini adalah standar yang digunakan oleh skrip Unix dan DOS untuk mencari tahu apa yang terjadi dengan program Anda dan mengendalikan seluruh aliran.

Jeegar Patel
sumber
4
Sebenarnya, $?bukan variabel lingkungan; itu adalah variabel shell yang telah ditentukan (atau built-in). Perbedaannya sulit dikenali, tetapi jika Anda menjalankan env(tanpa argumen), ia mencetak lingkungan, dan $?tidak akan ditampilkan di lingkungan.
Jonathan Leffler
1
Mengembalikan 0 secara otomatis ketika main "fall of the end" hanya di C ++ dan C99 dan seterusnya, bukan di C90.
Kaz
Typo: "closing {" seharusnya }. SO tidak akan mengizinkan saya melakukan edit sekecil ini.
Spencer
7

Ingatlah bahwa, meskipun Anda mengembalikan int, beberapa OS (Windows) memotong nilai yang dikembalikan ke satu byte (0-255).

Ferruccio
sumber
4
Unix melakukan hal yang sama, seperti halnya kebanyakan sistem operasi lain mungkin. Saya tahu VMS melakukan hal-hal aneh yang luar biasa dengannya sehingga mengembalikan apa pun selain EXIT_SUCCESS atau EXIT_FAILURE meminta masalah.
Leon Timmermans
2
MSDN memohon untuk berbeda: ketika dilaporkan melalui mscorlib, kode keluar adalah ditandatangani 32-bit integer . Ini tampaknya menyiratkan bahwa pustaka runtime C yang memotong kode keluar rusak.
Ya, ini salah. Pada Windows integer 32-bit dikembalikan (dan dikonversi ke unsigned). Ini sama pada sistem UNIX dengan integer 32-bit. Tetapi cangkang UNIX pada kedua sistem biasanya hanya akan mempertahankan bilangan bulat 8-bit yang tidak ditandatangani.
John McFarlane
4

Nilai kembali dapat digunakan oleh sistem operasi untuk memeriksa bagaimana program ditutup.

Nilai pengembalian 0 biasanya berarti OK di sebagian besar sistem operasi (yang bisa saya pikirkan).

Itu juga dapat diperiksa ketika Anda memanggil proses sendiri, dan melihat apakah program keluar dan selesai dengan benar.

Ini tidak hanya sebuah konvensi pemrograman.

Yochai Timmer
sumber
Tidak ada dalam pertanyaan yang menunjukkan bahwa sistem operasi hadir. Mengembalikan nilai tidak masuk akal dalam sistem berdiri bebas.
Lundin
3

Nilai pengembalian main()menunjukkan bagaimana program keluar. Jika nilai pengembaliannya zeroberarti eksekusi berhasil sementara nilai non-nol akan menyatakan bahwa ada yang tidak beres dalam eksekusi.

fuddin
sumber
1
Ini adalah komentar, bukan jawaban untuk pertanyaan itu.
Lundin
2

Saya mendapat kesan bahwa standar menentukan bahwa utama tidak memerlukan nilai kembali karena pengembalian yang berhasil adalah berbasis OS (nol dalam satu bisa berupa keberhasilan atau kegagalan dalam yang lain), oleh karena itu tidak adanya pengembalian adalah isyarat untuk kompiler untuk memasukkan pengembalian yang berhasil itu sendiri.

Namun saya biasanya mengembalikan 0.

graham.reeds
sumber
C99 (dan C ++ 98) memungkinkan Anda untuk menghilangkan pernyataan kembali dari utama; C89 tidak memungkinkan Anda untuk menghilangkan pernyataan kembali.
Jonathan Leffler
Ini adalah komentar, bukan jawaban.
Lundin
Ini tidak memberikan jawaban untuk pertanyaan itu. Untuk mengkritik atau meminta klarifikasi dari penulis, tinggalkan komentar di bawah posting mereka.
Steve Lillis
6
@SteveLillis: Pada tahun 2008 SO tidak memiliki bagian komentar.
graham.reeds
2

Kembali 0 harus memberi tahu programmer bahwa program telah berhasil menyelesaikan pekerjaan.

Vamsi Pavan Mahesh
sumber
Mengembalikan 1 dari main()biasanya sinyal kesalahan terjadi; mengembalikan 0 sinyal sukses. Jika program Anda selalu gagal, maka 1 OK, tetapi itu bukan ide terbaik.
Jonathan Leffler
1
@ JonathanLeffler: Arti kembali 1dari mainadalah implementasi-didefinisikan. Satu-satunya nilai yang didefinisikan bahasa adalah 0, EXIT_SUCCESS(sering didefinisikan sebagai 0), dan EXIT_FAILURE. Di OpenVMS, return 1;menunjukkan penghentian yang sukses .
Keith Thompson
VMS tidak 'normal' - dalam arti dari apa yang saya katakan. Bukankah ini seperti 'nilai ganjil adalah kesuksesan; bahkan nilai kegagalan 'pada VMS?
Jonathan Leffler
2

Menghilangkan return 0

Ketika program C atau C ++ mencapai akhir mainkompiler akan secara otomatis menghasilkan kode untuk mengembalikan 0, jadi tidak perlu menempatkan return 0;secara eksplisit di akhir main.

Catatan: ketika saya membuat saran ini, hampir selalu diikuti oleh salah satu dari dua jenis komentar: "Saya tidak tahu itu." atau "Itu saran yang buruk!" Alasan saya adalah aman dan bermanfaat untuk mengandalkan perilaku kompiler yang secara eksplisit didukung oleh standar. Untuk C, sejak C99; lihat ISO / IEC 9899: 1999 bagian 5.1.2.2.3:

[...] pengembalian dari panggilan awal ke mainfungsi setara dengan memanggil exitfungsi dengan nilai yang dikembalikan oleh mainfungsi sebagai argumennya; mencapai }yang mengakhiri mainfungsi mengembalikan nilai 0.

Untuk C ++, sejak standar pertama pada tahun 1998; lihat ISO / IEC 14882: 1998 bagian 3.6.1:

Jika kontrol mencapai ujung main tanpa menemui pernyataan pengembalian, efeknya adalah menjalankan kembali 0;

Semua versi dari kedua standar sejak saat itu (C99 dan C ++ 98) mempertahankan gagasan yang sama. Kami mengandalkan fungsi anggota yang dibuat secara otomatis di C ++, dan beberapa orang menulis return;pernyataan eksplisit di akhir voidfungsi. Alasan untuk menghilangkan sepertinya mendidih menjadi "itu terlihat aneh" . Jika, seperti saya, Anda ingin tahu tentang alasan perubahan standar C membaca pertanyaan ini . Juga perhatikan bahwa pada awal 1990-an ini dianggap "praktik ceroboh" karena itu adalah perilaku yang tidak terdefinisi (meskipun didukung secara luas) pada saat itu.

Selain itu, Pedoman Inti C ++ berisi beberapa instance dari menghilangkan return 0;pada akhir maindan tidak ada contoh di mana pengembalian eksplisit ditulis. Meskipun belum ada pedoman khusus tentang topik khusus ini dalam dokumen itu, yang tampaknya setidaknya merupakan dukungan diam-diam dari praktik tersebut.

Jadi saya menganjurkan menghilangkannya; yang lain tidak setuju (sering dengan keras!) Dalam kasus apa pun, jika Anda menemukan kode yang menghilangkannya, Anda akan tahu bahwa itu secara eksplisit didukung oleh standar dan Anda akan tahu apa artinya.

Edward
sumber
2
Ini adalah saran yang buruk karena kompiler yang hanya menerapkan C89, bukan standar kemudian, masih sangat umum (saya menulis ini pada 2017) dan akan tetap sangat umum untuk masa mendatang. Sebagai contoh, terakhir saya memeriksa tidak ada versi kompiler Microsoft yang mengimplementasikan C99, dan ini adalah pemahaman saya bahwa ini juga masih khas untuk kompiler sistem embedded yang bukan GCC.
zwol
4
@ zwol: Siapa pun yang tidak memiliki pilihan selain menggunakan kompiler yang kedaluwarsa pada 28 tahun mungkin memiliki lebih banyak masalah daripada memutuskan apakah akan secara eksplisit memasukkan return 0;, namun saya akan mencatat bahwa banyak kompiler pada era itu juga menerapkan implisit return 0;bahkan sebelum itu terstandarisasi.
Edward
2
Sebenarnya, saya melakukan banyak pekerjaan embedded system dan belum menemukan kompiler yang tidak mendukung implisit return 0selama lebih dari satu dekade. Versi Microsoft C saat ini juga mendukungnya . Mungkin informasi Anda kedaluwarsa?
Edward
2
Saya bisa menghargai ini menjadi kontroversial di C, hampir (per @ zwol). Dalam C ++ setiap kontroversi seputar ini adalah omong kosong belaka.
Lightness Races in Orbit
2
@Edward Saya tidak mengatakan kontroversi itu tidak ada, saya katakan itu omong kosong: P
Lightness Races in Orbit
1

Apa yang harus dikembalikan tergantung pada apa yang ingin Anda lakukan dengan executable. Misalnya jika Anda menggunakan program Anda dengan shell baris perintah, maka Anda harus mengembalikan 0 untuk sukses dan bukan nol untuk kegagalan. Maka Anda akan dapat menggunakan program dalam shell dengan pemrosesan bersyarat tergantung pada hasil kode Anda. Anda juga dapat menetapkan nilai bukan nol sesuai interpretasi Anda, misalnya untuk kesalahan kritis poin keluar program yang berbeda dapat menghentikan program dengan nilai keluar yang berbeda, dan yang tersedia untuk shell panggilan yang dapat memutuskan apa yang harus dilakukan dengan memeriksa nilai yang dikembalikan. Jika kode ini tidak dimaksudkan untuk digunakan dengan shell dan nilai yang dikembalikan tidak mengganggu siapa pun maka mungkin dihilangkan. Saya pribadi menggunakan tanda tanganint main (void) { .. return 0; .. }

phoxis
sumber
Format main () ditentukan oleh implementasi, artinya kompiler. Programmer tidak dapat memilih formulir mana yang akan dipilih, kecuali ketika kompiler mendukung beberapa formulir.
Lundin
@Lundin Jenis kembali akan implementasi oleh implementasi. Tetapi nilai yang akan dikembalikan ditentukan oleh programmer. C99 Bagian 5.1.2.2.3 menyebutkan bahwa tipe pengembalian mainkompatibel dengan int. Oleh karena itu kembali inttidak akan menjadi masalah. Meskipun jenis pengembalian lainnya diperbolehkan, tetapi dalam hal itu variabel lingkungan yang memiliki nilai pengembalian tidak ditentukan. Tetapi jika seorang programmer melakukannya return 0;maka dalam bash itu dapat digunakan untuk membuat cabang.
phoxis
1

Jika Anda benar-benar memiliki masalah yang terkait dengan efisiensi pengembalian integer dari suatu proses, Anda mungkin harus menghindari untuk memanggil proses itu berkali-kali sehingga nilai pengembalian ini menjadi masalah.

Jika Anda melakukan ini (panggil proses berkali-kali), Anda harus menemukan cara untuk menempatkan logika Anda langsung di dalam pemanggil, atau dalam file DLL, tanpa mengalokasikan proses khusus untuk setiap panggilan; alokasi beberapa proses membawa Anda masalah efisiensi yang relevan dalam kasus ini.

Secara terperinci, jika Anda hanya ingin tahu apakah pengembalian 0 lebih atau kurang efisien daripada mengembalikan 1, itu bisa bergantung dari kompiler dalam beberapa kasus, tetapi secara umum, dengan asumsi mereka dibaca dari sumber yang sama (lokal, bidang, konstan, disematkan dalam kode, hasil fungsi, dll.) ini membutuhkan jumlah siklus clock yang persis sama.

Luca C.
sumber
1

Berikut ini adalah demonstrasi kecil penggunaan kode pengembalian ...

Saat menggunakan berbagai alat yang disediakan oleh terminal Linux, seseorang dapat menggunakan kode pengembalian misalnya untuk penanganan kesalahan setelah proses selesai. Bayangkan file teks myfile berikut ada:

Ini adalah beberapa contoh untuk memeriksa cara kerja grep.

Ketika Anda menjalankan perintah grep, sebuah proses dibuat. Setelah melalui (dan tidak rusak) ia mengembalikan beberapa kode antara 0 dan 255. Misalnya:

$ grep order myfile

Jika kamu melakukan

$ echo $?
$ 0

Anda akan mendapatkan 0. Mengapa? Karena grep menemukan kecocokan dan mengembalikan kode keluar 0, yang merupakan nilai biasa untuk keluar dengan sukses. Mari kita periksa lagi tetapi dengan sesuatu yang tidak ada di dalam file teks kita dan dengan demikian tidak ditemukan kecocokan:

$ grep foo myfile
$ echo $?
$ 1

Karena grep gagal mencocokkan token "foo" dengan konten file kami, kode pengembaliannya adalah 1 (ini adalah kasus biasa ketika kegagalan terjadi tetapi seperti yang dinyatakan di atas Anda memiliki banyak nilai untuk dipilih).

Sekarang skrip bash berikut (cukup ketik di terminal Linux) meskipun sangat mendasar harus memberikan beberapa ide penanganan kesalahan:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

Setelah baris kedua tidak ada yang dicetak ke terminal karena "foo" membuat grep return 1 dan kami memeriksa apakah kode pengembalian grep sama dengan 0. Pernyataan bersyarat kedua menggemakan pesannya di baris terakhir karena benar karena LIHAT LIHAT == 1.

Seperti yang Anda lihat jika Anda memanggil ini dan itu proses itu kadang-kadang penting untuk melihat apa yang telah dikembalikan (dengan nilai pengembalian main ()).

rbaleksandar
sumber
Dalam skrip shell, Anda akan menggunakan if grep foo myfile; then echo 'Match found'; else echo 'No match was found'; fi- menguji status pengembalian secara langsung. Jika Anda ingin mengambil status (untuk pelaporan, dll), maka Anda menggunakan tugas. Anda mungkin menggunakan if grep foo myfile; CHECK=$?; [ "$CHECK" = 0 ]; then echo 'Match found'; else echo 'No match was found'; fiatau Anda mungkin menggunakan tiga baris. Anda mungkin juga menggunakan pilihan -sdan -quntuk grepmencegah pertandingan atau pesan error rutin muncul. Namun, ini adalah shell minutiae - titik kunci, bahwa status keluar dapat bermanfaat - tidak masalah.
Jonathan Leffler
1

Apa cara yang benar (paling efisien) untuk mendefinisikan fungsi utama () di C dan C ++ - int main () atau void main () - dan mengapa?

Kata-kata "(paling efisien)" tidak mengubah pertanyaan. Kecuali Anda berada di lingkungan yang berdiri sendiri, ada satu cara universal yang benar untuk menyatakan main(), dan itu adalah mengembalikan int.

Apa yang harus main()dikembalikan dalam C dan C ++?

Ini bukan apa yang harus main() kembali, itu apa yang dilakukannya main() kembali. main()tentu saja adalah fungsi yang dipanggil orang lain. Anda tidak memiliki kendali atas kode yang memanggil main(). Karena itu, Anda harus mendeklarasikan main()dengan tanda tangan yang benar untuk mencocokkan peneleponnya. Anda tidak punya pilihan dalam masalah ini. Anda tidak perlu bertanya pada diri sendiri apa yang lebih atau kurang efisien, atau apa gaya yang lebih baik atau lebih buruk, atau apa pun seperti itu, karena jawabannya sudah didefinisikan dengan sangat baik, untuk Anda, oleh standar C dan C +. Ikuti saja mereka.

Jika int main () lalu kembalikan 1 atau kembalikan 0?

0 untuk sukses, bukan nol untuk kegagalan. Sekali lagi, bukan sesuatu yang Anda perlu (atau mulai) pilih: itu ditentukan oleh antarmuka yang seharusnya Anda sesuaikan.

Steve Summit
sumber