Mengapa bahasa pengaturcaraan C tetap berlaku

Tidak ada teknologi yang bertahan selama 50 tahun melainkan jika ia menjalankan tugasnya dengan lebih baik daripada yang lain — terutamanya teknologi komputer. Bahasa pengaturcaraan C telah hidup dan ditendang sejak tahun 1972, dan masih berfungsi sebagai salah satu asas asas dunia yang ditentukan perisian kami.

Tetapi kadang-kadang sebuah teknologi masih ada kerana orang-orang belum dapat menggantikannya. Selama beberapa dekad terakhir, puluhan bahasa lain telah muncul - beberapa yang dirancang secara eksplisit untuk menantang dominasi C, beberapa menjatuhkan C dari sisi sebagai produk sampingan popularitas mereka.

Tidak sukar untuk membantah bahawa C perlu diganti. Penyelidikan bahasa pengaturcaraan dan praktik pengembangan perisian menunjukkan bagaimana terdapat cara yang lebih baik untuk melakukan sesuatu daripada cara C. Tetapi C tetap sama, dengan puluhan tahun penyelidikan dan pengembangan di belakangnya. Beberapa bahasa lain dapat mengalahkannya untuk prestasi, keserasian logam telanjang, atau untuk keberadaan. Namun, perlu dilihat bagaimana C bersaing dengan pertandingan bahasa dengan nama besar pada tahun 2018.

C lwn C ++

Secara semula jadi, C dibandingkan paling umum dengan C ++, bahasa yang — seperti namanya sendiri — diciptakan sebagai perpanjangan C. Perbezaan antara C ++ dan C dapat dicirikan sebagai luas, atau  berlebihan , bergantung pada siapa Anda bertanya.

Walaupun masih seperti C dalam sintaks dan pendekatannya, C ++ memberikan banyak ciri berguna yang sebenarnya tidak tersedia secara asli di C: ruang nama, templat, pengecualian, pengurusan memori automatik, dan sebagainya. Projek yang menuntut prestasi peringkat atas - pangkalan data, sistem pembelajaran mesin - sering ditulis dalam C ++ menggunakan ciri-ciri tersebut untuk mengatasi setiap penurunan prestasi dari sistem.

Selanjutnya, C ++ terus berkembang jauh lebih agresif daripada C. C ++ 20 yang akan datang membawa lebih banyak lagi jadual termasuk modul, coroutine, perpustakaan penyegerakan, dan konsep, yang menjadikan templat lebih mudah digunakan. Semakan terbaru pada standard C menambah sedikit dan memberi tumpuan untuk mengekalkan keserasian ke belakang.

Masalahnya, semua kelebihan dalam C ++ juga dapat berfungsi sebagai tolak. Yang besar. Semakin banyak ciri C ++ yang anda gunakan, semakin kompleks anda memperkenalkan dan semakin sukar untuk menjinakkan hasilnya. Pembangun yang mengehadkan diri pada subset C ++ dapat mengelakkan banyak masalah dan keburukannya. Tetapi sebilangan kedai mahu melindungi dari kerumitan C ++ bersama-sama. Berpegang teguh dengan C memaksa pemaju untuk membatasi diri pada subset tersebut. Pasukan pengembangan kernel Linux, misalnya, menghindari C ++.

Memilih C di atas C ++ adalah cara untuk anda - dan mana-mana pembangun yang menjaga kod selepas anda - untuk mengelakkan diri dari terjerat dengan kelebihan C ++, dengan menerapkan minimalisme yang dipaksakan. Sudah tentu, C ++ mempunyai sekumpulan ciri tahap tinggi yang kaya dengan alasan yang baik. Tetapi jika minimalisme lebih sesuai untuk projek semasa dan masa depan - dan pasukan projek - maka C lebih masuk akal.

C lwn Jawa

Setelah beberapa dekad, Java tetap menjadi pokok pengembangan perisian perusahaan - dan pokok pengembangan secara umum. Sebilangan besar projek perisian perusahaan yang paling penting ditulis di Jawa - termasuk sebagian besar proyek Apache Software Foundation - dan Java tetap menjadi bahasa yang layak untuk mengembangkan projek baru dengan keperluan kelas perusahaan.

