Apakah C ++ cocok untuk embedded system?


168

Pertanyaan umum, di sini dan di tempat lain. Apakah C ++ cocok untuk embedded system?

Mikrokontroler? RTOS? Pemanggang roti? PC Tertanam?

Apakah OOP bermanfaat pada mikrokontroler?

Apakah C ++ menghapus programmer terlalu jauh dari perangkat keras untuk menjadi efisien?

Haruskah Arduino C ++ (tanpa manajemen memori dinamis, templat, pengecualian) dianggap sebagai "nyata C ++"?

(Semoga wiki ini akan berfungsi sebagai tempat untuk mengandung potensi perang suci ini)


5
Pertanyaan cepat: ketika Anda mengatakan tertanam , maksud Anda mikrokontroler? mikroprosesor? embedded x86 / embedded PC?
J. Polfer

1
Saya tidak bermaksud menyebabkan perang suci; maksudnya adalah untuk mempelajari apa argumen Anda yang menentangnya.
J. Polfer

2
Itu muncul dalam beberapa pertanyaan sebelumnya, jadi saya pikir tempat sentral akan baik.
Toby Jaffey

4
C ++ vs tertanam adalah topik yang kontroversial. Saya memiliki pendapat yang kuat, tetapi saya pikir itu tidak adil untuk mengajukan pertanyaan dan bermain di poin penilaian. Saya berharap bahwa komunitas wiki akan membuat diskusi yang lebih seimbang.
Toby Jaffey

13
Ini adalah pertanyaan buruk karena "disematkan" adalah atribut yang tidak berarti dalam memutuskan apakah bahasa tertentu dan bagasi terkaitnya cocok. Intinya adalah sistem kecil versus besar, di mana sistem kecil tidak menjalankan OS, memiliki memori terbatas, mungkin tidak von-Neuman, mungkin memiliki berbagai pembatasan perangkat keras pada tumpukan panggilan, tumpukan data, Anda tidak bisa hanya secara dinamis mengalokasikan Mb atau bahkan kb, dll. Kebanyakan mikrokontroler adalah sistem "kecil". Komputer papan tunggal biasanya tertanam, tetapi umumnya sistem "besar".
Olin Lathrop

Jawaban:


135

Ya, C ++ masih berguna dalam sistem embedded. Seperti orang lain katakan, itu masih tergantung pada sistem itu sendiri, seperti 8-bit UC mungkin akan menjadi tidak-tidak dalam buku saya meskipun ada kompiler di luar sana dan beberapa orang melakukannya (bergidik). Masih ada keuntungan menggunakan C ++ bahkan ketika Anda menurunkannya ke sesuatu seperti "C +" bahkan di dunia mikro 8-bit. Apa yang saya maksud dengan "C +"? Maksud saya jangan gunakan baru / hapus, hindari pengecualian, hindari kelas virtual dengan pewarisan, mungkin hindari pewarisan bersama-sama, berhati-hatilah dengan templat, gunakan fungsi sebaris alih-alih makro, dan gunakan constvariabel sebagai ganti #defines.

Saya telah bekerja baik di C dan C ++ dalam sistem tertanam selama lebih dari satu dekade sekarang, dan beberapa antusiasme muda saya untuk C ++ telah hilang karena beberapa masalah dunia nyata yang mengguncang kenaifan seseorang. Saya telah melihat yang terburuk dari C ++ dalam sistem tertanam yang saya ingin sebut sebagai "programmer CS menjadi liar di dunia EE." Bahkan, itu adalah sesuatu yang saya kerjakan dengan klien saya untuk meningkatkan basis kode yang mereka miliki antara lain.

Bahaya C ++ adalah karena ini adalah alat yang sangat sangat kuat seperti pedang bermata dua yang dapat memotong lengan dan kaki Anda jika tidak dididik dan didisiplinkan dengan baik dalam bahasa dan pemrograman umum itu sendiri. C lebih seperti pedang bermata tunggal, tetapi masih sama tajamnya. Dengan C ++ terlalu mudah untuk mendapatkan abstraksi tingkat tinggi dan membuat antarmuka yang tidak jelas yang menjadi tidak berarti dalam jangka panjang, dan itu sebagian karena fleksibilitas C ++ dalam memecahkan masalah yang sama dengan banyak fitur bahasa yang berbeda (template, OOP, prosedural, Template RTTI, OOP +, kelebihan beban, inlining).

Saya menyelesaikan dua seminar 4 jam tentang Perangkat Lunak Tertanam di C ++ oleh guru C ++, Scott Meyers. Dia menunjukkan beberapa hal tentang template yang tidak pernah saya pertimbangkan sebelumnya dan berapa banyak lagi yang dapat membantu menciptakan kode keamanan-kritis. Intinya adalah, Anda tidak dapat memiliki kode mati dalam perangkat lunak yang harus memenuhi persyaratan kode keamanan yang ketat. Templat dapat membantu Anda mencapai hal ini, karena kompilator hanya membuat kode yang dibutuhkan saat membuat template. Namun, seseorang harus menjadi lebih terdidik dalam penggunaannya untuk merancang dengan benar untuk fitur ini yang lebih sulit untuk dicapai dalam C karena linker tidak selalu mengoptimalkan kode mati.

Scott Meyers adalah pendukung yang sangat besar pada template dan penggunaan inlining yang bijaksana, dan saya harus mengatakan saya masih skeptis tentang menjadi gung ho tentang template. Saya cenderung menghindar dari mereka, meskipun dia mengatakan mereka hanya boleh diterapkan di mana mereka menjadi alat terbaik. Ia juga menyatakan bahwa C ++ memberi Anda alat untuk membuat antarmuka yang benar-benar bagus yang mudah digunakan dan membuatnya sulit digunakan. Sekali lagi, itu bagian yang sulit. Seseorang harus mencapai tingkat penguasaan dalam C ++ sebelum Anda bisa tahu bagaimana menerapkan fitur-fitur ini dengan cara yang paling efisien untuk menjadi solusi desain terbaik.

Hal yang sama berlaku untuk OOP. Di dunia yang disematkan, Anda harus membiasakan diri dengan jenis kode yang akan dimuntahkan kompiler untuk mengetahui apakah Anda dapat menangani biaya run-time polimorfisme run-time. Anda harus mau melakukan pengukuran juga untuk membuktikan bahwa desain Anda akan memenuhi persyaratan tenggat waktu Anda. Apakah kelas InterruptManager yang baru akan membuat latensi interupsi saya terlalu lama? Ada bentuk-bentuk polimorfisme lain yang mungkin lebih sesuai dengan masalah Anda seperti polimorfisme tautan-waktu yang dapat dilakukan C juga, tetapi C ++ dapat dilakukan melalui pola desain Pimpl (penunjuk buram) .

Saya mengatakan bahwa semua untuk mengatakan, bahwa C ++ memiliki tempatnya di dunia tertanam. Anda bisa membenci itu semua yang Anda inginkan, tetapi itu tidak hilang. Ini dapat ditulis dengan cara yang sangat efisien, tetapi lebih sulit untuk belajar bagaimana melakukannya dengan benar daripada dengan C. Kadang-kadang dapat bekerja lebih baik daripada C dalam memecahkan masalah dan kadang-kadang mengekspresikan antarmuka yang lebih baik, tetapi sekali lagi, Anda harus mendidik diri sendiri dan jangan takut untuk belajar caranya.


1
Ini sejalan dengan apa yang saya baca dari konsultan sistem tertanam lainnya. Saya selalu diajarkan bahwa dengan C, Anda memotong diri Anda dengan cara-cara kecil terus-menerus, tetapi bug dalam C ++ akan menjadi lebih jarang, tetapi ketika Anda mengacaukan Anda akan kehilangan kaki. Terima kasih telah menulis respons yang jelas dengan beberapa keahlian yang tidak saya miliki.
Kortuk

3
Pada catatan jurusan Ilmu Komputer menjadi gila di tanah EE. Di pekerjaan saya, potongan kode terburuk yang kami miliki ditulis oleh mayor CS. Kami menghabiskan selamanya mencoba untuk mengajarinya apa perangkat keras itu. Dia membuat sistem terstruktur menggunakan UML dan membangun seluruh sistem berdasarkan itu di java menggunakan pewarisan yang tepat dan sebagainya. Itu bekerja, sampai ada yang berubah, dan itu adalah pekerjaan tambalan yang buruk untuk menambahkan fitur, atau mendesain ulang sepenuhnya. Kode ini hampir tidak dapat digunakan karena seberapa teliti dia mengaburkan semuanya dengan warisan.
Kortuk

2
Bukan hanya bug yang menggigit Anda, tetapi kode yang tidak dapat dipelihara juga akan menggigit Anda. Tentu, ketika Anda memulai proyek itu menggunakan fitur-fitur C ++ yang rapi semuanya berjalan lancar, tetapi setelah 2 atau 3 tahun entropi muncul jika tidak ada upaya serius yang dimasukkan ke dalam refactoring saat Anda berkembang. Itulah yang saya hadapi saat ini..kode membusuk lebih cepat dari waktu ke waktu di C ++.
Jay Atkinson

2
UML dan statemachine. Anda benar-benar perlu melihat barang-barang Miro Samek di state-machine.com . Dia membangun sistem yang efisien yang mudah untuk di refactor dan diubah, tetapi butuh waktu untuk mengatasinya.
Jay Atkinson

