Mengapa orang menggunakan C jika sangat berbahaya?

132

Saya sedang mempertimbangkan untuk belajar C.

Tetapi mengapa orang menggunakan C (atau C ++) jika itu dapat digunakan 'berbahaya'?

Berbahaya, maksud saya dengan pointer dan hal-hal serupa lainnya.

Seperti pertanyaan Stack Overflow. Mengapa fungsi ini begitu berbahaya sehingga tidak boleh digunakan? . Mengapa programmer tidak hanya menggunakan Java atau Python atau bahasa kompilasi lain seperti Visual Basic?

Tristan
sumber
152
Mengapa koki menggunakan pisau, jika mereka bisa digunakan 'berbahaya'?
Oerkelens
78
Dengan Kekuatan Besar Datang Tanggung Jawab Besar.
Pieter B
10
Joe Blow, banyak kepausan?
Matthew James Briggs
4
Karena "Back In The Day" ketika C menjadi Bahasa Pilihan kami diharapkan dapat menangani hal-hal seperti itu, karena kami harus melakukannya. Bahasa yang ditafsirkan atau byte-kode terlalu lambat karena prosesor hari ini jauh lebih lambat. (Hari ini saya dapat membeli PC desktop low-end dengan CPU multi-core 2+ GHz dan memori 4 GB dari Dell seharga $ 279. Anda TIDAK PUNYA IDEA betapa luar biasa hal ini bagi orang seperti saya yang memiliki PC 4 MHz dengan 640 kilobyte memori adalah kebahagiaan ...). Hadapi itu - Hukum Moore menang. Permainan. Lebih!
Bob Jarvis
6
@ Bob Jarvis: Game belum berakhir. Jika Anda berpikir 2 + GHz, PC 4GB - atau dalam hal ini, gugus beberapa ratus 4 GHz PC dengan GPU CUDA terbaru, atau apa pun - cukup cepat, Anda tidak bekerja pada masalah yang cukup sulit :-)
jamesqf

Jawaban:

246
  1. C mendahului banyak bahasa lain yang Anda pikirkan. Banyak hal yang sekarang kita ketahui tentang bagaimana membuat pemrograman "lebih aman" berasal dari pengalaman dengan bahasa seperti C.

  2. Banyak bahasa yang lebih aman yang telah keluar sejak C mengandalkan runtime yang lebih besar, seperangkat fitur yang lebih rumit, dan / atau mesin virtual untuk mencapai tujuan mereka. Akibatnya, C tetap menjadi "penyebut umum terendah" di antara semua bahasa populer / umum.

    • C adalah bahasa yang jauh lebih mudah untuk diimplementasikan karena relatif kecil, dan lebih cenderung berkinerja memadai bahkan di lingkungan terlemah, sehingga banyak sistem tertanam yang perlu mengembangkan kompiler mereka sendiri dan alat-alat lain lebih mungkin untuk dapat menyediakan kompiler fungsional untuk C.

    • Karena C sangat kecil dan sangat sederhana, bahasa pemrograman lain cenderung berkomunikasi satu sama lain menggunakan C-like API. Ini mungkin alasan utama mengapa C tidak akan pernah benar-benar mati, bahkan jika kebanyakan dari kita hanya pernah berinteraksi dengannya melalui pembungkus.

  3. Banyak bahasa "lebih aman" yang mencoba untuk meningkatkan pada C dan C ++ tidak mencoba menjadi "bahasa sistem" yang memberi Anda hampir total kontrol atas penggunaan memori dan perilaku runtime dari program Anda. Meskipun benar bahwa semakin banyak aplikasi saat ini tidak membutuhkan tingkat kontrol itu, akan selalu ada beberapa kasus di mana diperlukan (terutama di dalam mesin virtual dan browser yang menerapkan semua bahasa yang baik dan aman ini untuk kita semua).

    Saat ini, ada beberapa bahasa pemrograman sistem (Rust, Nim, D, ...) yang lebih aman daripada C atau C ++. Mereka memiliki manfaat dari tinjau balik, dan menyadari bahwa sebagian besar waktu, kontrol yang baik seperti itu tidak diperlukan, jadi tawarkan antarmuka yang umumnya aman dengan beberapa kait / mode tidak aman yang dapat digunakan untuk beralih ketika benar-benar diperlukan.

  4. Bahkan di dalam C, kami telah belajar banyak aturan dan pedoman yang cenderung secara drastis mengurangi jumlah bug berbahaya yang muncul dalam praktik. Pada umumnya tidak mungkin untuk mendapatkan standar untuk menegakkan aturan-aturan ini secara surut karena itu akan merusak terlalu banyak kode yang ada, tetapi biasanya menggunakan peringatan kompiler, serat dan alat analisis statis lainnya untuk mendeteksi jenis masalah yang mudah dicegah ini. Subset dari program C yang lulus alat-alat ini dengan warna terbang sudah jauh lebih aman daripada "hanya C", dan setiap programmer C yang kompeten hari ini akan menggunakan beberapa dari mereka.


Juga, Anda tidak akan pernah membuat kontes Java yang membingungkan sama menghiburnya dengan kontes C yang membingungkan .

Ixrec
sumber
7
"common denominator terendah" terdengar meremehkan. Saya akan mengatakan bahwa, tidak seperti banyak bahasa yang jauh lebih berat, C tidak memberlakukan satu ton bagasi tambahan yang tidak Anda butuhkan dan memberi Anda basis yang sangat cepat untuk mengimplementasikan barang-barang yang Anda butuhkan. Apakah itu yang kamu maksud?
underscore_d
9
"Anda tidak dapat benar-benar memilikinya tanpa yang lain.": Sebenarnya banyak bahasa baru (Rust, Nim, D, ...) berusaha. Ini pada dasarnya bermuara pada mencocokkan subset "aman" dari bahasa dengan beberapa primitif "tidak aman" ketika tingkat kontrol ini mutlak diperlukan. Namun, semua itu dibangun berdasarkan pengetahuan yang terakumulasi dari C dan C ++, jadi mungkin harus dikatakan bahwa pada saat C dan C ++ dikembangkan, Anda tidak dapat memilikinya tanpa yang lain, dan saat ini ada bahasa yang mencoba memartisi bit "tidak aman" mereka, tetapi mereka belum menyusul.
Matthieu M.
6
1) bukan poin yang valid! C mengambil fitur dari Algol 68, yang merupakan bahasa "aman" dalam pengertian ini; jadi penulis tahu tentang bahasa tersebut. Poin lainnya bagus.
reinierpost
4
@ MatthieuM. Anda mungkin ingin melihat Microsoft Research juga. Mereka telah menghasilkan beberapa OS yang dikelola selama satu atau dua dekade terakhir, termasuk beberapa yang lebih cepat (benar-benar tidak sengaja - tujuan utama sebagian besar OS penelitian ini adalah keselamatan, bukan kecepatan) daripada OS yang tidak dikelola yang setara untuk beban kerja kehidupan nyata tertentu . Percepatan sebagian besar disebabkan oleh kendala keamanan - pemeriksaan yang dapat dieksekusi statis dan dinamis memungkinkan optimisasi yang tidak tersedia dalam kode yang tidak dikelola. Ada cukup banyak untuk dilihat, semuanya, dan sumber disertakan;)
Luaan
3
@Luaan: Midori terlihat sangat mengagumkan; Saya selalu menantikan artikel blog Joe.
Matthieu M.
41

Pertama, C adalah bahasa pemrograman sistem. Jadi, misalnya, jika Anda menulis mesin virtual Java atau juru bahasa Python, Anda memerlukan bahasa pemrograman sistem untuk menuliskannya.

Kedua, C memberikan kinerja yang tidak dimiliki bahasa seperti Java dan Python. Biasanya, komputasi kinerja tinggi di Jawa dan Python akan menggunakan perpustakaan yang ditulis dalam bahasa kinerja tinggi seperti C untuk melakukan pengangkatan berat.