Sintaks Java meminjam banyak dari C dan C ++. Tidak seperti C, Java tidak secara default menyusun kod asli. Sebaliknya, lingkungan Java runtime, JVM, JIT (just-in-time) menyusun kod Java untuk dijalankan di lingkungan sasaran. Dalam keadaan yang tepat, kod Java JITted dapat mendekati atau bahkan melebihi prestasi C.

Falsafah "tulis sekali, jalankan ke mana saja" di belakang Java juga memungkinkan program Java berjalan dengan sedikit perubahan untuk arsitektur sasaran. Sebaliknya, walaupun C telah dipindahkan ke banyak arsitektur, program C yang diberikan mungkin masih memerlukan penyesuaian untuk berjalan dengan baik, katakanlah, Windows berbanding Linux.

Kombinasi mudah alih dan prestasi yang kuat ini, bersama dengan ekosistem perpustakaan dan kerangka kerja perisian yang besar, menjadikan Java sebagai bahasa dan waktu berjalan untuk membina aplikasi perusahaan.

Di mana Java kekurangan C adalah daerah di mana Java tidak pernah dimaksudkan untuk bersaing: berjalan dekat dengan logam, atau bekerja langsung dengan perkakasan. Kod C disusun menjadi kod mesin, yang dijalankan secara langsung oleh proses. Java disusun menjadi bytecode, yang merupakan kod perantaraan yang kemudian ditukarkan oleh jurubahasa JVM menjadi kod mesin. Lebih jauh lagi, walaupun manajemen memori otomatis Java adalah berkat dalam banyak keadaan, C lebih cocok untuk program yang harus menggunakan sumber daya memori yang terbatas secara optimum.

Yang mengatakan, ada beberapa daerah di mana Java dapat mendekati C dari segi kecepatan. Mesin JIT JVM mengoptimumkan rutin pada waktu berjalan berdasarkan tingkah laku program, yang memungkinkan untuk banyak kelas pengoptimuman yang tidak mungkin dilakukan dengan penyusun C. yang lebih awal. Dan semasa runtime Java mengotomatisasi pengurusan memori, beberapa aplikasi yang lebih baru berfungsi untuk mengatasi itu. Sebagai contoh, Apache Spark mengoptimumkan pemprosesan dalam memori sebahagiannya dengan menggunakan kod pengurusan memori tersuai yang mengelak dari JVM.

C lwn C # dan .Net

Hampir dua dekad setelah diperkenalkan, C # dan .Net Framework tetap menjadi bahagian utama dunia perisian perusahaan. Telah dikatakan bahwa C # dan .Net adalah tindak balas Microsoft terhadap Java - sistem penyusun kod yang dikendalikan dan runtime universal - dan begitu banyak perbandingan antara C dan Java juga bertahan untuk C dan C # /. Net.

Seperti Java (dan sampai tahap tertentu Python), .Net menawarkan mudah alih di pelbagai platform dan ekosistem perisian bersepadu yang luas. Ini bukan kelebihan kecil memandangkan berapa banyak pembangunan yang berorientasikan perusahaan berlaku di dunia .Net. Apabila anda mengembangkan program dalam C #, atau bahasa .Net yang lain, anda dapat menggunakan sejenis alat dan perpustakaan yang ditulis untuk waktu operasi .Net. 

Kelebihan lain seperti Java .NET adalah pengoptimuman JIT. Program C # dan .Net dapat dikompilasi lebih awal dari waktu C, tetapi program ini hanya tepat pada waktunya disusun oleh .Net runtime dan dioptimumkan dengan maklumat runtime. Penyusunan JIT membolehkan semua jenis pengoptimuman di tempat untuk program .Net yang sedang berjalan dan tidak dapat dijalankan di C.

Seperti C, C # dan .Net menyediakan pelbagai mekanisme untuk mengakses memori secara langsung. Tumpukan, timbunan, dan memori sistem yang tidak dikendalikan semuanya dapat diakses melalui .Net API dan objek. Dan pembangun boleh menggunakan unsafemod di. Net untuk mencapai prestasi yang lebih hebat.