2
Ini benar-benar tergantung pada sistem Anda dan berapa banyak memori yang Anda miliki. Apakah Anda menulis kode pada mikro 8-bit dengan RAM yang sangat sedikit? Maka Anda mungkin lebih baik menghindari menjadi gila pada antarmuka abstrak. Jika Anda menulis sesuatu seperti sistem tertanam 32-bit dengan lempengan memori, lakukanlah. Anda benar-benar harus mempertimbangkannya. Misalnya, setiap kali Anda menempelkan dunia "virtual" pada kelas itu, Anda mendapatkan pointer tambahan, yang bisa 8-bit, 16 bit atau 32 bit tergantung pada sistem, untuk setiap instance Anda mendeklarasikan objek itu. Anda bahkan tidak akan menyadari, dan teman,
Jay Atkinson

56

C ++ sangat cocok untuk embedded system. Sekarang saya menggunakan ada / tidaknya alat pengembangan yang baik (atau ketiadaannya) sebagai kriteria utama saya untuk menggunakan mikroprosesor tertentu atau tidak.

Area C ++ yang baik untuk digunakan pada sistem embedded karena mereka memiliki biaya sumber daya yang rendah:

  • modularitas dibawa oleh penggunaan kelas / struktur
  • Templat jika kompiler melakukan pekerjaan yang baik untuk mengkompilasinya secara efisien. Templat adalah alat yang baik untuk membawa penggunaan kembali algoritma ke berbagai tipe data.

Area OK:

  • fungsi virtual - saya dulu menentang ini, tetapi biaya sumber daya sangat kecil (satu vtable per kelas , bukan per objek; satu pointer ke vtable per objek; satu operasi dereferencing per panggilan fungsi virtual) dan keuntungan besar dari ini adalah memungkinkan Anda memiliki array yang berisi beberapa jenis objek tanpa harus tahu jenisnya. Saya menggunakan ini baru-baru ini untuk memiliki berbagai objek yang masing-masing mewakili perangkat I2C, masing-masing dengan metode terpisah.

Area yang tidak digunakan, sebagian besar karena overhead run-time yang tidak dapat diterima pada sistem kecil:

  • alokasi memori dinamis - yang lain telah menyebutkan ini, tetapi alasan penting lainnya untuk tidak menggunakan alokasi memori dinamis adalah bahwa hal itu mewakili ketidakpastian dalam waktu; banyak alasan untuk menggunakan sistem embedded adalah untuk aplikasi waktu nyata.
  • RTTI (run type type information) - biaya memori agak besar
  • pengecualian - pasti tidak-tidak, karena kecepatan eksekusi yang terjadi

Terima kasih atas masukannya. Menarik dan sangat mirip dengan apa yang saya baca.
Kortuk

1
Sebenarnya alokasi memori dinamis baik-baik saja, dan kadang-kadang tidak dapat dihindari. Ini adalah alokasi memori dinamis (dan penggunaan kembali berikutnya) yang menjadi masalah. RTTI adalah memori babi, saya setuju itu. Tapi apa masalahnya dengan pengecualian?
Wouter van Ooijen

1
@WoutervanOoijen: Masalah dengan pengecualian adalah bahwa jika foopanggilan bardalam blok try/ catch, dan barmembuat beberapa objek dan panggilan boz, yang melempar pengecualian, sistem harus entah bagaimana memanggil destruktor untuk objek yang bardibuat sebelum mengembalikan kontrol ke foo. Kecuali pengecualian benar-benar dinonaktifkan, tidak barakan memiliki cara untuk mengetahui apakah bozmungkin melempar, dan karenanya harus menyertakan kode tambahan untuk memungkinkan kemungkinan itu. Saya ingin melihat variasi C ++ dengan "pengecualian yang diperiksa" untuk menghadapinya; jika rutinitas yang dapat memungkinkan pengecualian untuk melarikan diri ...
supercat

1
... harus dideklarasikan seperti itu, maka hanya akan diperlukan bagi kompiler untuk memasukkan kode penanganan pengecualian dalam penelepon dari rutinitas tersebut. Yang pasti, harus menambahkan semua deklarasi yang diperlukan, sambil berharap menghindari yang tidak perlu, akan agak membebani, tetapi itu akan memungkinkan pengecualian untuk digunakan di tempat-tempat di mana mereka berguna, tanpa menambahkan overhead di mana mereka tidak.
supercat

3
@WoutervanOoijen: Kebetulan, jika saya mendesain ABI untuk penanganan pengecualian pada ARM, saya akan menentukan kode yang memanggil rutin yang dapat keluar melalui pengecualian harus memiliki R14 menunjuk ke alamat dua byte sebelum alamat pengirim yang diinginkan (ini akan muncul secara alami jika penelepon mengikuti instruksi PANGGILAN dengan kata 16-bit). Rutin yang dipanggil kemudian akan keluar secara normal melalui add r15,r14,#2bukan mov r15,r14; untuk keluar melalui pengecualian ldrhs r0,[r14] / add r15,r14,r0,. Biaya nol siklus untuk keluar normal, dan tidak ada batasan stack-frame.
supercat

36

Ya, C ++ tentu cocok untuk sistem embedded. Pertama mari kita jelaskan beberapa kesalahpahaman tentang perbedaan antara C dan C ++:

Dalam mikro tertanam, Anda akan selalu perlu menggunakan bahasa tingkat tinggi dengan hati-hati jika Anda khawatir tentang kendala waktu atau ruang. Sebagai contoh, banyak MCU tidak menangani pointer dengan baik, sehingga sangat tidak efisien ketika menggunakan stack. Ini berarti Anda harus berhati-hati tentang meneruskan variabel ke fungsi, menggunakan array dan pointer, dan rekursi. Garis C sederhana seperti:

a[i] = b[j] * c[k];

dapat menghasilkan sekitar 4 halaman instruksi tergantung pada sifat variabel-variabel tersebut.

Setiap kali Anda menggunakan setiap bahasa tingkat tinggi, dan Anda khawatir tentang waktu dan ruang kendala, maka Anda perlu mengetahui bagaimana setiap fitur bahasa yang diterjemahkan ke dalam instruksi mesin pada MCU Anda (setidaknya, setiap fitur yang Anda gunakan). Ini berlaku untuk C, C ++, Ada, apa pun. Mungkin semua bahasa akan berisi fitur yang tidak diterjemahkan secara efisien pada MCU kecil. Selalu periksa daftar pembongkaran untuk memastikan kompiler tidak menghasilkan rim instruksi untuk sesuatu yang sepele.

Apakah C cocok untuk MCU tertanam? Ya, selama Anda mengawasi kode yang dihasilkan.
Apakah C ++ cocok untuk MCU tertanam? Ya, selama Anda mengawasi kode yang dihasilkan.

Inilah mengapa saya berpikir bahwa C ++ lebih baik daripada C bahkan pada MCU 8-bit: C ++ memberikan peningkatan dukungan untuk:

  • Menyembunyikan data
  • Mengetik / memeriksa lebih kuat
  • Transparansi multi-perangkat menggunakan kelas
  • Template (seperti biasa jika digunakan dengan hati-hati)
  • Daftar inisialisasi
  • const

Tidak satu pun dari fitur ini yang lebih berat daripada fitur khas C.

Ketika Anda naik ke 16 atau 32 bit MCU, maka mulai masuk akal untuk menggunakan fitur C yang lebih berat (stack, heap, pointer, array, printf, dll.) Dengan cara yang sama, pada MCU yang lebih kuat menjadi tepat. untuk menggunakan fitur C ++ yang lebih berat (tumpukan, tumpukan, referensi, STL, baru / hapus).

Jadi, tidak perlu ngeri membayangkan C ++ pada PIC16. Jika Anda tahu bahasa Anda dan MCU Anda dengan benar, maka Anda akan tahu bagaimana menggunakannya secara efektif bersama-sama.


3
Ini adalah jawaban yang diungkapkan dengan sangat baik dan masuk akal untuk pertanyaan itu. +1 Ceria!
vicatcu

1
" a[i] = b[j] * c[k];dapat menghasilkan sekitar 4 halaman instruksi tergantung pada sifat dari variabel-variabel itu." Jika MCU / kompiler Anda melakukan ini, itu karena Anda menggunakan beberapa CPU hobi garasi dari tahun 80-an.
Lundin

@Lundin - Sigh. Tidak, itu berarti Anda menggunakan MCU kecil murah yang dirancang untuk menjadi sekecil dan semurah mungkin, untuk tidak memiliki hal-hal rumit seperti pengindeksan tumpukan.
Rocketmagnet

2
@ Rocketagnet Ok mungkin di tahun 1990-an? Saat ini 8 pahit jelek datang dengan harga yang sama dengan 32 pahit. Hanya alasan yang tersisa untuk memilih yang pertama adalah konsumsi saat ini. Dan mengenai 8-pahit ekstra-jelek tanpa tumpukan: jika Anda menulis C bukan assembler untuk MCU terbatas seperti itu, Anda mungkin melakukan kesalahan. 4 halaman yang dihasilkan adalah kesalahan Anda sendiri untuk menulis program yang terlalu rumit untuk CPU, dan pada dasarnya C adalah alat yang salah untuk tugas tersebut. (Saya telah melakukan ini di masa lalu di Freescale RS08, itu adalah ide yang sangat bodoh.)
Lundin

@Lundin prosesor 32-bit tidak diperlukan lebih cepat dari 16-bit. Ini adalah bukti jalan kembali pada hari ketika transisi program 16-ke-32bit sedang terjadi di dunia PC.
Barleyman

24

