“Int main (vooid)”? Bagaimana cara kerjanya?

135

Saya baru-baru mengetikkan program uji C kecil dan, dalam proses, saya membuat kesalahan ejaan dalam fungsi utama dengan sengaja menggunakan vooidbukan void.

Namun itu masih berhasil.

Mengurangi itu menjadi versi lengkap terkecil, saya berakhir dengan:

int main (vooid) {
    return 42;
}

Ini memang compile ( gcc -Wall -o myprog myprog.c) dan, ketika dijalankan, mengembalikan 42.

Bagaimana sebenarnya kode yang valid ini?


Ini transkrip yang dipotong dan ditempel dari bashcangkang saya untuk menunjukkan apa yang saya lakukan:

pax$ cat qq.c
int main (vooid) {
    return 42;
}

pax$ rm qq ; gcc -Wall -o qq qq.c ; ./qq

pax$ echo $?
42
paxdiablo
sumber
Dengan mendefinisikan main dengan satu intparameter, Anda memanggil Undefined Behavior . Apa pun bisa terjadi :)
pmg
9
Sebenarnya saya kurang yakin dengan UB, @pmg. ISO secara khusus memungkinkan kemungkinan lain dari maindua standar kanonik. Untuk portabilitas, Anda harus menggunakan salah satu dari keduanya tetapi menurut saya UB tidak berlaku di sini.
paxdiablo
Hmm: dalam lingkungan yang dihosting mainharus memiliki salah satu dari 2 bentuk kanonis (2.1.2.2). Tapi Anda benar @pax, dalam lingkungan yang berdiri sendiri, pengenal mainsama sekali tidak istimewa: jika digunakan sebagai fungsi , pengenal dapat berupa jenis apa pun dan memiliki sejumlah parameter jenis apa pun.
pmg
2
Di C99, berdiri bebas adalah implementasi total yang ditentukan. Untuk dihosting, bagian 5.1.2.2.1 menyatakan di bagian akhir "atau dalam beberapa cara lain yang ditentukan implementasi" sehingga memerlukan, minimal, dua bentuk kanonik tetapi dapat memiliki yang lain juga (ini akan memungkinkan UNIXy int main (int argc, char *argv[], char *envp[]);untuk menyesuaikan ).
paxdiablo

Jawaban:

220

Ini hanya menggunakan sintaks deklarasi fungsi "gaya lama"; Anda secara implisit mendeklarasikan intparameter yang dipanggil vooid.

Oliver Charlesworth
sumber
2
Sepertinya ini masalahnya. Jika Anda menambahkan "vooid = 42; return vooid;" ke utama, Anda juga mendapatkan nilai pengembalian 42.
Jeff Ames
43
Aargghh, kamu benar. Jika saya menambahkan -std=c99, saya mengerti qq.c:1: warning: type of 'vooid' defaults to 'int'.
paxdiablo
70

Ini kode yang valid, karena myprog.c berisi:

int main (vooid) // vooid is of type int, allowed, and an alias for argc
{     
  return 42; // The answer to the Ultimate Question
} 

vooidberisi satu ditambah jumlah argumen yang diteruskan (yaitu, argc). Jadi, pada dasarnya semua yang Anda lakukan adalah mengganti nama argcmenjadi vooid.

Michael Goldshteyn
sumber
11
Jika Anda melakukan "return vooid;" sebaliknya, ini memang memberikan 1 + num. dari args.
Jeff Ames
6
@Jeff, nama program dihitung sebagai arguement, maka +1
Martin Beckett
23

Di C, tipe default untuk argumen fungsi adalah int. Jadi, program Anda memperlakukan kata tersebut vooidsebagai int main(int vooid), yang merupakan kode yang benar-benar valid.

Chinmay Kanchi
sumber
20

Itu hanya gcc -std=c89 -Wall -o qq qq.cdan gcc -std=gnu89 -Wall -o qq qq.ctidak mengeluarkan peringatan. Semua standar lainnya mengeluarkan peringatan tentang tipe implisit intuntuk vooid.

int main(chart)berperilaku seperti itu int main (vooid).

return vooid; mengembalikan jumlah argumen baris perintah.

Saya menguji dengan gcc 4.4.5 pada sistem pengujian Debian.

vpit3833
sumber