Tidak ada yang percuma. Objek dan objek yang diuruskan unsafetidak dapat ditukar dengan sewenang-wenangnya, dan pengumpulan barang di antara mereka dikenakan biaya prestasi. Oleh itu, memaksimumkan prestasi aplikasi .Net bermaksud menjaga pergerakan antara objek yang diuruskan dan yang tidak dikendalikan dengan minimum.

Apabila anda tidak mampu membayar denda untuk memori yang diuruskan berbanding yang tidak dikendalikan, atau ketika waktu larian .Net adalah pilihan yang buruk untuk persekitaran sasaran (misalnya, ruang kernel) atau mungkin tidak tersedia sama sekali, maka C adalah apa yang anda memerlukan. Dan tidak seperti C # dan .Net, C membuka akses memori langsung secara lalai. 

C vs. Go

Sintaks Go berhutang banyak pada C — pendakap keriting sebagai pembatas, pernyataan yang diakhiri dengan titik koma, dan sebagainya. Pembangun yang mahir dalam C biasanya dapat langsung masuk ke Go tanpa banyak kesulitan, bahkan dengan mempertimbangkan fitur Go baru seperti ruang nama dan pengurusan pakej.

Kod yang boleh dibaca adalah salah satu tujuan reka bentuk panduan Go: Memudahkan pembangun untuk mempercepat dengan sebarang projek Go dan menjadi mahir dengan pangkalan kode dalam jangka pendek. Pangkalan data C sukar dilakukan, kerana mereka cenderung berubah menjadi sarang makro tikus dan #ifdefspesifik untuk projek dan pasukan tertentu. Sintaks Go, dan alat pemformatan kod dan pengurusan projeknya, bertujuan untuk mengatasi masalah institusi seperti itu.

Go juga mempunyai ciri tambahan seperti goroutine dan saluran, alat peringkat bahasa untuk menangani serentak dan penghantaran mesej antara komponen. C memerlukan barang seperti itu digulung tangan atau dibekalkan oleh perpustakaan luaran, tetapi Go menyediakannya langsung dari luar kotak, menjadikannya lebih mudah untuk membina perisian yang memerlukannya.

Di mana Go paling berbeza dengan C di bawah tudung adalah dalam pengurusan memori. Objek Go diuruskan secara automatik dan sampah dikumpulkan secara lalai. Untuk kebanyakan pekerjaan pengaturcaraan, ini sangat sesuai. Tetapi itu juga bermaksud bahawa setiap program yang memerlukan pengendalian memori yang pasti akan lebih sukar untuk ditulis.

Go termasuk unsafepakej untuk mengelakkan beberapa keselamatan pengendalian jenis Go, seperti membaca dan menulis memori sewenang-wenang dengan Pointerjenis. Tetapi unsafedisertakan dengan peringatan bahawa program yang ditulis dengannya "mungkin tidak mudah alih dan tidak dilindungi oleh panduan keserasian Go 1."

Go sangat sesuai untuk membina program seperti utiliti baris perintah dan perkhidmatan rangkaian, kerana mereka jarang memerlukan manipulasi yang baik. Tetapi pemacu peranti tahap rendah, komponen sistem operasi ruang kernel, dan tugas-tugas lain yang menuntut kawalan yang tepat terhadap susun atur dan pengurusan memori paling baik dibuat di C.

C vs Karat

Dalam beberapa cara, Rust adalah tindak balas terhadap teka-teki pengurusan memori yang dibuat oleh C dan C ++, dan juga banyak kekurangan bahasa-bahasa ini. Rust menyusun kod mesin asli, jadi dianggap setara dengan C sejauh prestasi. Keselamatan memori secara lalai, bagaimanapun, adalah titik penjualan utama Rust.