Saya selalu menemukan debat yang menghibur untuk dibaca. Tidak begitu banyak untuk diskusi intelektual tentang pro dan kontra dari berbagai bahasa yang tersedia tetapi karena Anda biasanya dapat mematok sikap seseorang pada topik berdasarkan pekerjaan / pengalaman / bidang minat mereka. Itu tepat di sana dengan argumen "optimasi prematur" adalah jurusan CS dan programer pemeliharaan mengutip Knuth kiri dan kanan dan mereka yang bekerja di dunia nyata di mana masalah kinerja berpikir mereka semua gila (saya anggota grup terakhir) untuk bersikap adil).

Pada akhirnya, Anda dapat mengembangkan perangkat lunak yang sangat baik dalam C atau C ++ atau memasukkan bahasa di sini . Itu datang ke kemampuan pengembang bukan bahasa. Menjadi ahli dalam suatu bahasa biasanya hanya diperlukan jika Anda telah memilih bahasa yang salah untuk memulai dan sekarang perlu membengkokkannya untuk menyelesaikan masalah Anda, dalam kebanyakan kasus ini adalah satu-satunya situasi di mana Anda perlu menyelam ke fitur yang tidak jelas atau kompiler trik untuk mencapai tujuan.

Saya sering mendengar orang memulai argumen ini sebagai "Saya seorang ahli dalam bahasa X dan bla bla" Jujur saya segera mendiskreditkan orang-orang ini karena, menurut pendapat saya, mereka sudah mendekati masalah dari sudut yang salah dan semuanya setelah itu ternoda oleh keinginan mereka untuk menggunakan alat mereka untuk memecahkan masalah dan menunjukkan betapa 'kerennya itu'.

Saya sering melihat pengembang memilih alat yang ditetapkan terlebih dahulu dan berusaha membengkokkannya ke masalah mereka yang kedua, yang sepenuhnya salah dan menghasilkan solusi omong kosong.

Seperti yang saya sebutkan dalam komentar untuk jawaban lain, perang bahasa ini sering beralih ke argumen bahwa bahasa X memungkinkan programmer untuk melakukan lebih banyak hal bodoh. Sambil menghibur untuk membaca, semua pernyataan ini benar-benar berarti bahwa Anda memiliki masalah dalam merekrut pengembang yang baik dan perlu untuk mengatasi masalah itu secara langsung daripada mencoba untuk membantu situasi dengan terus merekrut pengembang yang buruk dan memilih alat sehingga mereka dapat melakukan sedikit Kerusakan mungkin.

Menurut pendapat saya pengembang yang baik, baik itu pengembangan perangkat lunak atau perangkat keras, riset masalah, arsitek solusi dan temukan alat yang memungkinkan mereka mengekspresikan solusi dengan 'cara terbaik'. Seharusnya tidak masalah jika alat yang diperlukan adalah sesuatu yang belum pernah Anda gunakan sebelumnya, setelah Anda menggunakan 3-4 bahasa / alat pengembangan untuk proyek mengambil yang baru harus memiliki dampak minimal pada waktu pengembangan Anda.

Tentu saja, 'cara terbaik' adalah istilah subyektif dan juga perlu didefinisikan dalam fase penelitian. Orang perlu mempertimbangkan banyak masalah: kinerja, kemudahan berekspresi, kepadatan kode, dll berdasarkan masalah yang dihadapi. Saya tidak memasukkan perawatan dalam daftar itu karena suatu alasan, saya tidak peduli bahasa apa yang Anda pilih, jika Anda memilih alat yang tepat dan meluangkan waktu untuk memahami masalah ini harusnya 'gratis'. Sulit untuk mempertahankan kode sering merupakan hasil dari memilih alat yang salah atau struktur sistem yang buruk, ini mengakibatkan kekacauan yang jelek untuk membuatnya berfungsi.

Mengklaim bahasa apa pun 'lebih baik' daripada yang lain adalah konyol tanpa mendefinisikan masalah minat tertentu. Pendekatan berorientasi objek tidak selalu lebih baik dari pendekatan fungsional. Ada beberapa masalah yang cocok untuk paradigma desain berorientasi objek. Ada banyak yang tidak. Pernyataan yang sama dapat dibuat tentang banyak fitur bahasa yang tampaknya dinikmati orang-orang.

Jika Anda menghabiskan lebih dari 20% waktu Anda untuk masalah mengetik kode, Anda mungkin menghasilkan sistem yang sangat buruk, atau memiliki pengembang yang sangat buruk (atau Anda masih belajar). Anda harus menghabiskan sebagian besar waktu Anda di muka untuk membuat diagram masalah dan menentukan bagaimana berbagai bagian aplikasi berinteraksi. Menempelkan sekelompok pengembang berbakat di ruangan dengan papan penanda dan masalah untuk dipecahkan dan memberi tahu mereka bahwa mereka tidak diperbolehkan menulis kode apa pun atau memilih alat apa pun sampai mereka merasa nyaman dengan keseluruhan sistem akan berbuat lebih banyak untuk meningkatkan kualitas pengembangan keluaran dan kecepatan daripada memilih alat baru yang panas yang dijamin untuk meningkatkan waktu pengembangan. (lihat pengembangan scrum sebagai referensi untuk kebalikan dari argumen saya)

Seringkali kenyataan yang disayangkan adalah bahwa banyak bisnis hanya dapat mengukur nilai pengembang dengan jumlah baris yang ditulis, atau dengan melihat 'hasil nyata'. Mereka melihat 3 minggu di sebuah ruangan dengan papan penanda sebagai kehilangan produktivitas. Pengembang sering dipaksa untuk mempercepat melalui tahap pengembangan 'pemikiran' atau dipaksa menggunakan alat yang ditetapkan oleh beberapa masalah politik dalam perusahaan, "Saudara bos saya bekerja untuk IBM sehingga kami hanya dapat menggunakan alat mereka", sampah semacam itu . Atau lebih buruk, Anda mendapatkan serangkaian persyaratan yang terus berubah dari perusahaan karena mereka tidak mampu melakukan riset pasar yang tepat atau tidak memahami dampak perubahan pada siklus pengembangan.

Maaf karena sedikit keluar dari topik dengan kata-kata kasar ini, saya memiliki pendapat yang cukup kuat tentang topik ini.


2
Sekarang, saya tidak mengetuk tes unit pada level aplikasi (driver di atas) pada sistem embedded tertentu. Ada beberapa nilai umpan balik instan dari unit-testing dan membasmi bug di awal fase pengembangan, tetapi seluruh paradigma TDD untuk melahirkan desain menurut saya sedikit braindead. Saya lebih suka meluangkan waktu untuk "berpikir" tentang masalah dan membuat diagram baik di kepala saya, di atas kertas, atau di papan tulis, sebelum mulai kode. Saya juga berpikir TDD mendorong pasar untuk tidak melakukan penelitian awal tentang persyaratan, karena itu seharusnya membantu dengan perubahan kebutuhan yang konstan.
Jay Atkinson

2
Dan untuk memberikan catatan akhir pada komentar saya yang sangat panjang .. Kami tidak perlu ahli bahasa untuk mengerjakan desainnya. Kami membutuhkan desainer ahli yang dapat mengerjakan bahasa.
Jay Atkinson

1
PRD = dokumen persyaratan produk, MRD = dokumen persyaratan pemasaran, TRD = dokumen persyaratan teknis. TDD = Pengembangan Didorong oleh Tes.
Jay Atkinson

1
@ Mark - Saya setuju dengan sentimen desain-depan Anda, tetapi hanya sampai titik tertentu. Saya pikir desain berat di muka terbayar jika a) persyaratan Anda cukup stabil / dikenal, dan b) pengembang yang melakukan desain berpengalaman . Dalam prev. pekerjaan, saya ditugaskan untuk melakukan desain dan sangat timeboxed oleh tim saya, dan saya berpikir, "Betapa bodohnya melakukan hal ini! Desain di muka menghemat uang (lih. Buku Lengkap Kode) ??" Tetapi dalam coding saya menemukan banyak hal yang saya tidak tahu harus mencari. Jika saya telah melakukan banyak desain dan meminimalkan waktu kode, itu akan sia-sia. JME.
J. Polfer

1
@sheepsimulator Saya jelas setuju pada poin kedua, saya menganggap arsitek sistem utama adalah pengembang berpengalaman. Pada poin pertama saya sebenarnya tidak setuju. Saya pikir semakin Anda mengharapkan persyaratan untuk berubah, semakin banyak waktu yang harus Anda habiskan dalam fase desain karena Anda harus menghasilkan desain yang baik dan mudah diubah. Saya tahu beberapa filosofi mengusulkan pengembangan yang cepat. Dalam beberapa kasus ini bekerja dengan baik seperti banyak programmer yang buruk atau tidak berpengalaman pada staf. Semua filosofi desain ini datang dengan mengatakan "Saya tidak punya doa merancang sistem yang fleksibel, jadi jangan buang waktu mencoba".
Tandai

17

Bahasa apa pun bisa cocok untuk sistem tertanam. Embedded just berarti: bagian dari peralatan yang lebih besar, yang bertentangan dengan komputer yang bebas digunakan.

Pertanyaan ini memiliki relevansi lebih ketika ditanya untuk sistem ( sumber daya waktu nyata) atau sumber daya terbatas (sulit) .

Untuk sistem waktu-nyata C ++ adalah salah satu bahasa tertinggi yang masih sesuai saat pemrograman untuk batasan waktu yang ketat. Dengan pengecualian penggunaan heap (operator gratis), ia tidak memiliki konstruksi yang memiliki waktu eksekusi yang tidak ditentukan, sehingga Anda dapat menguji apakah program Anda memenuhi persyaratan waktu, dan dengan pengalaman yang lebih banyak Anda bahkan dapat memperkirakannya. Penggunaan heap tentu saja harus dihindari, meskipun operator baru masih dapat digunakan untuk alokasi satu kali. Konstruk yang ditawarkan C ++ di atas C dapat digunakan dengan baik di sistem tertanam: OO, pengecualian, templat.