Ketiga, C memiliki jejak yang jauh lebih kecil daripada bahasa seperti Java dan Python. Ini membuatnya dapat digunakan untuk sistem embedded, yang mungkin tidak memiliki sumber daya yang diperlukan untuk mendukung lingkungan run-time yang besar dan permintaan memori dari bahasa seperti Java dan Python.


"Bahasa pemrograman sistem" adalah bahasa yang cocok untuk membangun sistem berkekuatan industri dengan; sebagaimana adanya, Java dan Python bukan bahasa pemrograman sistem. "Tepatnya apa yang membuat bahasa pemrograman sistem" berada di luar cakupan pertanyaan ini, tetapi bahasa pemrograman sistem perlu memberikan dukungan untuk bekerja dengan platform yang mendasarinya.

Di sisi lain (dalam menanggapi komentar), bahasa pemrograman sistem tidak perlu hosting sendiri. Masalah ini muncul karena pertanyaan awal bertanya "mengapa orang menggunakan C", komentar pertama bertanya "mengapa Anda perlu bahasa seperti C" ketika Anda memiliki PyPy, dan saya mencatat bahwa PyPy tidak pada kenyataannya menggunakan C. Jadi, awalnya relevan dengan pertanyaan, tetapi sayangnya (dan membingungkan) "hosting sendiri" sebenarnya tidak relevan dengan jawaban ini. Maaf saya membawanya.

Jadi, untuk meringkas: Java dan Python tidak cocok untuk pemrograman sistem bukan karena implementasi utama mereka ditafsirkan, atau karena implementasi yang dikompilasi secara asli tidak di-host sendiri, tetapi karena mereka tidak memberikan dukungan yang diperlukan untuk bekerja dengan platform yang mendasarinya.

datang badai
sumber
19
"Jika Anda menulis mesin virtual Java atau juru bahasa Python, Anda memerlukan bahasa pemrograman sistem untuk menuliskannya." Uh? Bagaimana Anda menjelaskan PyPy? Mengapa Anda perlu bahasa seperti C untuk menulis kompiler atau juru bahasa atau mesin virtual?
Vincent Savard
10
Saya yakin Anda mengklaim Anda memerlukan bahasa pemrograman sistem untuk menulis mesin virtual Java atau juru bahasa Python ketika Anda berkata "jika Anda menulis mesin virtual Java atau juru bahasa Python, Anda akan memerlukan bahasa pemrograman sistem untuk menuliskannya". Jika PyPy tidak memuaskan Anda, Anda juga dapat mencari penerjemah atau kompiler yang ditulis dalam Haskell. Atau sungguh, cukup tambahkan referensi yang mendukung klaim Anda.
Vincent Savard
16
Bahkan jika itu kura-kura turun, sesuatu seperti PyPy tidak akan ada tanpa juru bahasa Python yang ditulis dalam bahasa lain.
Blrfl
18
@Birfl Tapi itu tidak banyak bicara. C tidak mungkin ditulis tanpa kompilator rakitan, dan Anda tidak bisa menulis rakitan tanpa perangkat keras yang mengimplementasikannya.
gardenhead
11
Jika PyPy bukan "bahasa pemrograman sistem" karena sebuah kompiler C terlibat di suatu tempat, maka C juga bukan bahasa pemrograman sistem karena assembler digunakan di suatu tempat. Sebenarnya, bukankah ini populer untuk menerjemahkan C ke bahasa lain akhir-akhir ini? misalnya LLVM
30

Maaf untuk menambahkan jawaban lain, tapi saya rasa jawaban yang ada tidak langsung menjawab kalimat pertama Anda yang menyatakan:

'Saya sedang mempertimbangkan belajar C'

Mengapa? Apakah Anda ingin melakukan hal-hal yang biasanya digunakan C untuk hari ini (mis. Driver perangkat, VM, mesin game, perpustakaan media, sistem tertanam, kernel OS)?

Jika ya, maka ya, tentu pelajari C atau C ++ tergantung pada yang Anda minati. Apakah Anda ingin mempelajarinya sehingga Anda akan memiliki pemahaman yang lebih dalam tentang apa yang dilakukan bahasa tingkat tinggi Anda?

Anda kemudian menyebutkan masalah keamanan. Anda tidak perlu membutuhkan pemahaman yang mendalam tentang safe C untuk melakukan yang terakhir, dengan cara yang sama bahwa contoh kode dalam bahasa tingkat yang lebih tinggi mungkin memberi Anda intisari tanpa menjadi siap produksi.

Tulis beberapa kode C untuk mendapatkan intinya. Lalu letakkan kembali di rak. Jangan terlalu khawatir tentang keamanan kecuali Anda ingin menulis kode produksi C.

Jared Smith
sumber
2
Pekerjaan hebat menjawab apa yang tampaknya menjadi pertanyaan sesungguhnya! Cara terbaik untuk menghargai bahasa C / C ++ dan "lebih aman" untuk semua sebenarnya adalah mencoba menulis sesuatu seperti mesin basis data sederhana. Anda akan merasakan dengan baik untuk setiap pendekatan yang Anda coba, dan melihat ke mana arahnya. Anda akan melihat apa yang terasa alami di kedua, dan Anda akan menemukan di mana pendekatan alami gagal (misalnya sangat mudah untuk "membuat serial" data mentah dalam C - cukup tulis data!; Tetapi hasilnya tidak portabel, sehingga mungkin terbatas penggunaannya). Memahami keamanan itu rumit, karena sebagian besar masalah mungkin sulit ditemui.
Luaan
1
@Luaan tepatnya, mempelajari cara menyalin string menggunakan pointer memberi Anda ide, belajar bagaimana melakukannya dengan aman adalah tingkat lain, dan tergantung pada tujuan seseorang yang mungkin tidak perlu.
Jared Smith
2
Ini sebenarnya bukan pertanyaan. Tapi itu membantu untuk membuat pertikaian. Saya memutuskan untuk melakukannya. Saya bersedia belajar lebih banyak tentang pekerjaan batin dari semua yang dibangun. Dan saya suka pemrograman. Dengan cara ini saya berharap dapat memahami cara kerja komputer secara lebih baik. Itu hanya untuk bersenang-senang.
Tristan
10
Saya tidak setuju dengan kalimat terakhir. Pelajari bagaimana melakukannya dengan benar sebelum mengembangkan kebiasaan buruk.
glglgl
2
@glglgl IDK, jika saya membaca (atau menulis) cuplikan JavaScript di web saya melakukannya dengan pemahaman bahwa itu bukan produksi siap: itu tidak akan memiliki penanganan pengecualian, itu mungkin O (n ^ 2), dll. Tidak ada itu diperlukan untuk mendapatkan titik di. Semua itu diperlukan untuk kode produksi. Mengapa ini berbeda? Saya dapat menulis C naif untuk membangun saya sendiri sambil memahami secara intelektual bahwa jika saya ingin meletakkannya di sana saya harus melakukan lebih banyak pekerjaan.
Jared Smith
14

Ini adalah pertanyaan BESAR dengan banyak jawaban, tetapi versi singkatnya adalah bahwa setiap bahasa pemrograman dikhususkan untuk situasi yang berbeda. Misalnya, JavaScript untuk web, C untuk hal-hal tingkat rendah, C # untuk apa pun Windows, dll. Ini membantu untuk mengetahui apa yang ingin Anda lakukan setelah Anda tahu pemrograman untuk memutuskan bahasa pemrograman apa yang akan dipilih.

Untuk membahas poin terakhir Anda, mengapa C / C ++ lebih dari Java / Python, sering kali turun ke kecepatan. Saya membuat game, dan Java / C # baru-baru ini mencapai kecepatan yang cukup baik untuk dijalankan. Lagi pula, jika Anda ingin game Anda berjalan pada 60 frame per detik, dan Anda ingin game Anda melakukan banyak hal (rendering sangat mahal), maka Anda memerlukan kode untuk berjalan secepat mungkin. Python / Java / C # / Banyak yang lain berjalan pada "penerjemah", lapisan tambahan perangkat lunak yang menangani semua hal yang membosankan yang tidak dimiliki oleh C / C ++, seperti mengelola memori dan pengumpulan sampah. Overhead tambahan itu memperlambat segalanya, jadi hampir setiap gim besar yang Anda lihat sudah selesai (dalam 10 tahun terakhir) di C atau C ++. Ada pengecualian: mesin game Unity menggunakan C # *, dan Minecraft menggunakan Java, tapi itu pengecualian, bukan aturannya. Secara umum,