Peraturan sintaks dan penyusunan Rust membantu pemaju mengelakkan kesalahan pengurusan memori biasa. Sekiranya program mempunyai masalah pengurusan memori yang melintasi sintaks Rust, ia tidak akan disusun. Pendatang baru dalam bahasa, terutama dari bahasa seperti C yang menyediakan banyak ruang untuk bug seperti itu, menghabiskan fasa pertama pendidikan Rust mereka belajar bagaimana untuk menenangkan penyusun. Tetapi penyokong Rust berpendapat bahawa kesakitan jangka pendek ini mempunyai hasil jangka panjang: kod yang lebih selamat yang tidak mengorbankan kepantasan.

Karat juga bertambah baik pada C dengan perkakasnya. Pengurusan projek dan komponen adalah sebahagian dari rantai alat yang dibekalkan dengan Rust secara lalai, sama seperti dengan Go. Terdapat cara lalai dan disyorkan untuk menguruskan pakej, mengatur folder projek, dan menangani banyak perkara lain yang ada di C yang terbaik secara ad-hoc, dengan setiap projek dan pasukan mengendalikannya secara berbeza.

Namun, apa yang disebut sebagai kelebihan dalam Rust mungkin tidak menyerupai pemaju C. Ciri keselamatan masa kompilasi Rust tidak dapat dilumpuhkan, bahkan program Rust yang paling remeh mesti sesuai dengan ketahanan keselamatan memori Rust. C mungkin kurang selamat secara lalai, tetapi jauh lebih fleksibel dan pemaaf apabila perlu.

Kelemahan lain yang mungkin adalah ukuran bahasa Rust. C mempunyai sedikit ciri, walaupun mengambil kira pustaka standard. Set ciri Rust sangat luas dan terus berkembang. Seperti C ++, set fitur Rust yang lebih besar bermaksud lebih banyak kuasa, tetapi juga lebih kompleks. C adalah bahasa yang lebih kecil, tetapi lebih mudah dimodelkan secara mental, jadi mungkin lebih sesuai untuk projek di mana Rust akan berlebihan.

C lwn Python

Hari-hari ini, setiap kali perbincangan mengenai pembangunan perisian, Python selalu memasuki perbualan. Lagipun, Python adalah "bahasa kedua terbaik untuk semuanya," dan tidak diragukan lagi salah satu yang paling serba boleh, dengan ribuan perpustakaan pihak ketiga tersedia.

Apa yang ditekankan oleh Python, dan di mana perbezaannya paling banyak dari C, adalah memilih kelajuan pengembangan berbanding kelajuan pelaksanaan. Program yang mungkin memerlukan satu jam untuk disatukan dalam bahasa lain - seperti C - mungkin akan dihimpun di Python dalam beberapa minit. Di sisi lain, program itu mungkin memerlukan beberapa saat untuk dijalankan di C, tetapi satu minit untuk dijalankan di Python. (Aturan praktik yang baik: Program Python pada umumnya menjalankan urutan magnitud lebih lambat daripada rakan C mereka.) Tetapi untuk banyak pekerjaan pada perkakasan moden, Python cukup pantas, dan itu merupakan kunci penyerapannya.

Perbezaan utama lain adalah pengurusan memori. Program Python dikendalikan sepenuhnya oleh memori runtime Python, jadi pembangun tidak perlu risau tentang peruntukan dan pembebasan memori. Tetapi di sini sekali lagi, kemudahan pemaju datang dengan kos prestasi masa operasi. Menulis program C memerlukan perhatian yang mendalam terhadap pengurusan memori, tetapi program yang dihasilkan sering menjadi standard emas untuk kelajuan mesin tulen.

Namun, di bawah kulit, Python dan C mempunyai hubungan yang mendalam: rujukan Python runtime ditulis dalam C. Ini membolehkan program Python membungkus perpustakaan yang ditulis dalam C dan C ++. Bahagian penting dari ekosistem Python perpustakaan pihak ketiga, seperti untuk pembelajaran mesin, mempunyai kod C pada intinya.

Sekiranya kepantasan pembangunan lebih penting daripada kepantasan pelaksanaan, dan jika sebahagian besar program yang berfungsi dapat diasingkan menjadi komponen yang berdiri sendiri (berbanding penyebaran ke seluruh kod), baik Python murni atau campuran perpustakaan Python dan C membuat pilihan yang lebih baik daripada C sahaja. Jika tidak, C tetap memerintah.