Untuk sistem yang sangat terbatas sumber daya (chip 8-bit, kurang dari beberapa Kb RAM, tidak ada tumpukan yang dapat diakses) C ++ penuh mungkin tidak cocok, meskipun mungkin masih digunakan sebagai 'C yang lebih baik'.

Saya pikir sangat disayangkan bahwa Ada tampaknya hanya digunakan di beberapa ceruk. Dalam banyak hal ini adalah Pascal ++, tetapi tanpa beban untuk menjadi kompatibel dengan bahasa yang sudah berantakan sejak awal. (sunting: kekacauan yang serius tentu saja C. Pascal adalah bahasa yang indah tapi agak tidak praktis.)

================================================== ==============

EDIT: Saya sedang mengetik jawaban untuk pertanyaan baru ("Dalam kasus mana C ++ diperlukan ketika kita sedang memprogram mikrokontroler"?) Yang ditutup merujuk pada yang ini, jadi saya akan menambahkan apa yang saya tulis:

Tidak pernah ada alasan yang sepenuhnya melarang penggunaan bahasa pemrograman apa pun , tetapi mungkin ada argumen yang memiliki bobot lebih atau kurang dalam situasi tertentu. Diskusi tentang ini dapat ditemukan di banyak tempat, dengan posisi yang diambil berkisar dari "tidak pernah menggunakan C ++ untuk mikrokontroler" hingga "selalu menggunakan C ++". Saya lebih banyak dengan posisi terakhir. Saya dapat memberikan beberapa argumen, tetapi Anda harus memutuskan sendiri berapa banyak beban yang mereka bawa dalam situasi tertentu (dan ke arah mana).

  • Kompiler C ++ lebih jarang dari pada kompiler C; untuk beberapa target (misalnya 12 dan 14 bit core PIC) tidak ada kompiler C ++ sama sekali.
  • (Bagus) Pemrogram C ++ lebih jarang dari pada pemrogram C (bagus), terutama di antara mereka yang juga (agak) berpengetahuan luas dalam elektronik.
  • C ++ memiliki lebih banyak konstruksi daripada C yang tidak sesuai untuk sistem kecil (seperti pengecualian, RTTI, sering menggunakan heap).
  • C ++ memiliki seperangkat pustaka (standar) yang lebih kaya daripada C, tetapi konsekuensi dari poin sebelumnya adalah bahwa pustaka C ++ sering menggunakan fitur yang tidak sesuai untuk sistem kecil dan karenanya tidak dapat diterapkan pada sistem kecil.
  • C ++ memiliki lebih banyak konstruksi daripada C yang memungkinkan Anda menembak diri sendiri.
  • C ++ memiliki lebih banyak konstruksi daripada C yang memungkinkan Anda untuk mencegah diri Anda menembak diri sendiri (ya, IMO ini dan yang sebelumnya keduanya benar).
  • C ++ memiliki seperangkat mekanisme abstraksi yang lebih kaya, sehingga memungkinkan cara pemrograman yang lebih baik, terutama untuk perpustakaan.
  • Fitur bahasa C ++ (misalnya konstruktor / destruktor, fungsi konversi) membuatnya lebih sulit untuk melihat melalui kode untuk melihat mesin yang dihasilkan dan dengan demikian biaya dalam ruang dan waktu membangun bahasa.
  • Konstruk bahasa C ++ membuatnya kurang perlu untuk menyadari bagaimana tepatnya diterjemahkan ke kode mesin karena mereka melakukan 'hal yang benar' dengan cara yang lebih abstrak.
  • Standar bahasa C ++ berkembang dengan cepat dan diadopsi dengan cepat oleh kompiler besar (gcc, clang, microsoft). C berevolusi dengan agak menabur, dan adopsi dari beberapa fitur yang lebih baru (array varian) sangat menakutkan dan bahkan telah dikembalikan dalam standar yang lebih baru. Poin ini khususnya menarik karena orang yang berbeda menggunakannya untuk mendukung posisi yang berlawanan.
  • C ++ tidak diragukan lagi alat yang lebih tajam daripada C. Apakah Anda memercayai programmer Anda (atau diri Anda sendiri) untuk menggunakan alat seperti itu untuk membuat patung yang indah, atau apakah Anda takut mereka melukai diri mereka sendiri dan apakah Anda lebih suka menerima produk yang kurang indah tetapi berisiko lebih rendah ? (Saya ingat bahwa guru seni pahat saya pernah mengatakan kepada saya bahwa alat tumpul dalam beberapa situasi bisa lebih berbahaya daripada yang tajam.)

Blog saya memiliki beberapa tulisan tentang penggunaan C ++ pada sistem kecil (= pengendali mikro).


15

Dalam pengalaman saya, C ++ biasanya tidak cocok untuk sistem embedded kecil. Maksud saya, mikrokontroler dan perangkat tanpa OS.

Banyak teknik C ++ OOP mengandalkan alokasi memori dinamis. Ini sering hilang dalam sistem kecil.

STL dan Boost benar-benar menunjukkan kekuatan C ++, keduanya sangat besar dalam footprint.

C ++ mendorong programmer untuk mengabstraksi mesin, di mana dalam sistem terbatas itu harus dipeluk.

Tahun lalu, saya porting produk desktop remote komersial ke ponsel. Itu ditulis dalam C ++ dan dijalankan pada Windows, Linux dan OSX. Tapi, itu sangat bergantung pada pengecualian STL, memori dinamis dan C ++. Untuk menjalankannya pada WinCE, Symbian dan lingkungan tanpa OS, penulisan ulang C adalah opsi yang paling baik.


Saya setuju dengan referensi untuk sistem kecil, tetapi saya pikir kami memiliki definisi berbeda dari sistem kecil. Ketika Anda memiliki ROM 1kB dan kode C yang ditulis dengan baik mengambil semua kecuali 1 byte ROM, itu adalah sistem kecil.
Kortuk

6
Saya tidak berpendapat bahwa C tidak dapat memiliki footprint yang lebih kecil, tetapi Anda bisa menggunakan C ++ dan mendapatkan hasil yang sangat mirip untuk mendesain apa yang baru saja dibahas. Saya pikir masalahnya adalah kebanyakan programmer OOP digunakan untuk sistem dengan memori dinamis dan menggunakan konstruksi yang sangat tidak efisien, menghasilkan kode yang sama sekali tidak berguna untuk sistem daya yang lebih rendah.
Kortuk

4
jadi apa yang Anda katakan adalah Anda tidak ingin menggunakan C ++, Anda ingin menggunakan sesuatu antara C dan C ++ (sebut saja C +?). Dalam hal ini saya setuju, ada banyak omong kosong di C ++ orang menggunakan hanya karena tersedia, bukan karena itu optimal. Hampir semua bahasa mampu menghasilkan kode yang baik dan cepat, hanya masalah bagaimana menggunakannya. Sebagian besar perang suci atas bahasa bukan hasil dari kemampuan bahasa, tetapi argumen tentang betapa mudahnya bagi seorang idiot untuk melakukan hal-hal idiot, yang sebenarnya merupakan argumen idiot: p
Mark

2
"Kebanyakan perang suci atas bahasa bukan hasil dari kemampuan bahasa, tetapi argumen tentang betapa mudahnya bagi seorang idiot untuk melakukan hal-hal idiot, yang sebenarnya merupakan argumen idiot." Merupakan kalimat yang sangat menyenangkan. Saya perlu nama belakang Anda sehingga saya bisa mengutip yang itu.
Kortuk

1
Saya benar-benar tidak menggunakan memori dinamis di C baik. Tidak ada tempat di mana saya harus memilikinya. Dalam jangka panjang saya telah membaca bahwa itu bisa menjadi sangat sangat tersegmentasi dan mulai menimbulkan masalah. Saya perlu memiliki case yang dirancang dengan sangat jelas untuk kehabisan memori, dan saya harus dapat memantau dengan tepat berapa banyak yang tersisa.
Kortuk

11

Saya berharap dapat menambahkan lebih banyak cahaya daripada panas pada diskusi ini tentang C ++ pada sistem bare metal dan sumber daya terbatas.

