Apa deklarasi utama yang tepat?

147

Apa tanda tangan yang tepat dari mainfungsi di C ++? Apa jenis pengembalian yang benar, dan apa artinya mengembalikan nilai dari main? Apa tipe parameter yang diizinkan, dan apa artinya?

Apakah ini khusus sistem? Apakah aturan itu berubah seiring waktu? Apa yang terjadi jika saya melanggar mereka?

fredoverflow
sumber
1
Ini sangat terkait erat dengan, atau duplikat, Apa yang harus mainkembali dalam C dan C ++ .
Jonathan Leffler
@JonathanLeffler Tidak main-main ... ditambahkan ke daftar duplikat dalam revisi 6 sekitar 8 bulan lalu.
fredoverflow

Jawaban:

192

The mainFungsi harus dinyatakan sebagai fungsi non-anggota di namespace global. Ini berarti bahwa itu tidak bisa menjadi fungsi anggota statis atau non-statis kelas, juga tidak dapat ditempatkan di namespace (bahkan namespace yang tidak disebutkan namanya).

Nama maintidak dicadangkan di C ++ kecuali sebagai fungsi di namespace global. Anda bebas untuk mendeklarasikan entitas lain yang dinamai main, termasuk di antaranya, kelas, variabel, enumerasi, fungsi anggota, dan fungsi non-anggota yang tidak ada dalam ruang nama global.

Anda bisa mendeklarasikan fungsi yang dinamai mainsebagai fungsi anggota atau dalam namespace, tetapi fungsi seperti itu tidak akan menjadi mainfungsi yang menentukan di mana program dimulai.

The mainFungsi tidak dapat dinyatakan sebagai staticatau inline. Itu juga tidak bisa kelebihan beban; hanya ada satu fungsi yang disebutkan maindalam namespace global.

The mainFungsi tidak dapat digunakan dalam program Anda: Anda tidak diizinkan untuk memanggil mainfungsi dari mana saja di kode Anda, atau apakah Anda diperbolehkan untuk mengambil alamat.

Jenis pengembalian mainharusint . Tidak ada jenis pengembalian lain yang diizinkan (aturan ini dicetak tebal karena sangat umum untuk melihat program yang salah yang menyatakan maindengan jenis pengembalian void; ini mungkin aturan yang paling sering dilanggar mengenai mainfungsi).

Ada dua deklarasi mainyang harus diizinkan:

int main()               // (1)
int main(int, char*[])   // (2)

Dalam (1) , tidak ada parameter.

Dalam (2) , ada dua parameter dan mereka secara konvensional dinamai argcdan argv, masing-masing. argvadalah pointer ke array string C yang mewakili argumen ke program. argcadalah jumlah argumen dalam argvarray.

Biasanya, argv[0]berisi nama program, tetapi ini tidak selalu terjadi. argv[argc]dijamin menjadi null pointer.

Perhatikan bahwa karena argumen tipe array (seperti char*[]) benar-benar hanya argumen tipe pointer yang menyamar, dua berikut ini adalah cara yang benar untuk menulis (2) dan keduanya memiliki arti yang persis sama:

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

Beberapa implementasi memungkinkan jenis dan jumlah parameter lainnya; Anda harus memeriksa dokumentasi implementasi Anda untuk melihat apa yang didukungnya.

main()diharapkan mengembalikan nol untuk menunjukkan keberhasilan dan bukan nol untuk menunjukkan kegagalan. Anda tidak diharuskan untuk menulis returnpernyataan secara eksplisit di main(): jika Anda membiarkan main()kembali tanpa returnpernyataan eksplisit , itu sama seperti jika Anda telah menulis return 0;. Dua main()fungsi berikut memiliki perilaku yang sama:

int main() { }
int main() { return 0; }

Ada dua makro, EXIT_SUCCESSdan EXIT_FAILURE, yang didefinisikan dalam <cstdlib>yang juga dapat dikembalikan dari main()untuk menunjukkan keberhasilan dan kegagalan, masing-masing.

Nilai yang dikembalikan oleh main()diteruskan ke exit()fungsi, yang mengakhiri program.

Perhatikan bahwa semua ini hanya berlaku ketika kompilasi untuk lingkungan yang dihosting (secara informal, lingkungan di mana Anda memiliki perpustakaan standar penuh dan ada OS yang menjalankan program Anda). Dimungkinkan juga untuk mengkompilasi program C ++ untuk lingkungan yang berdiri sendiri (misalnya, beberapa jenis sistem tertanam), di mana startup dan terminasi sepenuhnya ditentukan oleh implementasi dan sebuah main()fungsi bahkan mungkin tidak diperlukan. Jika Anda menulis C ++ untuk OS desktop modern, Anda mengkompilasi untuk lingkungan yang dihosting.

