Bagian $ 3.6.1 / 1 dari C ++ Standard berbunyi,
Suatu program harus mengandung fungsi global yang disebut main , yang merupakan awal dari program yang ditunjuk .
Sekarang pertimbangkan kode ini,
int square(int i) { return i*i; }
int user_main()
{
for ( int i = 0 ; i < 10 ; ++i )
std::cout << square(i) << endl;
return 0;
}
int main_ret= user_main();
int main()
{
return main_ret;
}
Kode contoh ini melakukan apa yang ingin saya lakukan, yaitu mencetak kuadrat dari 0 hingga 9, sebelum masuk ke main()
fungsi yang seharusnya menjadi "awal" dari program.
Saya juga mengkompilasinya dengan -pedantic
opsi, GCC 4.5.0. Tidak ada kesalahan, bahkan peringatan!
Jadi pertanyaan saya adalah,
Apakah kode ini benar-benar sesuai standar?
Jika itu sesuai standar, maka apakah itu tidak membatalkan apa yang dikatakan Standar? main()
belum memulai program ini! user_main()
dieksekusi sebelum main()
.
Saya mengerti bahwa untuk menginisialisasi variabel global main_ret
, use_main()
pertama-tama dijalankan tetapi itu adalah hal yang berbeda sama sekali; intinya adalah, itu tidak valid pernyataan dikutip $ 3.6.1 / 1 dari Standar, karena main()
BUKAN awal program; ini sebenarnya adalah akhir dari program ini !
EDIT:
Bagaimana Anda mendefinisikan kata 'mulai'?
Itu bermuara pada definisi frase "mulai dari program" . Jadi, bagaimana tepatnya Anda mendefinisikannya?
main()
sebagai "awal program"static
durasi penyimpanan, dan dengan demikian, objek-objek ini milik unit terjemahan yang berbeda dapat diinisialisasi dalam urutan apa pun (karena urutan tidak ditentukan oleh standar). Saya tidak yakin apakah itu menjawab pertanyaan Anda, meskipun itu yang bisa saya katakan dalam konteks topik ini.Anda salah membaca kalimat.
Standar ini mendefinisikan kata "mulai" untuk keperluan sisa standar. Itu tidak mengatakan bahwa tidak ada kode yang dijalankan sebelum
main
dipanggil. Dikatakan bahwa awal program dianggap berada pada fungsinyamain
.Program Anda patuh. Program Anda belum "mulai" sampai main dimulai. Konstruktor dipanggil sebelum program Anda "dimulai" sesuai dengan definisi "mulai" dalam standar, tetapi itu tidak terlalu penting. BANYAK kode dijalankan sebelum
main
ini pernah disebut dalam setiap program, tidak hanya contoh ini.Untuk keperluan diskusi, kode konstruktor Anda dijalankan sebelum 'mulai' program, dan yang sepenuhnya sesuai dengan standar.
sumber
Program Anda tidak akan ditautkan dan karenanya tidak akan berjalan kecuali ada yang utama. Namun main () tidak menyebabkan dimulainya eksekusi program karena objek pada level file memiliki konstruktor yang berjalan sebelumnya dan akan mungkin untuk menulis seluruh program yang menjalankan masa hidupnya sebelum main () tercapai dan membiarkan main itu sendiri memiliki tubuh kosong.
Pada kenyataannya untuk menegakkan ini, Anda harus memiliki satu objek yang dibangun sebelum utama dan konstruktornya untuk memanggil semua aliran program.
Lihat ini:
Aliran program Anda akan secara efektif berasal
Foo::Foo()
sumber
Anda menandai pertanyaan sebagai "C" juga, kemudian, berbicara tentang C, inisialisasi Anda akan gagal sesuai bagian 6.7.8 "Inisialisasi" dari standar ISO C99.
Yang paling relevan dalam kasus ini tampaknya menjadi kendala # 4 yang mengatakan:
Jadi, jawaban untuk pertanyaan Anda adalah bahwa kode tidak sesuai dengan standar C.
Anda mungkin ingin menghapus tag "C" jika Anda hanya tertarik dengan standar C ++.
sumber
Bagian 3.6 secara keseluruhan sangat jelas tentang interaksi
main
dan inisialisasi dinamis. "Awal yang ditentukan dari program" tidak digunakan di tempat lain dan hanya deskriptif dari maksud umummain()
. Tidak masuk akal untuk menafsirkan satu frasa dengan cara normatif yang bertentangan dengan persyaratan yang lebih rinci dan jelas dalam Standar.sumber
Compiler sering harus menambahkan kode sebelum main () untuk menjadi standar compliant. Karena standar menetapkan bahwa inisialisasi global / statika harus dilakukan sebelum program dijalankan. Dan seperti yang disebutkan, hal yang sama berlaku untuk konstruktor objek yang ditempatkan pada ruang lingkup file (global).
Dengan demikian pertanyaan awal juga relevan untuk C, karena dalam program C Anda masih memiliki inisialisasi global / statis yang harus dilakukan sebelum program dapat dimulai.
Standar mengasumsikan bahwa variabel-variabel ini diinisialisasi melalui "sihir", karena mereka tidak mengatakan bagaimana mereka harus ditetapkan sebelum inisialisasi program. Saya pikir mereka menganggap itu sebagai sesuatu di luar ruang lingkup standar bahasa pemrograman.
Sunting: Lihat misalnya ISO 9899: 1999 5.1.2:
Teori di balik bagaimana "sihir" ini harus dilakukan kembali ke kelahiran C, ketika itu adalah bahasa pemrograman yang dimaksudkan untuk digunakan hanya untuk OS UNIX, pada komputer berbasis RAM. Secara teori, program akan dapat memuat semua data pra-inisialisasi dari file yang dapat dieksekusi ke dalam RAM, pada saat yang sama ketika program itu sendiri diunggah ke RAM.
Sejak itu, komputer dan OS telah berevolusi, dan C digunakan di area yang jauh lebih luas dari yang diperkirakan semula. OS PC modern memiliki alamat virtual dll, dan semua sistem tertanam menjalankan kode dari ROM, bukan RAM. Jadi ada banyak situasi di mana RAM tidak dapat diatur "secara otomatis".
Juga, standarnya terlalu abstrak untuk mengetahui apa-apa tentang tumpukan dan memproses memori dll. Hal-hal ini harus dilakukan juga, sebelum program dimulai.
Oleh karena itu, hampir setiap program C / C ++ memiliki beberapa kode init / "copy-down" yang dieksekusi sebelum main dipanggil, agar sesuai dengan aturan inisialisasi standar.
Sebagai contoh, sistem embedded biasanya memiliki opsi yang disebut "startup non-ISO compliant" di mana seluruh fase inisialisasi dilewati karena alasan kinerja, dan kemudian kode sebenarnya dimulai langsung dari utama. Tetapi sistem seperti itu tidak sesuai dengan standar, karena Anda tidak dapat mengandalkan nilai init dari variabel global / statis.
sumber
"Program" Anda hanya mengembalikan nilai dari variabel global. Yang lainnya adalah kode inisialisasi. Dengan demikian, standar berlaku - Anda hanya memiliki program yang sangat sepele dan inisialisasi yang lebih kompleks.
sumber
main () adalah fungsi pengguna yang disebut oleh perpustakaan runtime C.
lihat juga: Menghindari utama (titik masuk) dalam program C.
sumber
Sepertinya semantik bahasa Inggris berdalih. OP merujuk pada blok kode-nya terlebih dahulu sebagai "kode" dan kemudian sebagai "program." Pengguna menulis kode, dan kemudian kompiler menulis program.
sumber
main dipanggil setelah menginisialisasi semua variabel global.
Yang tidak ditentukan oleh standar adalah urutan inisialisasi semua variabel global semua modul dan pustaka yang terhubung secara statis.
sumber
Ya, utama adalah "titik masuk" dari setiap program C ++, kecuali ekstensi spesifik implementasi. Meski begitu, beberapa hal terjadi sebelum main, terutama inisialisasi global seperti untuk main_ret.
sumber