Masalah dalam C ++:

  • Pengecualian khususnya merupakan masalah RAM karena "buffer darurat" yang diperlukan (di mana pengecualian kehabisan memori misalnya) dapat lebih besar dari RAM yang tersedia dan tentu saja merupakan pemborosan pada mikrokontroler. Untuk info lebih lanjut, lihat n4049 dan n4234 . Mereka harus dimatikan (yang saat ini perilaku yang tidak ditentukan jadi pastikan dan tidak pernah melempar). SG14 saat ini sedang mengerjakan cara yang lebih baik untuk melakukan ini.

  • RTTI mungkin tidak pernah sebanding dengan overhead, itu harus dimatikan

  • Membangun debug besar, meskipun ini bukan masalah dalam pengembangan desktop klasik jika debug tidak sesuai pada chip itu bisa menjadi masalah. Masalah muncul dari kode templated atau panggilan fungsi tambahan ditambahkan untuk kejelasan. Panggilan fungsi ekstra ini akan dihapus lagi oleh pengoptimal dan kejelasan atau fleksibilitas yang ditambahkan dapat menjadi keuntungan besar, namun dalam debug membangun ini bisa menjadi masalah.

  • Alokasi tumpukan. Meskipun STL memungkinkan untuk menggunakan pengalokasi khusus, ini bisa menjadi rumit bagi kebanyakan programmer. Alokasi heap bersifat non deterministik (yaitu bukan waktu nyata yang sulit) dan fragmentasi dapat menyebabkan situasi memori yang tidak terduga terjadi meskipun telah bekerja dalam pengujian. Pembukuan yang dibutuhkan oleh heap untuk melacak ruang kosong dan ukuran yang bervariasi dapat menjadi masalah dengan benda-benda kecil. Biasanya lebih baik menggunakan alokasi pool (baik dalam C dan C ++) tetapi ini bisa abnormal untuk programmer C ++ dulu hanya menggunakan heap.

  • Polimorfisme Runtime dan panggilan tidak langsung lainnya biasanya merupakan hit kinerja besar, masalahnya biasanya lebih karena pengoptimal tidak dapat melihat melalui mereka lebih dari mengambil dan melompat ke alamat yang sebenarnya. Panggilan tidak langsung harus dihindari karena alasan ini dalam C dan C ++ di mana seperti dalam C ++ mereka lebih tertanam dalam budaya (dan cukup berguna dalam domain lain).

  • interfacing implisit dengan clib bisa bermasalah. Mungkin berlawanan dengan intuisi bahwa masalah clib berada dalam kategori C ++ tetapi masalahnya muncul dari berbagi sumber daya secara implisit dalam lingkungan bersamaan (berbagi lebih eksplisit dalam C). Penggunaan implementasi newLib yang umum sering kali menyeret banyak mengasapi yang biasanya tidak diperlukan di UC, di sisi lain newLibNanno tidak reentrant sehingga akses ke sana harus diserialisasi (terlalu menyederhanakan sini). Ini juga masalah untuk C tetapi aksesnya lebih eksplisit. Sebagai aturan praktis kita harus menggunakan apa-apa dari namespace std dalam konteks ISR kecuali Anda yakin itu tidak mengakses negara di clib entah bagaimana (errorno atau heap misalnya). Ini juga penting jika Anda menggunakan utas (saya lebih suka RTC) untuk mengganti yang baru dan menghapus untuk menyinkronkan akses ke malloc dan gratis.

Kesimpulannya C ++ memiliki beberapa masalah tetapi pada dasarnya semuanya dapat diperbaiki atau dihindari.

Sekarang untuk C, di sini masalahnya adalah urutan yang lebih tinggi. Saya tidak memiliki kemampuan sintaksis dalam C untuk mengabstraksikan hal-hal sedemikian rupa sehingga saya dapat melakukan optimasi atau memeriksa invarian pada waktu kompilasi. Oleh karena itu saya tidak dapat merangkum hal-hal dengan benar sehingga pengguna tidak perlu tahu cara kerjanya untuk menggunakannya dan sebagian besar deteksi kesalahan saya dilakukan saat runtime (yang tidak hanya terlambat tetapi juga menambah biaya). Pada dasarnya satu-satunya cara untuk menjadi generik dalam C adalah melalui data, saya meneruskan string format ke printf atau scanf yang dievaluasi saat runtime misalnya. Maka sangat sulit bagi kompiler untuk membuktikan bahwa saya tidak menggunakan beberapa opsi yang secara teori dimungkinkan ketika melewati data yang tepat yang berarti potensi pembuatan kode mati dan hilangnya potensi optimisasi.

Saya tahu saya mungkin mengeluarkan shitstorm di sini tapi pengalaman saya pada mikrokontroler 32 bit adalah bahwa dalam sebuah apel dengan perbandingan apel C dan C ++ keduanya ditulis oleh para ahli (seperti dalam C ++ berpotensi sangat templated) C ++ adalah bahasa yang jauh lebih efisien segera setelah semuanya harus sama sekali generik (seperti di perpustakaan mana saja) dan mereka pada dasarnya setara dalam kasus non generik. Juga lebih mudah bagi pemula untuk memanfaatkan keahlian seorang pelaksana perpustakaan ahli dalam C ++.

Pada saat yang sama sebenarnya ada beberapa fungsi yang saya tidak dapat mengirimkan data yang salah, segera setelah input bukan int tetapi somethingsaya kebetulan menggunakan int sebagai metode representasi maka ada potensi untuk mendapatkannya salah (memberikan nilai yang tidak valid atau 'otherThing' daripada 'sesuatu'). Di C, satu-satunya metode saya memeriksa apakah pengguna salah adalah saat runtime. Dalam C ++ saya memiliki kemampuan untuk melakukan beberapa pemeriksaan, tidak semua pemeriksaan tetapi beberapa pemeriksaan pada waktu kompilasi yang gratis.

Pada akhirnya, tim C seringkali sama kuatnya dengan programmer yang paling lemah dan manfaat kode yang dihasilkan memiliki multipemain 1 atau penalti kinerja. Yang saya maksud dengan ini adalah apakah itu kinerja tinggi untuk satu dan hanya satu pekerjaan unik dalam lingkungan yang unik dari keputusan desain yang unik atau cukup umum untuk digunakan dalam berbagai lingkungan (mikrokontroler lain, strategi manajemen memori lain, latensi lain vs. tradeput trade off dll. dll) tetapi memiliki biaya kinerja yang melekat.

Dalam C ++ hal-hal dapat dirangkum oleh para ahli dan digunakan di banyak lingkungan di mana kompilasi pembuatan kode waktu beradaptasi dengan tugas spesifik dan pengecekan statis membuat pengguna tidak melakukan hal-hal bodoh dengan biaya nol. Di sini kita memiliki jauh lebih sedikit pertukaran antara menjadi generik dan menjadi cepat dan dengan demikian akhirnya dari sudut pandang biaya vs manfaat adalah bahasa yang lebih berkinerja, lebih aman dan lebih produktif.

Ini adalah kritik yang valid bahwa masih ada kekurangan besar pustaka C ++ yang bagus untuk disematkan, ini dapat mengarah pada keputusan pragmatis untuk menggunakan sebagian besar C pada kompiler C ++. Keputusan untuk menggunakan hanya C dalam suatu proyek pada dasarnya baik didorong secara ideologis, karena kebutuhan akan dukungan warisan atau pengakuan bahwa tim tidak cukup disiplin untuk menahan diri dari serangkaian hal-hal bodoh yang sangat dipilih yang dapat dilakukan seseorang dalam C ++ tetapi tidak dalam C dan pada saat yang sama cukup disiplin untuk tidak melakukan hal-hal bodoh yang jauh lebih besar yang tidak dapat dijaga oleh seseorang di C tetapi bisa di C ++.


Tambahan yang bagus untuk jawaban saya :) Siapa yang akan menjadi kekasih misterius C ++ ini? Profilnya menyatakan "Rupanya, pengguna ini lebih memilih untuk menjaga suasana misteri tentang mereka." (bahasa Inggris yang buruk, BTW) TAPI AHA lokasi adalah "Bochum, Jerman" ..... Sampai jumpa di konferensi!
Wouter van Ooijen

Ah ya memperbarui profil saya;) senang mengetahui kedatangan Anda ke emBO ++ itu akan menjadi kerumunan yang baik
odinthenerd

10

Latar belakang saya: baru keluar dari pelatihan sekolah di bawah programmer Bell Labs; telah bekerja selama 3 tahun, 2 di proyek penelitian sarjana; akuisisi data / kontrol proses di VB.NET. Menghabiskan 1,5 tahun melakukan pekerjaan pada aplikasi database perusahaan di VB6. Saat ini sedang mengerjakan proyek untuk PC tertanam dengan penyimpanan 2GB, RAM 512MB, CPU 500MHz x86; beberapa aplikasi berjalan secara bersamaan ditulis dalam C ++ dengan mekanisme IPC di antaranya. Ya saya masih muda.

Pendapat saya: Saya pikir C ++ dapat bekerja secara efektif mengingat lingkungan yang saya tulis di atas . Memang, kinerja real-time yang sulit bukanlah persyaratan untuk aplikasi yang saya gunakan, dan dalam beberapa aplikasi yang disematkan, itu bisa menjadi masalah. Tapi inilah hal-hal yang saya pelajari:

  • C ++ pada dasarnya berbeda dari C (yaitu, tidak ada C / C ++). Sementara semua yang valid C adalah valid C ++, C ++ adalah bahasa yang sangat berbeda dan orang perlu belajar bagaimana memprogram dalam C ++, bukan C, untuk menggunakannya secara efektif dalam situasi apa pun . Dalam C ++, Anda perlu memprogram berorientasi objek, tidak secara prosedural, dan bukan hibrida dari keduanya (kelas besar dengan banyak fungsi). Secara umum, Anda harus fokus membuat kelas kecil dengan beberapa fungsi, dan menyusun semua kelas kecil menjadi solusi yang lebih besar. Salah satu rekan kerja saya menjelaskan kepada saya bahwa saya dulu memprogram secara prosedural dalam objek, yang merupakan kekacauan besar dan sulit untuk dipertahankan. Ketika saya mulai menerapkan lebih banyak teknik berorientasi objek, saya menemukan pemeliharaan / keterbacaan kode saya meningkat.

  • C ++ menyediakan fitur tambahan dalam bentuk pengembangan berorientasi objek yang dapat menyediakan cara untuk menyederhanakan kode agar lebih mudah dibaca / dipelihara . Jujur, saya tidak berpikir ada banyak cara peningkatan kinerja / efisiensi ruang dalam melakukan OOP. Tapi saya pikir OOP adalah teknik yang dapat membantu membagi masalah yang kompleks menjadi banyak bagian kecil. Dan itu bermanfaat bagi orang-orang yang mengerjakan kode, sebuah elemen dari proses ini yang tidak boleh diabaikan.

  • Banyak argumen yang menentang C ++ terutama berkaitan dengan alokasi memori dinamis. C juga memiliki masalah yang sama. Anda dapat menulis aplikasi berorientasi objek tanpa menggunakan memori dinamis, meskipun salah satu manfaat menggunakan objek adalah Anda dapat mengalokasikan hal-hal ini secara dinamis dengan cara yang mudah. Sama seperti di C, Anda harus berhati-hati tentang bagaimana mengelola data untuk mengurangi kebocoran memori, tetapi teknik RAII membuat ini lebih sederhana dalam C ++ (membuat kehancuran memori dinamis secara otomatis dengan mengenkapsulasi dalam objek). Dalam beberapa aplikasi, di mana setiap lokasi memori diperhitungkan, ini mungkin terlalu liar & sulit untuk dikelola.