James McNellis
sumber
1
IIRC satu-satunya nilai pengembalian yang dijamin adalah 0, EXIT_SUCCESS (efek yang sama dengan 0), dan EXIT_FAILURE. EDIT: Ah, OK, nilai status non-nol lainnya dapat dikembalikan, tetapi dengan makna yang ditentukan implementasi Hanya EXIT_FAILURE yang dijamin ditafsirkan dengan cara tertentu sebagai nilai kegagalan.
Derrick Turk
4
@Synetech: Pertanyaan bertanya dalam kalimat pertama, "Apa tanda tangan yang tepat dari fungsi utama di C ++?" dan pertanyaannya ditandai [c ++] dan [c ++ - faq]. Saya tidak dapat menahannya jika pengguna Java atau C # (atau siapa pun) masih bingung. C # Mainharus merupakan fungsi anggota statis karena bahkan tidak memiliki fungsi nonanggota. Bahkan C89 mainharus kembali int. Saya tidak cukup akrab dengan K&R C untuk mengetahui aturan yang tepat, tetapi saya kira itu juga mengharuskan mainuntuk kembali intkarena maintanpa jenis pengembalian agak umum dan tidak ada tipe = tersirat intdalam K&R.
James McNellis
3
@Suhail: Karena standar bahasa mengatakan tipe pengembaliannya int.
James McNellis
1
@Suhail: Ya. Kode Anda tidak akan benar C ++ dan banyak kompiler akan menolak kode Anda.
James McNellis
2
@Suhail: Visual C ++ memungkinkan voidtipe kembali sebagai ekstensi bahasa . Kompiler yang tidak mengizinkannya termasuk GCC dan Comeau.
James McNellis
15

Dari Dokumen standar., 3.6.1.2 Fungsi Utama ,

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[]) { / ... / }

Dalam bentuk yang terakhir argcharus ada jumlah argumen yang diteruskan ke program dari lingkungan di mana program dijalankan. Jika argc bukan nol argumen ini harus diberikan dalam argv [0] melalui argv [argc-1] sebagai pointer ke inisial karakter string multibyte null-dihentikan ....

Semoga itu bisa membantu ..

berhubungan
sumber
2
apakah ada alasan khusus mengapa jenis pengembalian mainharus int?
Suhail Gupta
1
@SuhailGupta: Agar proses panggilan mengetahui apakah proses ini harus dianggap berhasil atau tidak. Mengizinkan voidistirahat model itu. Bahkan tidak masuk akal jika Anda mengatakan itu berarti "selalu menganggap kesuksesan". Karena Anda tidak punya cara untuk mengatakan jika prosesnya benar-benar gagal, jadi apakah Anda benar-benar berhasil? Tidak, kembali int.
Lightness Races dalam Orbit
4

Kata-kata persis dari standar terbaru yang diterbitkan (C ++ 14) adalah:

Suatu implementasi harus memungkinkan keduanya

  • fungsi ()mengembalikan intdan

  • fungsi dari (int, pointer ke pointer untuk char)kembaliint

sebagai jenis main.

Ini memperjelas bahwa ejaan alternatif diizinkan selama mainjenis int()atau jenis ejaannya int(int, char**). Jadi yang berikut ini juga diizinkan:

  • int main(void)
  • auto main() -> int
  • int main ( )
  • signed int main()
  • typedef char **a; typedef int b, e; e main(b d, a c)
MM
sumber
1
NB. Saya memposting jawaban ini seperti dalam komentar ke utas lain, seseorang mencoba mengutip utas ini sebagai bukti yang int main(void)tidak benar di C ++.
MM
3
@Stargateur auto main() -> inttidak memiliki tipe pengembalian yang disimpulkan. Perhatikan {in "(auto main () {... tidak diizinkan)" dan tolong pelajari untuk mengetahui kapan Anda belum cukup tahu untuk menambahkan sesuatu yang bermakna.
3

Dua induk yang valid adalah int main()dan int main(int, char*[]). Hal lain mungkin dikompilasi atau tidak. Jika maintidak secara eksplisit mengembalikan nilai, 0 secara implisit dikembalikan.

stonemetal
sumber
1
Saya belum pernah melihat kode tidak bisa dikompilasi ketika saya menyebutkan jenis kembali mainmenjadi batal. Apakah ada alasan khusus bahwa tipe pengembalian utama harus int?
Suhail Gupta
4
Spesifikasi bahasa mengatakan main harus memiliki tipe pengembalian int. Jenis pengembalian lainnya yang diizinkan oleh kompiler Anda adalah penyempurnaan spesifik kompiler. Pada dasarnya menggunakan void berarti Anda memprogram dalam bahasa yang mirip tetapi tidak dengan C ++.
stonemetal
2
Alasan standar membutuhkan intsebagai tipe pengembalian mainadalah bahwa nilai ini diserahkan ke shell sebagai kode keluar program, dan shmengharapkan a int.
uckelman
Mungkin alasannya adalah disiplin? Mungkin ada lebih dari satu jalan keluar. Jika tipe yang dikembalikan adalah voidmereka semua diam. Dengan intkita harus menentukan nilai keluar spesifik untuk setiap pengembalian dari main.
Andreas Spindler
2

Detail tentang nilai pengembalian dan artinya

Per 3.6.1 ( [basic.start.main]):

Pernyataan kembali dalam mainmemiliki efek meninggalkan mainfungsi (menghancurkan objek dengan durasi penyimpanan otomatis) dan memanggil std::exitdengan nilai kembali sebagai argumen. Jika kontrol mencapai akhir maintanpa menemukan returnpernyataan, efeknya adalah menjalankan

return 0;

Perilaku std::exitterperinci di bagian 18.5 ( [support.start.term]), dan menjelaskan kode status:

Akhirnya, kontrol dikembalikan ke lingkungan host. Jika statusnya nol atau EXIT_SUCCESS, bentuk yang ditentukan implementasi dari status pemutusan yang berhasil dikembalikan. Jika statusnya adalah EXIT_FAILURE, suatu bentuk yang ditentukan implementasi dari status tidak berhasilnya pemutusan dikembalikan. Kalau tidak, status yang dikembalikan ditentukan oleh implementasi.

Ben Voigt
sumber