* Bahkan Unity tidak semua C #, sebagian besar adalah C ++ dan Anda hanya menggunakan C # untuk kode permainan Anda.

EDIT Untuk menanggapi beberapa komentar yang muncul setelah saya memposting ini: Mungkin saya terlalu menyederhanakan terlalu banyak, saya hanya memberikan gambaran umum. Dengan pemrograman, jawabannya tidak pernah sederhana. Ada penerjemah untuk C, Javascript dapat berjalan di luar browser, dan C # dapat berjalan pada apa saja berkat Mono. Bahasa pemrograman yang berbeda dikhususkan untuk domain yang berbeda, tetapi beberapa programmer di suatu tempat mungkin menemukan cara untuk menjalankan bahasa apa pun dalam konteks apa pun. Karena OP tampaknya tidak tahu banyak pemrograman (asumsi saya, maaf kalau saya salah), saya mencoba untuk menjaga jawaban saya sederhana.

Adapun komentar tentang C # hampir secepat C + +, kata kuncinya ada hampir. Ketika saya masih kuliah, kami melakukan tur ke banyak perusahaan game, dan guru saya (yang telah mendorong kami untuk pindah dari C # ke C ++ sepanjang tahun) bertanya kepada programmer di setiap perusahaan yang kami kunjungi mengapa C ++ lebih dari C #, dan setiap satu kata C # terlalu lambat. Secara umum berjalan cepat, tetapi pengumpul sampah dapat merusak kinerja karena Anda tidak dapat mengontrol kapan dijalankan, dan memiliki hak untuk mengabaikan Anda jika tidak ingin berjalan ketika Anda merekomendasikannya. Jika Anda membutuhkan sesuatu untuk menjadi kinerja tinggi, Anda tidak ingin sesuatu yang tidak terduga seperti itu.

Untuk menanggapi komentar "baru mencapai kecepatan" saya, ya, banyak peningkatan kecepatan C # berasal dari perangkat keras yang lebih baik, tetapi karena kerangka .NET dan kompiler C # telah meningkat, ada beberapa peningkatan kecepatan di sana.

Tentang "permainan ditulis dalam bahasa yang sama dengan mesin" komentar, itu tergantung. Beberapa ada, tetapi banyak yang ditulis dalam hibrida bahasa. Unreal dapat melakukan UnrealScript dan C ++, Unity melakukan C # Javascript dan Boo, banyak mesin lain yang ditulis dalam C atau C ++ menggunakan Python atau Lua sebagai bahasa scripting. Tidak ada jawaban sederhana di sana.

Dan hanya karena itu mengganggu saya untuk membaca "siapa yang peduli jika game Anda berjalan pada 200fps atau 120fps", jika game Anda berjalan lebih cepat dari 60fps, Anda mungkin membuang-buang waktu cpu, karena monitor rata-rata bahkan tidak menyegarkan bahwa cepat. Beberapa yang lebih tinggi dan yang lebih baru, tetapi tidak standar (belum ...).

Dan tentang komentar "mengabaikan teknologi", saya masih berusia awal 20-an, jadi ketika saya mengekstrapolasi ke belakang, saya sebagian besar menggemakan apa yang dikatakan oleh programmer yang lebih tua dan lebih berpengalaman kepada saya. Jelas itu akan diperebutkan di situs seperti ini, tetapi layak untuk dipertimbangkan.

Cody
sumber
4
" C # untuk apa pun Windows " - Oh, itu kesalahan besar. Dan Anda bahkan memberikan contoh. Kesatuan. AFAIK Ini tidak ditulis itu menyediakan C # API karena bahasa yang bagus dan mudah beradaptasi. Ini dirancang dengan sangat baik. Dan saya suka c ++ lebih, tapi kredit harus diberikan di mana itu jatuh tempo. Mungkin Anda menggabungkan C # dengan .NET? Mereka sering nongkrong bersama.
luk32
2
"Bahkan Unity tidak semua C #, sebagian besar dari itu adalah C ++" Dan? Game di Unity sering menggunakan C # secara ekstensif, dan telah ada selama beberapa waktu sekarang. Menyarankan bahwa C # adalah 'baru saja mencapai kecepatan' baik membutuhkan lebih banyak konteks, atau berisiko buta terhadap teknologi dekade ini.
NPSF3000
2
Hampir setiap permainan besar ditulis dalam bahasa mesin yang digunakannya: jumlah pekerjaan yang akan membutuhkan penggandaan sangat besar sehingga tidak ada pertimbangan teknis lainnya yang layak diperhitungkan. Rendering memang mahal, tetapi saat ini itu semua ditulis dalam shader dan bahasa loop logika tidak relevan.
Peter Taylor
2
C # selalu dikompilasi JIT (tidak seperti Java, di mana komentar Anda benar), dan itu cukup mampu kecepatan eksekusi yang sangat mirip dengan C ++ dari awal jika Anda tahu apa yang Anda lakukan. Itu tahun 2003 - bukan sesuatu yang akan saya pertimbangkan baru-baru ini. Kecepatan mentah bukan masalah utama untuk gim (terutama dengan shader yang dapat diprogram pada GPU), ada hal-hal lain yang membuat bahasa seperti C # lebih atau kurang populer saat itu. Dua masalah utama adalah API (yang sangat berorientasi C, dan interfacing mungkin mahal) dan GC (kebanyakan untuk masalah latensi, bukan throughput mentah).
Luaan
1
@ gbjbaanb Bukan hanya CPU yang lebih cepat - masalah besar adalah bahwa C ++ dan C memiliki dekade untuk menyempurnakan kompiler dan runtime mereka, sementara Java pada dasarnya dimulai dari nol (dirancang sebagai platform multi-platform terutama). Ketika VM meningkat (mis., Beralih dari interpreter ke kompiler JIT, meningkatkan GC ...), begitu pula kinerja aplikasi Java. Banyak keunggulan C / C ++ masih ada dalam pendekatan "mari kita berharap tidak ada istirahat" - menghindari banyak pemeriksaan yang dianggap "tidak perlu". Tapi itu masih memori babi yang besar - pada kenyataannya, peningkatan penggunaan CPU sering berarti kinerja memori yang lebih buruk :)
Luaan
13

Lucu bahwa Anda mengklaim C tidak aman karena "memiliki petunjuk". Yang sebaliknya adalah benar: Java dan C # secara praktis hanya memiliki pointer (untuk tipe non-asli). Kesalahan paling umum di Jawa mungkin adalah Null Pointer Exception (lih. Https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare ). Kesalahan kedua yang paling umum mungkin adalah memegang referensi tersembunyi ke objek yang tidak digunakan (mis. Dialog tertutup tidak dibuang) yang karenanya tidak dapat dilepaskan, yang mengarah ke program yang berjalan lama dengan jejak memori yang terus tumbuh.

Ada dua mekanisme dasar yang membuat C # dan Java lebih aman, dan lebih aman dalam dua cara berbeda:

  • Pengumpulan sampah memperkecil kemungkinan program mencoba mengakses objek yang dibuang. Hal ini membuat program cenderung berhenti secara tak terduga. Berbeda dengan C, Java dan C # secara default mengalokasikan data non-asli secara dinamis. Ini membuat logika program sebenarnya lebih kompleks, tetapi pengumpulan sampah bawaan - dengan biaya - mengambil alih bagian yang sulit.