SUNTING:

  • WRT pertanyaan "Arduino C ++" : Saya berpendapat bahwa C ++ tanpa manajemen memori dinamis masih bisa berguna. Anda dapat mengatur kode Anda menjadi objek, dan kemudian menempatkan objek-objek itu ke berbagai lokasi dalam aplikasi Anda, mengatur antarmuka panggilan balik, dll. Sekarang saya telah mengembangkan di C ++, saya dapat melihat banyak cara di mana aplikasi dengan semua data dialokasikan pada stack masih bisa bermanfaat dengan objek. Namun saya akui - saya tidak pernah benar-benar menulis aplikasi yang tertanam seperti itu untuk Arduino, jadi saya tidak punya bukti di balik klaim saya. Saya memiliki beberapa peluang untuk melakukan pengembangan Arduino dalam proyek yang akan datang - semoga saya dapat menguji klaim saya di sana.

2
Saya ingin mengomentari poin kedua Anda, Anda mengatakan bahwa itu membantu memecah masalah yang kompleks menjadi banyak bagian kecil dan fitur itu harus diabaikan. Ini adalah alasan yang tepat bahwa saya sangat pro-C ++. Badan penelitian yang sangat besar dalam pemrograman menunjukkan bahwa pertumbuhan linier dalam ukuran program memberikan pertumbuhan eksponensial dalam waktu pengembangan. ini mengikuti sebaliknya, jika Anda dapat membagi program dengan benar maka Anda dapat memberikan peluruhan eksponensial dalam waktu pengembangan. Sejauh ini adalah hal yang paling penting.
Kortuk

pada poin kedua Anda juga: Cukup menggunakan metodologi desain OOP tidak menghasilkan kode yang lebih terkotak. Memiliki desain dasar yang baik tidak, bagaimana seseorang mengekspresikan desain itu diserahkan kepada pengembang. OOP tidak mendefinisikan bahwa Anda memisahkan kode Anda dengan benar, itu memberikan opsi lain, dan lebih dari itu, penampilan yang Anda lakukan, tetapi, tentu saja tidak menegakkan desain yang baik, yang tergantung pada pengembang.
Tandai

Itu selalu benar. Saya belum pernah mendengar bahasa yang menerapkan desain bagus. Saya pikir kami sebagian besar menyiratkan bahwa itu adalah pekerjaan pengembang dan bahwa C ++ membuatnya mudah digunakan dan diimplementasikan secara terorganisir.
Kortuk,

@ Mark - Saya setuju. Ini merupakan proses pembelajaran bagi saya.
J. Polfer

7

Ya, masalah dengan C ++ adalah peningkatan jejak kode.

Dalam beberapa sistem Anda menghitung byte, dan dalam hal ini Anda harus menerima biaya menjalankan yang dekat dengan batas-batas sistem Anda meningkat biaya pengembangan C.

Tetapi, bahkan dalam C, untuk sistem yang dirancang dengan baik, Anda harus menyimpan segala sesuatu yang terkurung. Sistem yang dirancang dengan baik sulit, dan C ++ memberi programmer tempat untuk metode pengembangan yang sangat terstruktur dan terkontrol. Ada biaya untuk mempelajari OOP, dan jika Anda ingin beralih ke itu Anda banyak menerimanya, dan dalam banyak kasus manajemen lebih suka melanjutkan dengan C dan tidak membayar biaya, karena sulit untuk mengukur hasil dari saklar yang meningkatkan produktivitas. Anda dapat melihat artikel oleh guru sistem tertanam Jack Ganssle di sini .

Manajemen memori dinamis adalah iblis. Tidak juga, iblis adalah auto-route, manajemen memori dinamis bekerja sangat baik pada PC, tetapi Anda dapat berharap untuk me-restart PC setidaknya setiap beberapa minggu. Anda akan menemukan bahwa ketika sistem tertanam terus berjalan selama 5 tahun, manajemen memori dinamis dapat benar-benar kacau dan sebenarnya mulai gagal. Ganssle membahas hal-hal seperti tumpukan dan tumpukan di artikelnya.

Ada beberapa hal dalam C ++ yang lebih rentan menyebabkan masalah dan menggunakan banyak sumber daya, menghapus manajemen memori dinamis dan templat adalah langkah besar untuk menjaga jejak C ++ lebih dekat dengan jejak C. Ini masih C ++, Anda tidak perlu dinamis manajemen memori atau template untuk menulis C ++ yang baik. Saya tidak menyadari mereka menghapus pengecualian, saya menganggap pengecualian sebagai bagian penting dari kode saya yang saya hapus dalam rilis, tetapi gunakan sampai saat itu. Dalam pengujian lapangan saya dapat memiliki pengecualian yang menghasilkan pesan untuk memberitahu saya tentang pengecualian yang ditangkap.


1
Saya dulu setuju bahwa kode jejak adalah masalah, tetapi baru-baru ini tampaknya ukuran flash memiliki pengaruh yang sangat kecil pada harga mikrokontroler, jauh lebih sedikit daripada ukuran RAM atau jumlah pin IO.
Wouter van Ooijen

Argumen tentang memori dinamis adalah IMO yang lebih penting. Saya telah melihat sistem industri yang dapat berjalan selama berminggu-minggu tanpa henti, tetapi lapisan diagnostik (ditulis dalam C ++) akan membatasi waktu untuk memulai kembali hingga 12 jam.
Dmitry Grigoryev

6

Saya pikir ini anti-C ++ kata-kata kasar oleh Linus Torvalds menarik.

Salah satu fitur absolut terburuk dari C ++ adalah bagaimana ia membuat banyak hal sangat tergantung pada konteks - yang hanya berarti bahwa ketika Anda melihat kode, tampilan lokal jarang memberikan konteks yang cukup untuk mengetahui apa yang sedang terjadi.

Dia tidak berbicara tentang dunia sistem tertanam, tetapi pengembangan kernel Linux. Bagi saya, relevansinya berasal dari ini: C ++ memerlukan pemahaman konteks yang lebih luas, dan saya bisa belajar menggunakan seperangkat templat objek, saya tidak percaya diri untuk mengingatnya ketika saya harus memperbarui kode dalam beberapa bulan.

(Di sisi lain, saya saat ini sedang bekerja pada perangkat yang tertanam menggunakan Python (bukan C ++, tetapi menggunakan paradigma OOP yang sama) yang akan memiliki masalah itu. Dalam pertahanan saya, ini adalah sistem tertanam yang cukup kuat untuk disebut PC 10 tahun yang lalu.)


5
Kita mungkin berbeda, tetapi saya menemukan bahwa hanya dengan membuka proyek apa pun saya tidak dapat mengetahui apa yang terjadi dengan segera, tetapi jika saya tahu sesuatu tentang apa yang dilakukannya dan saya memiliki sesuatu yang dikodekan dengan baik dalam C dan sesuatu yang dikodekan dengan baik dalam C ++, C ++ selalu tampak lebih bersih. Anda masih perlu mengimplementasikan enkapsulasi untuk pengembangan yang baik di C, yang membuat C ++ sangat mudah dilakukan. Penggunaan kelas yang benar dapat membuatnya sangat jelas di mana antarmuka Anda berada, dan mereka dapat ditangani sepenuhnya melalui suatu objek.
Kortuk

Sepenuhnya menyetujui enkapsulasi dan kelas. Kelebihan dan warisan operator, tidak terlalu banyak.
pingswept

1
Haha, ya, overloading operator dapat digunakan untuk mengaburkan fungsi kode. Jika seseorang kelebihan operator, itu harus karena alasan yang jelas atau tidak dilakukan sama sekali. Warisan hanya boleh digunakan dalam kasus-kasus tertentu di mana Anda benar-benar melakukan sesuatu yang sama seperti orang tua dengan beberapa tambahan. Saya pikir saya tidak akan menggunakan setiap fungsi baik di OOP. Saya telah menggunakan keduanya, tetapi dalam sebuah sistem embedded tidak dapat memikirkan sebuah kasus jika saya mau. Sama seperti saya pikir kompiler dengan batas 80 karakter pada nama variabel harus segera dihapus.
Kortuk

2
Saya baru saja muntah di mulut memikirkan memikirkan memprogram MCU dengan Python ...
vicatcu

Anda bukan satu-satunya, tetapi jika itu bekerja dengan baik dan efisien, saya bisa memaafkan.
Kortuk

6

Saya pikir jawaban lain membuat kasus yang cukup baik untuk pro dan kontra dan faktor keputusan, jadi saya ingin meringkas dan menambahkan beberapa komentar.

