Saya membaca di buku Bahasa Pemrograman C karya Dennis Ritchie yang int
harus digunakan untuk variabel untuk menahan EOF - untuk membuatnya cukup besar sehingga dapat menyimpan nilai EOF - tidak char
. Tetapi kode berikut berfungsi dengan baik:
#include<stdio.h>
main() {
char c;
c=getchar();
while(c!=EOF) {
putchar(c);
c=getchar();
}
}
Ketika tidak ada lagi input, getchar
kembalikan EOF. Dan dalam program di atas, variabel c
, dengan tipe char, dapat menahannya dengan sukses.
Mengapa ini bekerja? Sesuai penjelasan dalam buku yang disebutkan di atas, kode tidak boleh bekerja.
0xff
. Menyimpan hasilgetchar()
dalamint
memecahkan masalah itu. Pertanyaan Anda pada dasarnya sama dengan pertanyaan 12.1 di FAQ comp.lang.c , yang merupakan sumber yang bagus. (Juga,main()
seharusnya begituint main(void)
, dan tidak ada ruginya menambahkanreturn 0;
sebelum penutupan}
.)Jawaban:
Kode Anda tampaknya berfungsi, karena konversi tipe implisit terjadi secara tidak sengaja untuk melakukan hal yang benar.
getchar()
mengembalikan nilaiint
dengan nilai yang cocok dengan rentangunsigned char
atau adalahEOF
(yang harus negatif, biasanya -1). Perhatikan bahwaEOF
itu sendiri bukan karakter, tetapi sinyal bahwa tidak ada lagi karakter yang tersedia.Saat menyimpan hasil dari
getchar()
dalamc
, ada dua kemungkinan. Baik tipechar
dapat mewakili nilai, dalam hal ini adalah nilaic
. Atau tipechar
tidak dapat mewakili nilai. Dalam hal ini, tidak ditentukan apa yang akan terjadi. Prosesor Intel hanya memotong bit-bit tinggi yang tidak cocok dengan tipe baru (secara efektif mengurangi nilai modulo 256 untukchar
), tetapi Anda tidak boleh bergantung pada itu.Langkah berikutnya adalah untuk membandingkan
c
denganEOF
. SebagaiEOF
adalahint
,c
akan dikonversi keint
juga, melestarikan nilai yang disimpan dalamc
. Jikac
bisa menyimpan nilaiEOF
, maka perbandingan akan berhasil, tetapi jika tidakc
bisa menyimpan nilai, maka perbandingan akan gagal, karena telah terjadi kehilangan informasi yang tidak dapat dipulihkan saat mengonversi untuk mengetik .EOF
char
Tampaknya kompiler Anda memilih untuk membuat
char
jenis ditandatangani dan nilaiEOF
cukup kecil untuk masukchar
. Jikachar
tidak ditandatangani (atau jika Anda telah menggunakanunsigned char
), pengujian Anda akan gagal, karenaunsigned char
tidak dapat menyimpan nilaiEOF
.Perhatikan juga bahwa ada masalah kedua dengan kode Anda. Karena
EOF
bukan karakter itu sendiri, tetapi Anda memaksanya menjadi suatuchar
tipe, sangat mungkin ada karakter di luar sana yang disalahartikan sebagaiEOF
dan untuk separuh karakter yang mungkin tidak ditentukan apakah karakter tersebut akan diproses dengan benar.sumber
char
nilai di luar rentangCHAR_MIN
..CHAR_MAX
akan diperlukan untuk menghasilkan nilai yang ditentukan-implementasi, menghasilkan pola bit yang didefinisikan oleh implementasi sebagai representasi trap, atau menaikkan sinyal yang ditentukan implementasi. Dalam kebanyakan kasus, implementasi harus melalui banyak pekerjaan ekstra untuk melakukan apa pun selain pengurangan dua-pelengkap. Jika orang-orang di Komite Standar berlangganan gagasan bahwa penyusun harus didorong untuk menerapkan perilaku yang konsisten dengan kebanyakan penyusun lain dengan tidak adanya alasan untuk melakukan sebaliknya ...(signed char)x
harus dianggap lebih jelas dan sama amannya((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
.) Seperti itu, saya tidak melihat kemungkinan adanya kompiler yang menerapkan perilaku lain yang sesuai dengan standar saat ini; salah satu bahayanya adalah bahwa Standar tersebut dapat diubah untuk menghentikan perilaku demi kepentingan "optimisasi".int i=129; signed char c=i;
adalah salah satu perilaku tersebut. Relatif sedikit prosesor yang memiliki instruksi yangc
setarai
dengan -127 hingga +127 dan akan menghasilkan pemetaan nilai-nilai lain yang konsisteni
pada kisaran -128 hingga +127 yang berbeda dari reduksi dua komplemen, atau. ..