Pointer pintar C ++ terbaru membuat pekerjaan itu lebih mudah bagi programmer.

  • Java dan C # mengkompilasi ke kode perantara yang ditafsirkan / dieksekusi oleh run time yang rumit. Ini menambah tingkat keamanan karena run time dapat mendeteksi aktivitas terlarang dari suatu program. Bahkan jika program dikodekan secara tidak aman (yang dimungkinkan dalam kedua bahasa), masing-masing waktu dalam teori mencegah "pecah" ke dalam sistem.
    Waktu berjalan tidak melindungi terhadap mis. Upaya buffer overruns, tetapi secara teori tidak memungkinkan eksploitasi program tersebut. Sebaliknya, dengan C dan C ++, programmer harus membuat kode dengan aman untuk mencegah eksploitasi. Ini biasanya tidak tercapai segera tetapi membutuhkan ulasan dan iterasi.

Perlu dicatat bahwa jangka waktu yang rumit juga merupakan risiko keamanan. Tampak bagi saya bahwa Oracle memperbarui JVM setiap beberapa minggu karena masalah keamanan yang baru ditemukan. Tentu saja, jauh lebih sulit untuk memverifikasi JVM daripada satu program tunggal.

Oleh karena itu, keamanan waktu lari yang rumit bersifat ambigu dan menipu: Program C rata-rata Anda dapat, dengan ulasan dan iterasi, dibuat cukup aman. Program Java rata-rata Anda hanya seaman JVM; itu tidak benar. Tidak pernah.

Artikel tentang gets()yang Anda tautkan mencerminkan keputusan perpustakaan historis yang akan dibuat berbeda hari ini, bukan bahasa inti.

Peter A. Schneider
sumber
3
Saya pikir inti dari penulis asli adalah bahwa dalam C Anda dapat mengambil tindakan yang tidak dicentang pada pointer tersebut. Di java, Anda mendapatkan pengecualian yang bagus segera - di C, Anda mungkin tidak menyadari bahwa Anda sedang membaca lokasi yang tidak valid sampai keadaan aplikasi Anda rusak.
Sam Dufel
1
Juga, stackoverflow.com/questions/57483/… - akan lebih akurat untuk mengatakan bahwa java memiliki "referensi praktis hanya".
Sam Dufel
4
Saya telah melihat semua jenis bug menarik hasil dari upaya untuk menghindari petunjuk eksplisit. Biasanya masalah mendasar adalah kebingungan antara salinan dan referensi. Di C, jika saya memberikan Anda pointer ke sesuatu, Anda tahu bahwa memodifikasi itu akan memengaruhi yang asli. Beberapa upaya untuk menghindari petunjuk mengaburkan perbedaan ini, yang mengarah ke labirin salinan dalam, salinan dangkal, dan kebingungan umum.
Arlie Stephens
Menyatakan bahwa Oracle JVM menyebalkan (dari sudut pandang pendarahan kerentanan keamanan yang dapat dieksploitasi) dan oleh karena itu runtime bahasa yang dikelola secara umum memperkenalkan lebih banyak masalah keamanan daripada menggunakan bahasa yang dikelola menghindari seperti mengatakan bahwa Adobe Flash mengerikan sebagai sumber ketidakamanan dan program yang apakah pemutaran video & animasi dari situs web pada dasarnya tidak aman. Tidak semua runtime Java hampir seburuk kekejaman JVM vintage-Oracle tahun 1990-an, dan tidak semua bahasa yang dikelola adalah Java. (Ya, tentu saja.)
Sebagian besar diinformasikan
@halfin dengan baik; Saya mengatakan bahwa sebuah program hanya seaman runtime-nya, dan program "your average" (baca: small-ish) dapat dengan upaya dibuat lebih aman daripada runtime besar seperti penerjemah kode byte. Pernyataan itu sepertinya tidak bisa disangkal. Apakah program yang berdiri sendiri atau runtime tertentu lebih atau kurang aman daripada yang lain tergantung pada kompleksitas dan desain masing-masing, pengkodean dan kualitas pemeliharaan. Sebagai contoh, saya tidak akan mengatakan bahwa sendmail lebih aman daripada Java VM Oracle; tapi qmail mungkin.
Peter A. Schneider
10

Karena "keamanan" membutuhkan kecepatan, bahasa "aman" tampil pada kecepatan yang lebih lambat.

Anda bertanya mengapa menggunakan bahasa "berbahaya" seperti C atau C ++, mintalah seseorang menulis driver video atau sejenisnya dengan Python atau Java, dll. Dan lihat bagaimana perasaan Anda tentang "keamanan" :)

Namun serius, Anda harus sedekat mungkin dengan memori inti mesin untuk dapat memanipulasi piksel, register, dll. Java atau Python tidak dapat melakukan ini dengan semua jenis kecepatan layak-kinerja ... C dan C ++ keduanya memungkinkan Anda untuk melakukan ini melalui petunjuk dan sejenisnya ...

Wintermut3
sumber
20
Secara umum tidak benar bahwa biaya keselamatan lebih cepat . Bahasa yang tersedia paling aman melakukan sebagian besar pemeriksaan pada waktu kompilasi. O'Caml, Ada, Haskell, Rust semua tidak tertinggal jauh di belakang C dalam hal kecepatan runtime rata-rata. Apa yang biasanya mereka lakukan adalah overhead yang signifikan dalam ukuran program, efisiensi memori, latensi, dan waktu kompilasi yang jelas. Dan, ya, mereka mengalami kesulitan dengan hal-hal yang dekat dengan logam. Tapi itu bukan masalah kecepatan.
leftaroundabout
6
Juga, C tidak melakukan apa yang Anda pikirkan. C adalah mesin abstrak . Itu tidak memberi Anda akses langsung ke apa pun - itu hal yang baik. Anda bahkan tidak bisa melihat perakitan modern untuk melihat seberapa banyak C bersembunyi dari Anda - perakitan modern (misalnya TASM) akan dianggap sebagai bahasa tingkat tinggi kembali ketika C dikembangkan. Saya akan sangat senang jika seseorang menulis driver dalam bahasa "aman", terima kasih - itu akan sangat membantu menghindari banyak BSODs dan membeku, belum lagi lubang keamanan :) Dan yang paling penting, ada bahasa sistem yang jauh lebih aman dari C.
Luaan
3
@Wintermute Anda benar-benar ingin mencari Rust sebelum membuat komentar tentang bagaimana fitur keselamatan tentu membutuhkan biaya. Sial, sistem tipe tingkat rendah C sebenarnya menghambat banyak optimisasi yang sangat berguna yang bisa dilakukan oleh kompiler (terutama ketika mempertimbangkan bahwa tidak ada proyek c yang besar yang berhasil dihindari untuk tidak melanggar alias ketat di suatu tempat ).
Voo
7
@Wintermute Ya mitos bahwa Anda tidak dapat membuat C / C ++ lebih aman tanpa memperkenalkan overhead kinerja sangat gigih itulah sebabnya saya menganggap ini agak serius (ada beberapa area di mana ini memang benar [memeriksa batas]). Sekarang mengapa Rust tidak lebih luas? Sejarah dan kompleksitas. Rust masih relatif baru dan banyak sistem terbesar yang ditulis dalam C ada sebelum Rust ditemukan - Anda tidak akan menulis ulang sejuta LOC dalam bahasa baru meskipun itu jauh lebih aman. Juga setiap programmer dan anjing mereka tahu C, Rust? Semoga berhasil menemukan cukup banyak orang.
Voo
3
@Vo Dogs melakukan C? ... tidak heran saya telah melihat begitu banyak kode buruk di luar sana ... j / k Poin diambil tentang Rust (saya baru saja mengunduh dan menginstalnya, jadi Anda mungkin memiliki konversi lain untuk menambahkan) BTW dalam hal untuk Rust melakukannya dengan benar ... Aku bisa membuat penambahan yang sama untuk "D" :)
Wintermut3
9

Selain semua hal di atas, ada juga satu kasus penggunaan yang cukup umum, yaitu menggunakan C sebagai perpustakaan umum untuk bahasa lain.

Pada dasarnya, hampir semua bahasa memiliki antarmuka API ke C.