Untuk mikrokontroler kecil (8-bit), tidak mungkin. Anda hanya meminta untuk melukai diri sendiri, tidak ada keuntungan dan Anda akan memberikan terlalu banyak sumber daya.

Untuk mikrokontroler kelas atas (mis. 32-bit, 10-an atau 100-an MB untuk RAM dan penyimpanan) yang memiliki OS yang layak, itu sangat oke dan, saya berani mengatakan, bahkan direkomendasikan.

Jadi pertanyaannya adalah: di mana batasnya?

Saya tidak tahu pasti, tetapi begitu saya mengembangkan sistem untuk UC 16-bit dengan 1 MB RAM & 1 MB penyimpanan di C ++, hanya untuk menyesal nanti. Ya, itu berhasil, tetapi pekerjaan ekstra yang saya miliki tidak sepadan. Saya harus membuatnya pas, memastikan hal-hal seperti pengecualian tidak akan menghasilkan kebocoran (dukungan OS + RTL cukup buggy dan tidak dapat diandalkan). Selain itu, aplikasi OO biasanya melakukan banyak alokasi kecil, dan biaya overhead untuk itu adalah mimpi buruk lain.

Mengingat pengalaman itu, saya akan menganggap untuk proyek-proyek masa depan bahwa saya akan memilih C ++ hanya dalam sistem setidaknya 16-bit, dan dengan setidaknya 16 MB untuk RAM & penyimpanan. Itu batas yang sewenang-wenang, dan mungkin akan bervariasi sesuai dengan hal-hal seperti jenis aplikasi, gaya pengkodean dan idiom, dll. Tetapi mengingat peringatan, saya akan merekomendasikan pendekatan yang sama.


2
Saya harus tidak setuju di sini, tidak ada titik tiba-tiba di mana C ++ menjadi dapat diterima karena sumber daya sistem, praktik desain yang baik dapat menjaga jejak C ++ di mana jejak C berada. Ini menghasilkan kode dengan desain OOP yang mengambil ruang yang sama. C yang ditulis dengan buruk bisa sama buruknya.
Kortuk

1
Yah, itu tergantung pada seberapa besar aplikasi Anda dan seberapa banyak Anda menggunakan fitur tertentu yang membutuhkan lebih banyak ruang (seperti templat dan pengecualian). Tapi secara pribadi saya lebih suka menggunakan C daripada harus membatasi diri ke C ++ yang terkendali. Tetapi meskipun demikian Anda akan memiliki overhead RTL yang lebih besar, metode virtual thunks, permintaan konstruktor / destruktor rantai ... efek ini dapat dikurangi dengan pengkodean yang cermat, tetapi kemudian Anda kehilangan alasan utama untuk penggunaan C ++, abstraksi dan perspektif tingkat tinggi.
fceconel

4

Ada beberapa fitur C ++ yang berguna dalam sistem embedded. Ada yang lain, seperti pengecualian, yang bisa mahal, dan yang biayanya tidak selalu jelas.

Jika saya memiliki pemabuk saya, akan ada bahasa populer yang menggabungkan yang terbaik dari kedua dunia, dan termasuk beberapa fitur yang kurang dalam kedua bahasa; beberapa vendor menyertakan beberapa fitur seperti itu, tetapi tidak ada standar. Beberapa hal yang ingin saya lihat:

  1. Penanganan pengecualian sedikit lebih seperti Java, di mana fungsi yang dapat membuang atau membocorkan pengecualian harus dinyatakan demikian. Sementara persyaratan untuk deklarasi seperti itu mungkin agak mengganggu dari perspektif pemrograman, itu akan meningkatkan kejelasan kode dalam kasus-kasus di mana fungsi dapat mengembalikan integer sewenang-wenang jika berhasil, tetapi juga mungkin gagal. Banyak platform dapat menangani ini dengan murah dalam kode dengan misalnya memiliki nilai balik dalam register dan indikasi keberhasilan / kegagalan pada flag carry.
  2. Kelebihan fungsi statis dan sebaris saja; Pemahaman saya adalah bahwa badan standar untuk C telah menghindari fungsi yang berlebihan sehingga untuk menghindari kebutuhan untuk nama mangling. Mengizinkan kelebihan fungsi statis dan sebaris hanya akan menghindari masalah itu, dan akan memberikan 99,9% manfaat kelebihan fungsi eksternal (karena file .h dapat mendefinisikan kelebihan sebaris dalam hal fungsi eksternal yang diberi nama berbeda)
  3. Kelebihan untuk nilai parameter konstan kompilasi arbitrer atau spesifik yang dapat diselesaikan waktu. Beberapa fungsi mungkin sebaris secara efisien ketika dilewatkan dengan nilai konstan, tetapi sebaris sangat buruk jika melewati variabel. Kode waktu lain yang mungkin merupakan optimasi jika suatu nilai konstan dapat menjadi pesimisasi jika tidak. Sebagai contoh:
    inline void copy_uint32s (uint32_t * dest, const uint32_t * src, __is_const int n)
    {
      jika (n <= 0) kembali;
      lain jika (n == 1) {dest [0] = src [0];}
      lain jika (n == 2) {dest [0] = src [0]; dest [1] = src [1];}
      lain jika (n == 3) {dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2];}
      lain jika (n == 4) {dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2]; dest [3] = src [3];}
      selain itu memcpy ((void *) dest, (const void *) src, n * sizeof (* src));
    }
    
    Jika 'n' dapat dievaluasi pada waktu kompilasi, kode di atas akan lebih efisien daripada panggilan untuk memcpy, tetapi jika 'n' tidak dapat dievaluasi pada waktu kompilasi, kode yang dihasilkan akan jauh lebih besar dan lebih lambat daripada kode yang hanya disebut memcpy.

Saya tahu bapak C ++ tidak terlalu tertarik pada versi khusus C ++ yang tertanam, tapi saya pikir itu bisa menawarkan beberapa perbaikan yang cukup besar daripada hanya menggunakan C.

Adakah yang tahu jika sesuatu seperti di atas dipertimbangkan untuk semua jenis standar?



@Joby Taffey: Saya kira saya mengedit posting saya untuk menghilangkan menyebutkan bahwa pembuat C ++ tidak tertarik pada subset tertanam; Saya sadar bahwa ada upaya, tetapi dengan pemahaman saya, mereka belum benar-benar sampai sejauh itu. Saya pikir akan ada penggunaan yang pasti untuk bahasa standar yang akan setuju dengan prosesor 8-bit, dan fitur seperti yang saya jelaskan di atas akan tampak berguna pada platform apa pun. Pernahkah Anda mendengar bahasa yang menawarkan hal-hal seperti # 3 di atas? Tampaknya sangat bermanfaat, tetapi saya belum pernah melihat bahasa yang menawarkannya.
supercat

"Ayah dari C ++" tidak memiliki pengalaman pemrograman sistem embedded, jadi mengapa ada yang peduli dengan pendapatnya?
Lundin

@Lundin: Fakta bahwa beberapa orang berpengaruh tampaknya peduli dengan pendapatnya tentang berbagai hal tampaknya menjadi alasan, dalam dan dari dirinya sendiri, bagi orang lain untuk melakukannya. Saya berpikir bahwa sejak saya menulis di atas, peningkatan kekuatan template mungkin telah menambah kemungkinan baru untuk kelebihan beban berdasarkan konstanta apa yang dapat diselesaikan pada waktu kompilasi, meskipun jauh lebih tidak bersih daripada jika hal seperti itu didukung sebagai kompilasi- fitur waktu (dari apa yang saya mengerti, orang akan menentukan template yang harus mencoba berbagai hal secara berurutan dan pergi dengan yang pertama yang tidak gagal ...
supercat

... tetapi itu akan membutuhkan kompiler untuk membuang sedikit usaha mengumpulkan potensi pengganti yang kemudian akan dibuang. Mampu mengatakan dengan lebih jelas, "Jika ini konstan, lakukan ini; kalau tidak, lakukan ini" tanpa "awal yang salah" akan tampak sebagai pendekatan yang lebih bersih.
supercat

3

C ++ lebih dari satu bahasa pemrograman:

a) Ini "lebih baik" C b) Ini adalah bahasa yang berorientasi objek c) Ini adalah bahasa yang memungkinkan kita untuk menulis program generik

Meskipun semua fitur ini dapat digunakan secara terpisah, hasil terbaik dicapai ketika ketiganya digunakan secara bersamaan. Meskipun demikian, jika Anda memilih untuk memilih salah satunya saja, kualitas perangkat lunak yang disematkan akan meningkat.

a) Ini "lebih baik" C

C ++ adalah bahasa yang diketik dengan kuat; lebih kuat dari C. Program Anda akan mendapat manfaat dari fitur ini.

Beberapa orang takut akan petunjuk. C ++ termasuk referensi. Fungsi kelebihan beban.

Dan layak untuk dikatakan: Tidak satu pun dari fitur ini muncul dalam program yang lebih besar atau lebih lambat.

b) Bahasa ini berorientasi pada objek

Seseorang berkata dalam posting ini bahwa mengabstraksikan mesin dalam mikrokontroler bukanlah ide yang baik. Salah! Kita semua, para insinyur yang tertanam, selalu mengabstraksi mesin, hanya dengan sintaks lain yang dari C ++. Masalah yang saya lihat dengan argumen ini adalah bahwa beberapa programmer tidak terbiasa berpikir dalam objek, dengan begitu mereka tidak melihat manfaat dari OOP.

