Pertama, saya perhatikan bahwa meskipun saya hanya menyebutkan "C" di sini, hal yang sama juga berlaku untuk C ++.
Komentar yang menyebutkan Godel sebagian (tetapi hanya sebagian) tepat sasaran.
Ketika Anda sampai ke sana, perilaku yang tidak terdefinisi dalam standar C sebagian besar hanya menunjukkan batas antara apa yang berusaha didefinisikan oleh standar, dan apa yang tidak.
Teorema Godel (ada dua) pada dasarnya mengatakan bahwa mustahil untuk mendefinisikan sistem matematika yang dapat dibuktikan (dengan aturannya sendiri) menjadi lengkap dan konsisten. Anda dapat membuat aturan Anda sehingga bisa lengkap (kasus yang dia tangani adalah aturan "normal" untuk bilangan asli), atau Anda dapat membuatnya membuktikan konsistensi, tetapi Anda tidak dapat memiliki keduanya.
Dalam hal sesuatu seperti C, yang tidak berlaku secara langsung - sebagian besar, "provabilitas" kelengkapan atau konsistensi sistem bukanlah prioritas tinggi bagi sebagian besar perancang bahasa. Pada saat yang sama, ya, mereka mungkin dipengaruhi (setidaknya sampai taraf tertentu) dengan mengetahui bahwa mustahil untuk mendefinisikan sistem "sempurna" - sistem yang terbukti lengkap dan konsisten. Mengetahui bahwa hal seperti itu tidak mungkin mungkin membuatnya sedikit lebih mudah untuk mundur, bernapas sedikit, dan memutuskan batasan-batasan apa yang akan mereka coba definisikan.
Dengan risiko (lagi-lagi) dituduh sombong, saya akan menganggap standar C sebagai yang diatur (sebagian) oleh dua ide dasar:
- Bahasa tersebut harus mendukung berbagai perangkat keras seluas mungkin (idealnya, semua perangkat keras "waras" hingga batas bawah yang wajar).
- Bahasa harus mendukung penulisan berbagai perangkat lunak seluas mungkin untuk lingkungan yang diberikan.
Yang pertama berarti bahwa jika seseorang mendefinisikan CPU baru, harus dimungkinkan untuk memberikan implementasi C yang baik, solid, dapat digunakan untuk itu, selama desain jatuh setidaknya cukup dekat dengan beberapa pedoman sederhana - pada dasarnya, jika mengikuti sesuatu pada urutan umum model Von Neumann, dan menyediakan setidaknya sejumlah memori minimum yang masuk akal, yang seharusnya cukup untuk memungkinkan implementasi C. Untuk implementasi "dihosting" (yang dijalankan pada OS) Anda perlu mendukung beberapa gagasan yang sesuai dengan file, dan memiliki set karakter dengan set karakter minimum tertentu (diperlukan 91).
Yang kedua berarti harus mungkin untuk menulis kode yang memanipulasi perangkat keras secara langsung, sehingga Anda dapat menulis hal-hal seperti boot loader, sistem operasi, perangkat lunak tertanam yang berjalan tanpa OS, dll. Pada akhirnya ada beberapa batasan dalam hal ini, sehingga hampir semua sistem praktis operasi, boot loader, dll, mungkin mengandung setidaknya sedikit sedikit kode yang ditulis dalam bahasa assembly. Demikian juga, bahkan sistem tertanam kecil kemungkinan akan menyertakan setidaknya semacam rutin perpustakaan pra-tertulis untuk memberikan akses ke perangkat pada sistem host. Meskipun batas yang tepat sulit untuk didefinisikan, tujuannya adalah bahwa ketergantungan pada kode tersebut harus dijaga agar tetap minimum.
Perilaku tidak terdefinisi dalam bahasa sebagian besar didorong oleh niat untuk bahasa untuk mendukung kemampuan ini. Misalnya, bahasa ini memungkinkan Anda untuk mengkonversi bilangan bulat sembarang menjadi penunjuk, dan mengakses apa pun yang terjadi di alamat itu. Standar tidak berusaha mengatakan apa yang akan terjadi ketika Anda melakukannya (misalnya, bahkan membaca dari beberapa alamat dapat memiliki pengaruh yang terlihat secara eksternal). Pada saat yang sama, tidak ada upaya mencegah Anda dari melakukan hal-hal seperti itu, karena Anda perlu untuk beberapa jenis perangkat lunak yang Anda seharusnya dapat menulis dalam C.
Ada beberapa perilaku tidak terdefinisi yang didorong oleh elemen desain lain juga. Misalnya, satu maksud C lainnya adalah untuk mendukung kompilasi terpisah. Ini berarti (misalnya) bahwa ini dimaksudkan agar Anda dapat "menautkan" potongan-potongan menggunakan tautan yang kira-kira mengikuti apa yang sebagian besar dari kita lihat sebagai model tautan biasa. Secara khusus, harus dimungkinkan untuk menggabungkan modul yang dikompilasi secara terpisah ke dalam program yang lengkap tanpa sepengetahuan semantik bahasa.
Ada tipe lain dari perilaku tidak terdefinisi (yang jauh lebih umum di C ++ daripada C), yang hadir hanya karena batasan pada teknologi kompiler - hal-hal yang pada dasarnya kita tahu adalah kesalahan, dan mungkin ingin kompiler mendiagnosis sebagai kesalahan, tetapi mengingat batas saat ini pada teknologi kompiler, diragukan bahwa mereka dapat didiagnosis dalam semua keadaan. Banyak dari ini didorong oleh persyaratan lain, seperti untuk kompilasi terpisah, sehingga sebagian besar masalah keseimbangan persyaratan yang saling bertentangan, dalam hal ini panitia umumnya memilih untuk mendukung kemampuan yang lebih besar, bahkan jika itu berarti kurangnya mendiagnosis beberapa masalah yang mungkin terjadi, daripada membatasi kemampuan untuk memastikan bahwa semua masalah yang mungkin didiagnosis.
Perbedaan-perbedaan ini dalam niat mendorong sebagian besar perbedaan antara C dan sesuatu seperti Java atau sistem berbasis CLI Microsoft. Yang terakhir ini secara eksplisit terbatas untuk bekerja dengan perangkat keras yang jauh lebih terbatas, atau membutuhkan perangkat lunak untuk meniru perangkat keras yang lebih spesifik yang mereka targetkan. Mereka juga secara khusus berniat untuk mencegah manipulasi langsung perangkat keras, alih-alih mengharuskan Anda menggunakan sesuatu seperti JNI atau P / Invoke (dan kode yang ditulis dalam sesuatu seperti C) untuk melakukan upaya semacam itu.
Kembali ke teorema Godel sejenak, kita dapat menggambar sesuatu yang paralel: Java dan CLI telah memilih alternatif "konsisten secara internal", sementara C telah memilih alternatif "lengkap". Tentu saja, ini analogi yang sangat kasar - saya ragu ada orang yang mencoba bukti formal baik konsistensi internal atau kelengkapan dalam kedua kasus. Meskipun demikian, gagasan umum tidak cukup cocok dengan pilihan yang telah mereka ambil.