Contoh sederhana, cobalah membuat aplikasi umum untuk Linux / IOS / Android / Windows. Selain semua alat yang ada di luar sana, yang akhirnya kami lakukan adalah pustaka inti di C, dan kemudian mengubah GUI untuk setiap lingkungan, yaitu:

  • IOS: ObjectiveC dapat menggunakan pustaka C secara asli
  • Android: Java + JNI
  • Linux / Windows / MacOS: Dengan GTK / .Net Anda dapat menggunakan pustaka asli. Jika Anda menggunakan Python, Perl, Ruby masing-masing memiliki antarmuka API asli. (Java lagi dengan JNI).

Dua sen saya,

Nito
sumber
Salah satu alasan saya suka menggunakan, katakanlah, PHP, adalah karena hampir semua perpustakaannya, memang, ditulis dalam C - untungnya begitu, atau PHP akan lambat tak tertahankan :) PHP bagus untuk menulis kode ceroboh tanpa takut melakukan sesuatu yang 'berbahaya' (dan itulah sebabnya saya cenderung menulis lebih banyak kode PHP daripada yang lain - saya suka kode ceroboh!: D), tapi senang mengetahui bahwa di bawah banyak fungsi panggilan itu ada yang baik 'dipercaya' C perpustakaan untuk memberinya beberapa peningkatan kinerja ;-) Sebaliknya, menulis kode ceroboh dalam C adalah besar tidak-tidak ...
Gwyneth Llewelyn
7

Kesulitan mendasar dengan C adalah bahwa nama tersebut digunakan untuk menggambarkan sejumlah dialek dengan sintaksis yang identik tetapi sangat berbeda. Beberapa dialek jauh lebih aman daripada yang lain.