Setiap kali Anda siap untuk menggunakan perangkat mikrokontroler, kemungkinan perangkat tersebut telah diabstraksikan untuk kami (dari Anda sendiri atau pihak ketiga) dalam bentuk driver perangkat. Seperti yang saya katakan sebelumnya, driver itu menggunakan sintax C, seperti contoh berikut menunjukkan (diambil langsung dari contoh NXP LPC1114):

/ * Pengaturan timer untuk pertandingan dan interupsi di TICKRATE_HZ * /

Chip_TIMER_Reset (LPC_TIMER32_0);

Chip_TIMER_MatchEnableInt (LPC_TIMER32_0, 1);

Chip_TIMER_SetMatch (LPC_TIMER32_0, 1, (timerFreq / TICKRATE_HZ2));

Chip_TIMER_ResetOnMatchEnable (LPC_TIMER32_0, 1);

Chip_TIMER_Enable (LPC_TIMER32_0);

Apakah Anda melihat abstraksi? Jadi, ketika menggunakan C ++ untuk tujuan yang sama, abstraksi dibawa ke tingkat berikutnya melalui mekanisme abstraksi dan enkapsulasi C ++, tanpa biaya!

c) Ini adalah bahasa yang memungkinkan kita untuk menulis program generik

Program generik dicapai melalui templat, dan templat juga tidak memiliki biaya untuk program kami.

Selain itu, polimorfisme statis dicapai dengan templat.

Metode virtual, RTTI, dan pengecualian.

Ada kompromi ketika menggunakan metode virtual: perangkat lunak yang lebih baik vs beberapa penalti dalam kinerja. Namun, ingat bahwa pengikatan dinamis kemungkinan akan diimplementasikan menggunakan tabel virtual (array pointer fungsi). Saya telah melakukan hal yang sama di C berkali-kali (bahkan secara teratur), jadi saya tidak melihat kekurangan dalam menggunakan metode virtual. Selain itu, metode virtual dalam C ++ lebih elegan.

Akhirnya, saran tentang RTTI dan pengecualian: JANGAN GUNAKAN MEREKA dalam sistem embedded. Hindari mereka sama sekali !!


2

Latar belakang saya, tertanam (mcu, pc, unix, lainnya), realtime. Keselamatan penting. Saya memperkenalkan majikan sebelumnya ke STL. Saya tidak melakukan itu lagi.

Beberapa konten Api

Apakah C ++ cocok untuk embedded system?

Ah. C ++ adalah rasa sakit untuk menulis dan rasa sakit untuk dipertahankan. C + agak baik-baik saja (jangan gunakan beberapa fitur)

C ++ di Mikrokontroler? RTOS? Pemanggang roti? PC Tertanam?

Sekali lagi saya katakan Meh. C + tidak terlalu buruk, tetapi ADA tidak terlalu menyakitkan (dan itu benar-benar mengatakan sesuatu). Jika Anda beruntung seperti saya, Anda bisa melakukan embedded Java. Akses array diperiksa dan tidak ada aritmatika pointer membuat kode yang sangat andal. Pengumpul sampah di Jawa yang disematkan bukan prioritas tertinggi, dan ada ruang lingkup memori dan penggunaan kembali objek, sehingga kode yang dirancang dengan baik dapat berjalan selamanya tanpa GC.

Apakah OOP bermanfaat pada mikrokontroler?

Tentu saja. UART adalah sebuah objek ..... DMAC adalah sebuah objek ...

Mesin Object State sangat mudah.

Apakah C ++ menghapus programmer terlalu jauh dari perangkat keras untuk menjadi efisien?

Kecuali itu PDP-11, C bukan CPU Anda. C ++ awalnya merupakan preprocessor ontop C sehingga Bjarne Stroustrup akan berhenti ditertawakan karena memiliki simulasi Simula yang lambat saat di AT&T. C ++ bukan CPU Anda.

Dapatkan MCU yang menjalankan bytecodes java. Program di Jawa. Tertawa pada teman-teman C.

Haruskah Arduino C ++ (tanpa manajemen memori dinamis, templat, pengecualian) dianggap sebagai "nyata C ++"?

Nggak. sama seperti semua kompiler C bastardised di luar sana untuk MCU.

Keempat, Embedded Java atau Embedded ADA distandarisasi (ish); yang lainnya adalah kesedihan.


2
Apakah semudah itu menemukan mikrokontroler yang mendukung Java? Saya pikir ini akan membatasi pilihan. Dan apa pengalaman Anda tentang penalti kinerja (karena di UC Anda biasanya tidak memiliki JIT)? Bagaimana dengan dampak ketidakpastian GC dalam sistem waktu nyata?
fceconel

2
MCU apa yang ada di luar sana yang mendukung Java tertanam?
J. Polfer

www.ajile.com sebagai permulaan.
Tim Williscroft

+1 untuk Ada. Ada banyak hal yang harus dilakukan dalam embedded, termasuk Arduinos.
Brian Drummond

portable java VM untuk micros yang ditulis dalam c adalah open source. dmitry.co/index.php?p=./04.Thoughts/…
Tim Williscroft

-2

Sistem tertanam dirancang untuk melakukan beberapa tugas tertentu, alih-alih menjadi komputer tujuan umum untuk banyak tugas. Sistem tertanam adalah kombinasi perangkat keras dan perangkat lunak komputer. C adalah ibu dari semua bahasa modern. Ini adalah bahasa tingkat rendah tetapi penuh daya dan menangani semua jenis perangkat keras. Jadi C / C ++ adalah pilihan optimal untuk mengembangkan perangkat lunak untuk sistem embedded, yang sangat penuh digunakan untuk setiap sistem embedded. Seperti yang kita tahu C adalah bahasa berkembang. Sistem operasi UNIX ditulis dalam bahasa C. Karena pengembangan perangkat lunak yang sukses sering kali mengenai pemilihan bahasa terbaik untuk proyek yang diberikan, sangat mengejutkan menemukan bahwa bahasa C / C ++ telah terbukti cocok untuk prosesor 8-bit dan 64-bit. ; dalam sistem dengan byte, kilobyte, dan megabita memori. C memiliki keunggulan independensi prosesor, yang memungkinkan programmer untuk berkonsentrasi pada algoritma dan aplikasi, bukan pada detail arsitektur prosesor tertentu. Namun, banyak dari keunggulan ini berlaku untuk bahasa tingkat tinggi lainnya. Tapi C / C ++ berhasil dimana banyak bahasa lain gagal?


6
Saya benar-benar tidak yakin apa ini menambah diskusi.
Dave Tweed

-3

<rant>

Saya pikir C ++ adalah bahasa yang jelek di tempat pertama. Jika Anda ingin menggunakan OOP, tulislah program Java. C ++ tidak melakukan apa pun untuk menegakkan paradigma OOP, karena akses memori langsung sepenuhnya berada dalam kekuasaan Anda untuk (ab) digunakan.

Jika Anda memiliki MCU, Anda berbicara tentang kemungkinan besar memori flash kurang dari 100kB. Anda ingin memprogram dalam bahasa yang abstraksi memori: ketika saya mendeklarasikan variabel atau array, ia mendapat memori, titik; malloc (alias kata kunci "baru" dalam C ++) harus lebih atau kurang dilarang digunakan dalam perangkat lunak yang disematkan, kecuali mungkin dalam beberapa kesempatan satu panggilan selama startup program.

Sial, ada (sering) kali dalam pemrograman tertanam di mana C tidak cukup tingkat rendah, dan Anda perlu melakukan hal-hal seperti mengalokasikan variabel ke register, dan menulis inline assembly untuk memperketat rutinitas layanan interupsi Anda (ISR). Kata kunci seperti "volatile" menjadi sangat sangat penting untuk dipahami. Anda menghabiskan banyak waktu memanipulasi memori pada level bit , bukan level objek .

Mengapa Anda ingin menipu diri sendiri dengan berpikir bahwa segala sesuatunya lebih sederhana daripada kenyataannya?

</rant>


Masalah saya di sini adalah sederhana, mengapa saya ingin mengetahui kompleksitas driver yang ditulis untuk mengendalikan USART1 jika telah dikembangkan sepenuhnya untuk menangani antarmuka.
Kortuk

1
Saya tidak memilih Anda, tetapi saya ingin menunjukkan bahwa C ++ tidak perlu menegakkan OOP, cukup berikan alat untuk melakukannya. Menegakkan standar pengkodean yang baik adalah tugas pengembang. Ini bisa membantu jika bahasa membuatnya lebih mudah, tetapi bahasa tidak akan pernah melakukannya sendiri. C dalam beberapa kasus tidak dapat dibaca.
Kortuk

1
Semua bahasa bagus untuk sesuatu. C ++ cepat. OOP, jika dilakukan dengan baik, membuatnya lebih mudah bagi banyak pengembang untuk bekerja secara paralel dan untuk mengkode yang tidak diketahui. Saya pikir inilah mengapa ia memiliki banyak daya tarik dalam pengembangan game.
Toby Jaffey

1
Ya saya setuju. Alasan saya melihatnya untuk dunia yang tertanam adalah karena banyaknya fitur dan fungsi yang ditambahkan ke banyak sistem yang berbeda yang sudah ada dan sistem baru sedang dikembangkan. Proyek menjadi lebih besar dan lebih besar. Entah kami membutuhkan waktu lebih lama untuk mengembangkannya atau kami mulai menerapkan dan memutarbalikkan apa yang telah dilakukan dunia CS pada PC.
Kortuk

5
Namun orang lain yang tidak mengerti C ++ dengan benar. Itu selalu mengherankan saya ada berapa banyak.
Rocketmagnet
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.
Judi bola <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>|