Off pertama, seperti yang disinggung di beberapa jawaban yang lain tetapi tidak, pikiran saya, terbilang cukup jelas: Ini tidak bekerja untuk memberikan sebuah integer dalam kebanyakan konteks di mana fungsi perpustakaan membutuhkan double
atau float
argumen. Kompilator secara otomatis akan memasukkan konversi. Misalnya, sqrt(0)
terdefinisi dengan baik dan akan berperilaku persis seperti sqrt((double)0)
, dan hal yang sama berlaku untuk ekspresi tipe bilangan bulat lainnya yang digunakan di sana.
printf
berbeda. Ini berbeda karena membutuhkan sejumlah variabel argumen. Prototipe fungsinya adalah
extern int printf(const char *fmt, ...);
Karena itu, saat Anda menulis
printf(message, 0);
kompilator tidak mempunyai informasi apapun tentang tipe apa yang printf
mengharapkan argumen kedua itu. Ini hanya memiliki tipe ekspresi argumen, yaitu int
, untuk dilalui. Oleh karena itu, tidak seperti kebanyakan fungsi perpustakaan, Anda, programmer, untuk memastikan daftar argumen sesuai dengan harapan format string.
(Kompiler modern dapat melihat ke dalam string format dan memberi tahu Anda bahwa Anda memiliki jenis ketidakcocokan, tetapi mereka tidak akan mulai memasukkan konversi untuk mencapai apa yang Anda maksud, karena lebih baik kode Anda harus rusak sekarang, ketika Anda akan melihatnya , dibandingkan beberapa tahun kemudian ketika dibangun kembali dengan kompilator yang kurang membantu.)
Sekarang, separuh pertanyaan lainnya adalah: Mengingat bahwa (int) 0 dan (float) 0.0, pada kebanyakan sistem modern, keduanya direpresentasikan sebagai 32 bit yang semuanya nol, mengapa tetap tidak berfungsi, secara tidak sengaja? Standar C hanya mengatakan "ini tidak diharuskan untuk bekerja, Anda sendiri", tapi izinkan saya menjelaskan dua alasan paling umum mengapa ini tidak akan berhasil; yang mungkin akan membantu Anda memahami mengapa hal itu tidak diwajibkan.
Pertama, karena alasan historis, ketika Anda melewati float
melalui daftar argumen variabel itu akan dipromosikan untuk double
, yang, pada kebanyakan sistem modern, adalah 64 bit lebar. Jadi printf("%f", 0)
hanya mengirimkan 32 bit nol ke callee mengharapkan 64 dari mereka.
Kedua, alasan yang sama penting adalah bahwa argumen fungsi floating-point dapat dilewatkan di berbagai tempat dari argumen integer. Misalnya, sebagian besar CPU memiliki file register terpisah untuk bilangan bulat dan nilai floating-point, jadi mungkin ada aturan bahwa argumen 0 hingga 4 masuk dalam register r0 hingga r4 jika bilangan bulat, tetapi f0 hingga f4 jika berupa floating-point. Jadi printf("%f", 0)
lihat di register f1 untuk nol itu, tapi tidak ada sama sekali.
printf
mengharapkandouble
, dan Anda memberikannyaint
.float
danint
mungkin berukuran sama di komputer Anda, tetapi0.0f
sebenarnya diubah menjadidouble
ketika didorong ke daftar argumen variadic (danprintf
mengharapkan itu). Singkatnya, Anda tidak memenuhi akhir dari penawaranprintf
berdasarkan spesifikasi yang Anda gunakan dan argumen yang Anda berikan.