Dalam C seperti yang awalnya dirancang oleh Dennis Ritchie, pernyataan C umumnya akan dipetakan ke instruksi mesin dengan cara yang dapat diprediksi. Karena C dapat berjalan pada prosesor yang berperilaku berbeda ketika hal-hal seperti menandatangani aritmatika meluap terjadi, seorang programmer yang tidak tahu bagaimana mesin akan berperilaku jika aritmatika meluap tidak akan tahu kode C yang berjalan pada mesin itu akan berperilaku baik, tetapi jika sebuah mesin diketahui berperilaku dengan cara tertentu (mis. silent two's-melengkapi wraparound) maka implementasi pada mesin itu biasanya akan melakukan hal yang sama. Salah satu alasan mengapa C mendapat reputasi untuk menjadi cepat adalah bahwa dalam kasus di mana programmer tahu bahwa perilaku alami platform dalam skenario kasus tepi akan sesuai dengan kebutuhan mereka, tidak perlu bagi programmer atau kompiler untuk menulis kode untuk menghasilkan skenario seperti itu. .

Sayangnya, penulis kompiler telah mengambil pandangan bahwa karena Standar tidak memaksakan persyaratan pada implementasi apa yang harus dilakukan dalam kasus-kasus seperti itu (kelonggaran yang dimaksudkan untuk memungkinkan implementasi perangkat keras yang mungkin tidak berperilaku dapat diprediksi), kompiler harus merasa bebas untuk menghasilkan kode yang meniadakan hukum waktu dan kausalitas.

Pertimbangkan sesuatu seperti:

int hey(int x)
{
   printf("%d", x);
   return x*10000;
}
void wow(int x)
{
  if (x < 1000000)
    printf("QUACK!");
  hey(x);    
}

Teori kompiler hiper-modern (tetapi modis) akan menyarankan bahwa kompiler harus menampilkan "QUACK!" tanpa syarat, karena dalam kasus mana pun kondisi itu salah, program akan berakhir meminta perilaku tidak terdefinisi melakukan kelipatan yang hasilnya akan diabaikan. Karena Standar akan memungkinkan kompiler untuk melakukan apa pun yang disukainya dalam kasus seperti itu, itu memungkinkan kompiler untuk menghasilkan "QUACK!".

Sementara C dulu lebih aman daripada bahasa assembly, ketika menggunakan kompiler hyper-modern kebalikannya adalah benar. Dalam bahasa assembly, integer overflow dapat menyebabkan perhitungan menghasilkan hasil yang tidak berarti, tetapi pada sebagian besar platform yang akan menjadi sejauh efeknya. Jika hasilnya akhirnya diabaikan, melimpah tidak akan menjadi masalah. Dalam hiper-modern C, bagaimanapun, bahkan apa yang biasanya akan menjadi "jinak" bentuk Perilaku Tidak Terdefinisi (seperti overflow integer dalam perhitungan yang akhirnya diabaikan) dapat menyebabkan eksekusi program sewenang-wenang.

supercat
sumber
1
bahkan dalam kompiler hiper-modern, C tidak membatasi-memeriksa array. jika itu dilakukan, itu tidak akan kompatibel dengan definisi bahasa. saya menggunakan fakta itu kadang-kadang untuk membuat array dengan pointer tambahan ke tengah array untuk memiliki indeks negatif.
robert bristow-johnson
1
Saya ingin melihat bukti dari contoh Anda yang menghasilkan "QUACK!" tanpa syarat. x tentu saja bisa lebih besar dari 10.00000 pada titik perbandingan, dan evaluasi selanjutnya yang akan menghasilkan luapan tidak mencegah hal itu. Lebih dari itu, jika Anda telah mengaktifkan inlining yang memungkinkan multiplikasi meluap untuk dihapus, argumen Anda tentang batasan rentang implisit tidak berlaku.
Graham
2
@ robertbristow-johnson: Sebenarnya, Standar secara eksplisit mengatakan bahwa jika diberikan int arr[5][[5], upaya untuk mengakses arr[0][5]akan menghasilkan Perilaku Tidak Terdefinisi. Aturan seperti itu memungkinkan kompiler yang diberi sesuatu seperti arr[1][0]=3; arr[0][i]=6; arr[1][0]++;menyimpulkan yang arr[1][0]akan sama dengan 4, tanpa memperhatikan nilai i.
supercat
2
@ robertbristow-johnson: Sekalipun kompiler mengalokasikan array dalam suatu struktur secara berurutan tanpa celah, itu tidak menjamin bahwa pengindeksan salah satu array dijamin untuk mempengaruhi yang lain. Lihat godbolt.org/g/Avt3KW untuk contoh bagaimana gcc akan memperlakukan kode tersebut.
supercat
1
@ robertbristow-johnson: Saya berkomentar di majelis untuk menjelaskan apa yang dilakukannya. Kompiler melihat bahwa kode menyimpan 1 ke s-> arr2 [0] dan kemudian menambahkan s-> arr2 [0], jadi gcc menggabungkan kedua operasi tersebut dengan meminta kode hanya menyimpan nilai nilai 2, tanpa mempertimbangkan kemungkinan bahwa intervensi menulis untuk s-> arr1 [i] dapat mempengaruhi nilai s-> arr1 [0] (karena, menurut Standar, itu tidak bisa).
supercat
5

Alasan historis. Saya tidak sering menulis kode baru, kebanyakan saya bisa mempertahankan dan memperpanjang hal-hal lama yang telah berjalan selama beberapa dekade. Saya senang C dan bukan Fortran.

Saya bisa kesal ketika beberapa siswa berkata, "tapi mengapa kamu melakukan X mengerikan ini ketika kamu bisa melakukan Y?". Ya, X adalah pekerjaan yang saya dapatkan dan membayar tagihan dengan sangat baik. Saya pernah melakukan Y pada kesempatan, dan itu menyenangkan, tetapi X adalah apa yang kebanyakan dari kita lakukan.

RedSonja
sumber
5

Apa itu "berbahaya"?

Klaim bahwa C "berbahaya" adalah titik pembicaraan yang sering terjadi dalam perang api bahasa (paling sering dibandingkan dengan Jawa). Namun, bukti untuk klaim ini tidak jelas.

C adalah bahasa dengan serangkaian fitur tertentu. Beberapa fitur ini memungkinkan jenis kesalahan tertentu yang tidak diizinkan oleh jenis bahasa lain (risiko manajemen memori C biasanya disorot). Namun, ini tidak sama dengan argumen bahwa C lebih berbahaya daripada bahasa lain secara keseluruhan . Saya tidak mengetahui ada orang yang memberikan bukti meyakinkan tentang hal ini.

Juga, "berbahaya" tergantung pada konteks: apa yang Anda coba lakukan, dan risiko apa yang Anda khawatirkan?

Dalam banyak konteks saya akan menganggap C lebih "berbahaya" daripada bahasa tingkat tinggi, karena mengharuskan Anda untuk melakukan lebih banyak penerapan fungsionalitas dasar secara manual, meningkatkan risiko bug. Misalnya, melakukan beberapa pemrosesan teks dasar atau mengembangkan situs web di C biasanya akan menjadi bodoh, karena bahasa lain memiliki fitur yang membuat ini jauh lebih mudah.

Namun, C dan C ++ banyak digunakan untuk sistem mission-critical, karena bahasa yang lebih kecil dengan kontrol langsung yang lebih keras dianggap "lebih aman" dalam konteks itu. Dari jawaban Stack Overflow yang sangat baik :

Meskipun C dan C ++ tidak secara khusus dirancang untuk jenis aplikasi ini, mereka banyak digunakan untuk perangkat lunak yang tertanam dan penting karena beberapa alasan. Properti utama note adalah kontrol atas manajemen memori (yang memungkinkan Anda untuk menghindari pengumpulan sampah, misalnya), pustaka run-time core yang sederhana dan penuh debugged serta dukungan alat yang matang. Banyak rantai alat pengembangan tertanam yang digunakan saat ini pertama kali dikembangkan pada 1980-an dan 1990-an ketika ini adalah teknologi saat ini dan berasal dari budaya Unix yang lazim pada waktu itu, sehingga alat ini tetap populer untuk jenis pekerjaan ini.

Walaupun kode manajemen memori manual harus diperiksa dengan cermat untuk menghindari kesalahan, kode ini memungkinkan tingkat kontrol atas waktu respons aplikasi yang tidak tersedia dengan bahasa yang bergantung pada pengumpulan sampah. Pustaka run time inti dari bahasa C dan C ++ relatif sederhana, matang, dan dipahami dengan baik, sehingga merupakan salah satu platform paling stabil yang tersedia.

Komunitas
sumber
2
Saya akan mengatakan hyper-modern C juga lebih berbahaya daripada bahasa rakitan atau dialek tingkat rendah asli C yang secara konsisten berperilaku seolah-olah mereka secara konsisten menerjemahkan operasi C ke dalam operasi kode mesin tanpa memperhatikan kasus-kasus tepi di mana operasi kode mesin alami akan telah menetapkan perilaku tetapi Standar C tidak akan memaksakan persyaratan. Pendekatan hyper-modern di mana integer overflow dapat meniadakan aturan waktu dan hubungan sebab akibat tampaknya jauh lebih tidak bisa diterima oleh pembuatan kode aman.
supercat
5

Untuk menambah jawaban yang ada, semuanya baik-baik saja dan pepatah mengatakan bahwa Anda akan memilih Python atau PHP untuk proyek Anda, karena relatif aman. Tetapi seseorang harus mengimplementasikan bahasa-bahasa itu dan, ketika mereka melakukannya, mereka mungkin akan melakukannya dalam bahasa C. (Atau, yah, sesuatu seperti itu.)

Jadi itu sebabnya orang menggunakan C - untuk membuat alat yang tidak berbahaya yang ingin Anda gunakan.

Lightness Races di Orbit
sumber
2

Izinkan saya mengulangi pertanyaan Anda:

Saya sedang mempertimbangkan untuk belajar [alat].

Tetapi mengapa orang menggunakan [alat] (atau [alat terkait]) jika [mereka] dapat digunakan 'berbahaya'?

Alat apa pun yang menarik dapat digunakan secara berbahaya, termasuk bahasa pemrograman. Anda belajar lebih banyak sehingga Anda dapat melakukan lebih banyak (dan agar lebih sedikit bahaya dibuat ketika Anda menggunakan alat ini). Secara khusus, Anda mempelajari alat itu sehingga Anda dapat melakukan hal yang baik untuk alat itu (dan mungkin mengenali kapan alat itu adalah alat terbaik dari alat yang Anda tahu).

Misalnya, jika Anda perlu meletakkan lubang silinder berdiameter 6 mm, dalam 5 cm, pada balok kayu, bor adalah alat yang jauh lebih baik daripada parser LALR. Jika Anda tahu apa dua alat ini, Anda tahu mana alat yang tepat. Jika Anda sudah tahu cara menggunakan bor, voila !, lubang.

C hanyalah alat lain. Lebih baik untuk beberapa tugas daripada untuk yang lain. Jawaban lain di sini membahas hal ini. Jika Anda belajar beberapa C, Anda akan mengenali kapan itu adalah alat yang tepat dan kapan tidak.

Eric Towers
sumber
Sebagian besar jawaban ini adalah mengapa pertanyaan dilontarkan sebagai "terutama berdasarkan pendapat". Jangan katakan bahwa C memiliki kelebihannya, katakan apa adanya!
reinierpost
1

Saya sedang mempertimbangkan untuk belajar C

Tidak ada alasan khusus untuk tidak belajar C tetapi saya akan menyarankan C ++. Ia menawarkan banyak hal yang dilakukan oleh C (karena C ++ adalah kumpulan super C), dengan sejumlah besar "ekstra". Belajar C sebelum C ++ tidak perlu - mereka adalah bahasa yang terpisah secara efektif.

Dengan kata lain, jika C adalah seperangkat alat-alat pertukangan, kemungkinan akan menjadi:

  • Palu
  • kuku
  • gergaji tangan
  • bor tangan
  • block sander
  • pahat (mungkin)

Anda dapat membangun apa saja dengan alat-alat ini - tetapi segala sesuatu yang bagus berpotensi membutuhkan banyak waktu dan keterampilan.

C ++ adalah kumpulan alat-alat listrik di toko perangkat keras lokal Anda.

Jika Anda tetap menggunakan fitur bahasa dasar untuk memulai, C ++ memiliki kurva belajar tambahan yang relatif sedikit.

Tetapi mengapa orang menggunakan C (atau C ++) jika itu dapat digunakan 'berbahaya'?

Karena beberapa orang tidak menginginkan furnitur dari IKEA. =)

Serius meskipun, sementara banyak bahasa yang "lebih tinggi" dari C atau C ++ mungkin memiliki hal-hal yang membuat mereka (berpotensi) "lebih mudah" untuk digunakan dalam aspek-aspek tertentu, ini tidak selalu merupakan hal yang baik. Jika Anda tidak menyukai cara sesuatu dilakukan atau fitur tidak disediakan, kemungkinan tidak banyak yang dapat Anda lakukan. Di sisi lain, C dan C ++ menyediakan fitur bahasa "tingkat rendah" yang cukup (termasuk pointer) sehingga Anda dapat mengakses banyak hal secara langsung (terutama perangkat keras atau sistem operasi) atau membangunnya sendiri, yang mungkin tidak dapat dilakukan di negara lain. bahasa sebagaimana diterapkan.

Lebih khusus, C memiliki serangkaian fitur berikut yang membuatnya diinginkan untuk banyak programmer:

  • Kecepatan - Karena kesederhanaan relatif dan optimisasi kompiler selama bertahun-tahun, ini secara alami sangat cepat. Selain itu, banyak orang telah menemukan banyak pintasan untuk sasaran tertentu saat menggunakan bahasa tersebut, yang membuatnya berpotensi lebih cepat.
  • Ukuran - Untuk alasan yang sama seperti yang terdaftar untuk kecepatan, program C dapat dibuat sangat kecil (baik dalam hal ukuran yang dapat dieksekusi dan penggunaan memori), yang diinginkan untuk lingkungan dengan memori terbatas (yaitu tertanam atau seluler).
  • Kompatibilitas - C telah ada sejak lama dan semua orang memiliki alat dan pustaka untuk itu. Bahasa itu sendiri juga tidak pilih-pilih - ia mengharapkan prosesor untuk menjalankan instruksi dan memori untuk menyimpan barang-barang dan itu saja.

    Selain itu, ada sesuatu yang dikenal sebagai Application Binary Interface (ABI) . Singkatnya, ini adalah cara bagi program untuk berkomunikasi pada tingkat kode mesin, yang dapat memiliki keunggulan dibandingkan Antarmuka Pemrograman Aplikasi (API) . Sementara bahasa lain seperti C ++ dapat memiliki ABI, biasanya ini kurang seragam (disepakati) dari C, jadi C membuat bahasa dasar yang baik ketika Anda ingin menggunakan ABI untuk berkomunikasi dengan program lain karena suatu alasan.

Mengapa programmer tidak hanya menggunakan Java atau Python atau bahasa kompilasi lain seperti Visual Basic?

Efisiensi (dan terkadang skema manajemen memori yang tidak dapat diimplementasikan tanpa akses langsung ke memori).

Langsung mengakses memori dengan pointer memperkenalkan banyak trik rapi (biasanya cepat) ketika Anda dapat menempatkan cakar kotor Anda pada anak-anak kecil dan nol di memori Anda lubang cubby langsung dan tidak harus menunggu itu berarti guru untuk membagikan mainan hanya saat bermain kemudian ambil lagi.

Singkatnya, menambahkan hal-hal yang berpotensi menciptakan kelambatan atau memperkenalkan kompleksitas yang tidak diinginkan.

Mengenai bahasa skrip dan sejenisnya, Anda harus bekerja keras untuk mendapatkan bahasa yang membutuhkan program sekunder untuk berjalan seefisien C (atau bahasa yang dikompilasi) secara asli. Menambahkan penerjemah saat terbang secara inheren memperkenalkan kemungkinan penurunan kecepatan eksekusi dan peningkatan penggunaan memori karena Anda menambahkan program lain ke dalam campuran. Efisiensi program Anda sangat bergantung pada efisiensi program sekunder ini sebaik seberapa baik (buruk =)) Anda menulis kode program asli Anda. Belum lagi program Anda sering benar-benar bergantung pada program kedua untuk dieksekusi. Program kedua itu tidak ada karena suatu alasan pada sistem tertentu? Kode tidak jalan.

