C
Huruf "x" hilang dalam file. Sebuah program ditulis untuk menemukannya:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE* fp = fopen("desert_file", "r");
char letter;
char missing_letter = argv[1][0];
int found = 0;
printf("Searching file for missing letter %c...\n", missing_letter);
while( (letter = fgetc(fp)) != EOF ) {
if (letter == missing_letter) found = 1;
}
printf("Whole file searched.\n");
fclose(fp);
if (found) {
printf("Hurray, letter lost in the file is finally found!\n");
} else {
printf("Haven't found missing letter...\n");
}
}
Itu dikompilasi dan dijalankan dan akhirnya berteriak:
Hurray, letter lost in the file is finally found!
Selama bertahun-tahun surat telah diselamatkan dengan cara ini sampai orang baru datang dan mengoptimalkan kode. Dia akrab dengan tipe data dan tahu bahwa lebih baik menggunakan unsigned daripada menandatangani untuk nilai-nilai non-negatif karena memiliki rentang yang lebih luas dan memberikan perlindungan terhadap luapan. Jadi dia mengubah int menjadi unsigned int . Dia juga tahu ascii cukup baik untuk mengetahui bahwa mereka selalu memiliki nilai non-negatif. Jadi dia juga mengubah char menjadi char yang tidak ditandatangani . Dia menyusun kode dan pulang dengan bangga atas pekerjaan bagus yang dia lakukan. Programnya terlihat seperti ini:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE* fp = fopen("desert_file", "r");
unsigned char letter;
unsigned char missing_letter = argv[1][0];
unsigned int found = 0;
printf("Searching file for missing letter %c...\n", missing_letter);
while( (letter = fgetc(fp)) != EOF ) {
if (letter == missing_letter) found = 1;
}
printf("Whole file searched.\n");
fclose(fp);
if (found) {
printf("Hurray, letter lost in the file is finally found!\n");
} else {
printf("Haven't found missing letter...\n");
}
}
Dia kembali ke malapetaka pada hari berikutnya. Huruf "a" hilang dan meskipun seharusnya berada di "desert_file" yang berisi "abc", program tersebut mencarinya selamanya hanya untuk mencetak:
Searching file for missing letter a...
Mereka memecat orang itu dan kembali ke versi sebelumnya mengingat bahwa orang tidak boleh mengoptimalkan tipe data dalam kode kerja.
Tapi pelajaran apa yang seharusnya mereka pelajari di sini?
Pertama-tama, jika Anda melihat tabel ascii Anda akan melihat bahwa tidak ada EOF. Itu karena EOF bukan karakter tetapi nilai khusus yang dikembalikan dari fgetc (), yang dapat mengembalikan karakter diperluas ke int atau -1 yang menunjukkan akhir file.
Selama kita menggunakan char yang ditandatangani semuanya berfungsi dengan baik - char yang sama dengan 50 diperpanjang oleh fgetc () menjadi int sama dengan 50 juga. Kemudian kita mengubahnya kembali menjadi char dan masih memiliki 50. Hal yang sama terjadi untuk -1 atau output lain yang berasal dari fgetc ().
Tapi lihat apa yang terjadi ketika kita menggunakan char yang tidak ditandatangani. Kami mulai dengan char di fgetc () memperluasnya ke int dan kemudian ingin memiliki char yang tidak ditandatangani. Satu-satunya masalah adalah bahwa kita tidak dapat menyimpan -1 di char yang tidak ditandatangani. Program menyimpannya sebagai 255 yang tidak lagi sama dengan EOF.
Jika Anda melihat bagian 3.1.2.
Peringatan
salinan dokumentasi ANSI C Anda akan mengetahui bahwa apakah char ditandatangani atau tidak, semata-mata tergantung pada implementasi. Jadi orang itu mungkin tidak boleh dipecat karena dia menemukan bug yang sangat rumit bersembunyi di kode. Itu bisa keluar ketika mengubah kompiler atau pindah ke arsitektur yang berbeda. Saya ingin tahu siapa yang akan dipecat jika bug keluar dalam kasus seperti itu;)
PS. Program dibangun di sekitar bug yang disebutkan dalam Bahasa Majelis PC oleh Paul A. Carter