Bahkan, memperkenalkan sesuatu yang "ekstra" berpotensi memperlambat atau mempersulit kode Anda. Dalam bahasa "tanpa penunjuk menakutkan", Anda selalu menunggu bit kode lain untuk dibersihkan di belakang Anda atau mencari cara "aman" untuk melakukan sesuatu - karena program Anda masih melakukan operasi akses memori yang sama seperti yang mungkin dilakukan dengan pointer. Anda bukan orang yang menanganinya (jadi Anda tidak dapat melakukannya, genius = P).

Berbahaya, maksud saya dengan pointer dan hal-hal serupa lainnya. [...] Seperti pertanyaan Stack Overflow. Mengapa fungsi get jadi berbahaya sehingga tidak boleh digunakan?

Per jawaban yang diterima:

"Itu tetap merupakan bagian resmi dari bahasa hingga standar ISO C 1999, tetapi secara resmi dihapus oleh standar 2011. Sebagian besar implementasi C masih mendukungnya, tetapi setidaknya gcc mengeluarkan peringatan untuk kode apa pun yang menggunakannya."

Gagasan bahwa karena sesuatu dapat dilakukan dalam bahasa, itu harus dilakukan adalah konyol. Bahasa memiliki kekurangan yang diperbaiki. Untuk alasan kompatibilitas dengan kode lama, konstruk ini masih dapat digunakan. Tapi tidak ada (kemungkinan) memaksa programmer untuk menggunakan get () dan, pada kenyataannya, perintah ini pada dasarnya diganti dengan alternatif yang lebih aman.

Lebih tepatnya, masalah dengan mendapat () bukan masalah pointer per se. Ini masalah dengan perintah yang tidak perlu tahu cara menggunakan memori dengan aman. Dalam arti abstrak, ini semua masalah pointer - membaca dan menulis hal-hal yang tidak seharusnya. Itu bukan masalah dengan pointer; itu masalah dengan implementasi pointer.

Untuk memperjelas, pointer tidak berbahaya sampai Anda secara tidak sengaja mengakses lokasi memori yang tidak Anda inginkan. Itupun tidak menjamin komputer Anda akan meleleh atau meledak. Dalam kebanyakan kasus, program Anda akan berhenti berfungsi (dengan benar).

Yang mengatakan, karena pointer memberikan akses ke lokasi memori dan karena data dan kode yang dapat dieksekusi ada dalam memori bersama, ada cukup bahaya nyata dari korupsi tidak disengaja yang Anda ingin mengelola memori dengan benar.

Untuk itu, karena operasi akses memori yang benar-benar langsung sering kali memberikan manfaat yang kurang secara umum daripada yang mungkin terjadi bertahun-tahun yang lalu, bahkan bahasa yang dikumpulkan non- sampah seperti C ++ telah memperkenalkan hal-hal seperti pointer pintar untuk membantu menjembatani kesenjangan antara efisiensi dan keamanan memori.

Singkatnya, ada sangat sedikit alasan untuk takut pada pointer selama itu digunakan dengan aman. Ambil saja petunjuk dari Steve Park "The Crocodile Hunter" versi South Park, Irwin - jangan terus menempel ibu jari Anda di lubang buaya .

Anaksunaman
sumber
2
Saya tidak setuju dengan saran untuk belajar C ++ alih-alih C. Menulis C ++ bagus lebih sulit daripada menulis C bagus dan membaca C ++ jauh lebih sulit daripada membaca C. Jadi kurva belajar C ++ jauh lebih curam. "C ++ adalah set super C" Ini kurang lebih seperti mengatakan bahwa sepatu bot adalah superset dari sandal. Mereka memiliki kelebihan dan penggunaan yang berbeda dan masing-masing memiliki fitur yang lainnya tidak.
martinkunev
"Menulis C ++ bagus lebih sulit daripada menulis C bagus" - Tentu saja. =) "[R] membaca C ++ jauh lebih sulit daripada membaca C" - Setiap pemrograman tingkat lanjut kemungkinan tidak dapat dibedakan dari sihir ;-) Dua sen saya adalah bahwa ini jauh lebih tergantung pada programmer daripada tergantung pada bahasa, meskipun C ++ tidak banyak membantu dirinya sendiri. dalam kategori ini. "Jadi kurva belajar C ++ jauh lebih curam." - Dalam jangka panjang, ya. Dalam jangka pendek, kurang begitu (menurut saya). Secara anekdot, sebagian besar kursus bahasa dasar di C dan C ++ cenderung mencakup jenis materi umum yang hampir sama, kecuali kelas untuk C ++.
Anaksunaman
2
"Mereka memiliki kelebihan dan penggunaan yang berbeda dan masing-masing memiliki fitur yang lainnya tidak." - Seperti yang disebutkan "Tidak ada alasan khusus untuk tidak belajar C [.]" C adalah bahasa yang baik dan saya tetap dengan itu. Jika cocok dengan OP atau orang lain, saya sepenuhnya mendukung mempelajarinya. =)
Anaksunaman
Belajar C mengajarkan Anda cara kerja mesin (tidak sepenuhnya turun, tetapi masih selangkah lebih dekat ke logam). Itu alasan yang sangat bagus untuk mempelajarinya.
Agent_L
1

Seperti biasa, bahasa pemrograman hanyalah konsekuensi dari pemecahan masalah. Anda sebenarnya harus belajar tidak hanya C tetapi banyak bahasa yang berbeda (dan cara-cara lain pemrograman komputer, baik itu alat GUI atau penerjemah perintah) untuk memiliki kotak peralatan yang layak untuk digunakan saat memecahkan masalah.

Kadang-kadang Anda akan menemukan bahwa masalah cocok untuk sesuatu yang termasuk dalam pustaka default Java, dalam kasus seperti itu Anda dapat memilih Java untuk memanfaatkan itu. Dalam kasus lain, mungkin Anda perlu melakukan sesuatu pada Windows yang jauh lebih sederhana di .NET runtime, jadi Anda dapat menggunakan C # atau VB. Mungkin ada alat grafis atau skrip perintah yang memecahkan masalah Anda, maka Anda dapat menggunakannya. Mungkin Anda perlu menulis aplikasi GUI pada banyak platform, Java bisa menjadi pilihan, mengingat pustaka yang disertakan di JDK, tetapi sekali lagi, satu platform target mungkin tidak memiliki JRE jadi mungkin Anda memilih C dan SDL (atau serupa).

C memiliki posisi penting dalam set alat ini, karena bersifat umum, kecil dan cepat dan juga mengkompilasi ke kode mesin. Ini juga didukung pada setiap platform di bawah matahari (bukan tanpa mengkompilasi ulang namun).

Intinya adalah, Anda harus belajar sebanyak mungkin alat, bahasa, dan paradigma yang Anda bisa.

Jauhi pola pikir: "Saya seorang programmer X" (X = C, C ++, Java, dll.)

Cukup gunakan "Saya seorang programmer".

Seorang programmer memecahkan masalah dan merancang algoritma dengan menginstruksikan mesin untuk melakukan beban kerja. Akhir dari cerita. Ini tidak relevan dengan bahasa. Keterampilan Anda yang paling penting adalah pemecahan masalah dan pemecahan logis masalah terstruktur, keterampilan bahasa / pilihan SELALU sekunder dan / atau konsekuensi dari sifat masalah.

Jalur yang menarik jika Anda tertarik pada C adalah memperluas keterampilan Anda dengan Go. Go benar-benar merupakan peningkatan C, dengan pengumpulan dan antarmuka sampah, serta model / saluran threading bawaan yang bagus, yang juga membawa banyak manfaat C (seperti aritmatika pointer dan kompilasi ke kode mesin).

Richard Tyregrim
sumber
0

Itu tergantung pada apa yang ingin Anda lakukan dengannya. C dirancang sebagai pengganti bahasa rakitan dan merupakan bahasa tingkat tinggi yang paling dekat dengan bahasa mesin. Dengan demikian memiliki overhead dan ukuran yang rendah dalam kinerja dan cocok untuk pemrograman sistem dan tugas-tugas lain yang memerlukan jejak kecil dan mendekati perangkat keras yang mendasarinya.

Jonathan Rosenne
sumber
0

Ketika Anda bekerja pada tingkat bit dan byte, memori sebagai kumpulan data homogen mentah, seperti yang sering diperlukan untuk secara efektif mengimplementasikan pengalokasi dan struktur data yang paling efisien, tidak ada keamanan yang bisa didapat. Keselamatan didominasi konsep tipe data yang kuat, dan pengalokasi memori tidak bekerja dengan tipe data. Ia bekerja dengan bit dan byte untuk menyatukan dengan bit dan byte yang sama berpotensi mewakili satu tipe data satu saat dan yang lain nanti.

Tidak masalah jika Anda menggunakan C ++ dalam kasus itu. Anda masih akan menaburkan static_castsseluruh kode untuk membuang dari void*pointer dan masih bekerja dengan bit dan byte dan hanya berurusan dengan lebih banyak kerepotan terkait dengan menghormati sistem tipe dalam konteks ini daripada C yang memiliki sistem tipe yang jauh lebih sederhana di mana Anda bebas untuk memcpybit dan byte di sekitar tanpa khawatir tentang melibas sistem tipe.

Bahkan seringkali lebih sulit untuk bekerja di C ++, bahasa yang lebih aman secara keseluruhan, dalam konteks bit dan byte tingkat rendah tanpa menulis kode yang bahkan lebih berbahaya daripada yang Anda lakukan di C, karena Anda bisa melakukan buldoser pada sistem tipe C ++ dan melakukan hal-hal seperti menimpa vptrs dan gagal memunculkan copy constructor dan destructor pada waktu yang tepat. Jika Anda mengambil waktu yang tepat untuk menghormati jenis-jenis ini dan menggunakan penempatan yang baru dan secara manual memanggil para pengawas dan sebagainya, Anda kemudian akan terpapar ke dunia penanganan-pengecualian dalam konteks yang terlalu rendah untuk RAII menjadi praktis, dan mencapai pengecualian- keamanan dalam konteks tingkat rendah seperti itu sangat sulit (Anda harus berpura-pura seperti fungsi apa pun dapat melempar dan menangkap semua kemungkinan dan memutar balik semua efek samping sebagai transaksi yang tidak dapat dibagi seolah-olah tidak terjadi apa-apa). Kode C sering dapat "

Dan mustahil untuk menerapkan pengalokasi semacam itu dalam bahasa yang tidak memungkinkan Anda untuk menjadi "berbahaya" di sini; Anda harus bersandar pada pengalokasi apa pun yang mereka berikan (diimplementasikan paling mungkin dalam C atau C ++) dan berharap itu cukup baik untuk tujuan Anda. Dan hampir selalu ada yang lebih efisien tetapi lebih sedikit pengalokasi umum dan struktur data yang cocok untuk tujuan spesifik Anda, tetapi jauh lebih sempit karena mereka secara khusus dirancang untuk tujuan Anda.

Kebanyakan orang tidak memerlukan suka C atau C ++ karena mereka hanya bisa memanggil kode yang awalnya diimplementasikan dalam C atau C ++ atau bahkan mungkin perakitan sudah diterapkan untuk mereka. Banyak yang mungkin mendapat manfaat dari berinovasi di tingkat tinggi, seperti merangkai bersama sebuah program gambar yang hanya menggunakan pustaka dari fungsi pemrosesan gambar yang sudah diterapkan di C di mana mereka tidak terlalu banyak berinovasi pada tingkat terendah perulangan melalui piksel individu, tapi mungkin menawarkan antarmuka pengguna yang sangat ramah dan alur kerja yang belum pernah terlihat sebelumnya. Dalam hal ini, jika titik dari perangkat lunak hanya untuk membuat panggilan tingkat tinggi menjadi pustaka tingkat rendah ( "proses seluruh gambar ini untuk saya, bukan untuk setiap piksel, lakukan sesuatu" ), maka itu bisa dibilang menjadi optimasi prematur bahkan mencoba untuk mulai menulis aplikasi seperti itu di C.

Tetapi jika Anda melakukan sesuatu yang baru di tingkat rendah di mana itu membantu untuk mengakses data dengan cara tingkat rendah seperti filter gambar baru yang belum pernah dilihat sebelumnya yang cukup cepat untuk bekerja pada video HD secara realtime, maka Anda umumnya harus mendapatkan sedikit berbahaya.

Sangat mudah untuk menerima hal ini begitu saja. Saya ingat posting Facebook dengan seseorang yang menunjukkan bagaimana layak untuk membuat video game 3D dengan Python dengan implikasi bahwa bahasa tingkat rendah menjadi usang, dan itu tentu saja merupakan permainan yang tampak layak. Tapi Python membuat panggilan tingkat tinggi ke perpustakaan diimplementasikan dalam C untuk melakukan semua pekerjaan berat. Anda tidak dapat membuat Unreal Engine 4 hanya dengan melakukan panggilan tingkat tinggi ke perpustakaan yang ada. Unreal Engine 4 adalahPerpustakaan. Ia melakukan segala macam hal yang tidak pernah ada di perpustakaan dan mesin lain mulai dari pencahayaan hingga bahkan sistem cetak biru nodal dan bagaimana ia dapat menyusun dan menjalankan kode dengan cepat. Jika Anda ingin berinovasi di level mesin rendah / inti / kernel, maka Anda harus mendapatkan level rendah. Jika semua pengembang game beralih ke bahasa aman tingkat tinggi, tidak akan ada Unreal Engine 5, atau 6, atau 7. Kemungkinan orang masih menggunakan Unreal Engine 4 dekade kemudian karena Anda tidak dapat berinovasi pada level yang diperlukan untuk datang keluar dengan mesin generasi berikutnya dengan hanya melakukan panggilan tingkat tinggi ke yang lama.


sumber