Чи підходить C ++ для вбудованих систем?


167

Поширене питання тут і деінде. Чи підходить C ++ для вбудованих систем?

Мікроконтролери? RTOS? Тостери? Вбудовані ПК?

Чи корисний OOP на мікроконтролерах?

Чи C ++ віддаляє програміста занадто далеко від обладнання, щоб бути ефективним?

Чи слід вважати C ++ Arduino (без динамічного управління пам'яттю, шаблонами, винятками) "справжнім C ++"?

(Сподіваємось, цей вікі буде служити місцем для вміщення цієї потенційної святої війни)


5
Швидке запитання: коли ви говорите вбудований , ви маєте на увазі мікроконтролер? мікропроцесор? вбудований x86 / вбудований ПК?
Дж. Полфер

1
Я не мав наміру викликати святу війну; наміром було дізнатися, які ваші аргументи були проти цього.
Дж. Полфер

2
Раніше вона виходила з декількох питань, тому я вважав, що центральне місце буде добре.
Тобі Джаффі

4
C ++ vs embedded - це спірна тема. У мене є сильна думка, але я не вважав, що було б справедливо ставити питання і грати на балах. Я сподіваюся, що вікі спільноти запропонує більш врівноважене обговорення.
Тобі Джаффі

13
Це поганий питання, оскільки "вбудований" - це безглуздий атрибут у вирішенні того, чи підходить певна мова та пов'язаний з нею багаж. Сенс у малому порівняно з великими системами, де маленькі системи не працюють з ОС, мають обмежену пам’ять, можуть не бути фон-Нейманом, можуть мати різні апаратні обмеження на стеки викликів, стеки даних, ви не можете просто динамічно виділити Мб або навіть kb і т. д. Більшість мікроконтролерів - це "малі" системи. Одноплаткові комп'ютери зазвичай вбудовані, але, як правило, "великі" системи.
Олін Латроп

Відповіді:


135

Так, C ++ все ще корисний у вбудованих системах. Як уже говорили всі, це все ще залежить від самої системи, як 8-бітний UC, ймовірно, буде ні-ні в моїй книзі, хоча там є компілятор, і деякі люди це роблять (здригаються). Є все-таки перевага в застосуванні C ++, навіть якщо ви зменшуєте його до чогось типу "C +" навіть у 8-бітовому мікросвіті. Що я маю на увазі під "C +"? Я маю на увазі не використовувати нові / видаляти, уникати винятків, уникати віртуальних класів з успадкуванням, можливо, уникати успадковування всіх разом, будьте дуже обережні з шаблонами, використовуйте вбудовані функції замість макросів та використовуйте constзмінні замість #defines.

Я працюю як в C, так і в C ++ у вбудованих системах вже більше десяти років, і деякі мої юнацькі захоплення C ++, безумовно, зношуються через деякі реальні проблеми, які потрясають наївність. Я бачив найгірший C ++ у вбудованих системах, які я б хотів назвати "програмістами CS, що розійшлися в світі EE". Насправді це те, над чим я працюю зі своїм клієнтом, щоб покращити цю кодову базу, яку вони мають серед інших.

Небезпека C ++ полягає в тому, що це дуже потужний інструмент, подібний до двозубного меча, який може відрізати і вашу руку, і ногу, якщо не буде навчений та дисциплінований належним чином мовою та загальним програмуванням. С більше схожий на однозубний меч, але все одно такий же гострий. З C ++ надто просто отримати дуже високі рівні абстрагування та створити непрозорі інтерфейси, які довгостроково стають безглуздими, і це частково пов’язано з гнучкістю C ++ у вирішенні однієї проблеми з багатьма різними мовними особливостями (шаблони, OOP, процедурні, RTTI, OOP + шаблони, перевантаження, вбудовування).

Я закінчив два 4-годинні семінари з вбудованого програмного забезпечення в C ++ гуру C ++, Скотт Майерс. Він вказав на деякі речі щодо шаблонів, які я ніколи не розглядав, і як багато іншого вони можуть допомогти створити критичний для безпеки код. Суть полягає в тому, що ви не можете мати мертвий код у програмному забезпеченні, яке повинно відповідати суворим вимогам щодо безпеки коду. Шаблони можуть допомогти вам досягти цього, оскільки компілятор створює потрібний йому код лише при інстанціюванні шаблонів. Однак, потрібно більш ретельно навчатись їх використанню для правильного проектування цієї функції, що важче здійснити в C, оскільки лінкери не завжди оптимізують мертвий код.

Скотт Майєрс є дуже великим прихильником шаблонів та розумного використання вкладених текстів, і я повинен сказати, що я все ще скептично налаштований на шанси щодо шаблонів. Я схиляюся від них ухилятися, хоча він каже, що їх слід застосовувати лише там, де вони стають найкращим інструментом. Він також зазначає, що C ++ надає вам інструменти для створення дійсно хороших інтерфейсів, які прості у користуванні правильно та ускладнюють неправильне використання. Знову ж таки, це важка частина. Потрібно досягти рівня майстерності в C ++, перш ніж ви зможете використовувати ці функції найбільш ефективно, щоб бути найкращим дизайнерським рішенням.

Те саме стосується ООП. У вбудованому світі ви повинні ознайомитись із тим, який код збирається виплюнути, щоб дізнатися, чи можете ви впоратися з витратами на поліморфізм часу виконання. Вам потрібно бути готовим проводити вимірювання, а також доводити, що ваш дизайн відповідає вашим вимогам. Це новий клас InterruptManager буде занадто довгим? Існують і інші форми поліморфізму, які можуть краще відповідати вашій проблемі, такі як поліморфізм зв’язкового часу, який може зробити і C, але C ++ можна зробити за допомогою схеми дизайну Pimpl (непрозорий покажчик) .

Я кажу, що всі говорять, що C ++ має своє місце у вбудованому світі. Ви можете ненавидіти все, що хочете, але це не проходить. Це може бути написано дуже ефективно, але важче навчитися робити це правильно, ніж із С. Іноді це може працювати краще, ніж C при вирішенні проблеми, а іноді і при вираженні кращого інтерфейсу, але знову ж таки, ви повинні виховувати себе і не боятися вчитися як.


1
Це узгоджується з тим, що я прочитав від інших консультантів із вбудованих систем. Мене завжди вчили, що з C ти постійно мало різаєш себе, але помилка в C ++ буде рідше, але коли ти накрутишся, ти втратиш ногу. Дякую, що ви написали чітку відповідь з деякими знаннями, яких у мене немає.
Кортук

3
Зауваживши, що спеціалісти з інформатики зійдуть з глузду на землі ЕЕ. На моїй роботі найгірший фрагмент коду, який ми написали, мажор CS. Ми витратили назавжди, намагаючись навчити його, що таке обладнання. Він створив структуровану систему за допомогою UML і побудував на її основі всю систему в Java, використовуючи належне успадкування тощо. Це працювало, поки нічого не змінилося, і тоді було поганою роботою з виправленням, щоб додати функції або повний перероблений дизайн. Код майже не застосовується через те, наскільки ретельно він затуманив усю справу у спадок.
Кортук

2
Це не просто помилки, які вас кусають, а нездійсненний код, який укусить і вас. Звичайно, коли ви починаєте цей проект із використанням цих акуратних функцій C ++, все проходить плавно, але після 2 або 3 років ентропія починається, якщо серйозних зусиль не буде докладено до рефакторингу в процесі розвитку. З цим я зараз стикаюсь. Код з часом гріє швидше в C ++.
Джей Аткінсон

2
UML та державні машини. Вам справді потрібно вивчити матеріали Міро Самека на сайті state-machine.com . Він побудував ефективну систему, яку легко змінити та змінити, але для її отримання потрібен певний час.
Джей Аткінсон

2
Це дійсно залежить від вашої системи та кількості пам’яті у вас. Ви пишете код на 8-бітовому мікро, з дуже маленькою оперативною пам’яттю? Тоді вам може бути краще уникати з глузду за абстрактними інтерфейсами. Якщо ви пишете щось на зразок 32-бітної вбудованої системи з плитами пам'яті, перейдіть до цього. Ви дійсно повинні зважити це. Наприклад, кожного разу, коли ви вставляєте світовий "віртуальний" на цей клас, ви отримуєте додатковий покажчик, який може бути 8-бітним, 16-бітним або 32-бітовим залежно від системи, для кожного окремого екземпляра ви заявляєте про цей об'єкт. Ви навіть не зрозумієте, чоловіче,
Джей Аткінсон

56

C ++ абсолютно підходить для вбудованих систем. Зараз я використовую наявність / відсутність хороших інструментів розробки (або їх відсутність) як основний критерій використання того чи іншого мікропроцесора чи ні.

Області С ++, які добре використовувати у вбудованих системах, оскільки вони мають низькі витрати на ресурси:

  • модульність, спричинена хорошим використанням класів / структур
  • шаблони, якщо компілятор добре працює над їх ефективним складанням. Шаблони є хорошим інструментом для приведення повторного використання алгоритмів до різних типів даних.

ОК райони:

  • віртуальні функції - я був проти цього, але вартість ресурсу дуже мала (один vtable на клас , а не на об'єкт; один вказівник на vtable на об'єкт; одна операція перенаправлення на виклик віртуальної функції) і велика перевага цього полягає в тому, що він дозволяє мати масив, що містить декілька різних типів об'єктів, без необхідності знати, який вони тип. Нещодавно я використав це для створення масиву об'єктів, кожен з яких представляє пристрій I2C, кожен з яких має окремі методи.

Області не використовувати, в основному через накладні витрати, які неприйнятні для малих систем:

  • динамічний розподіл пам’яті - інші згадували про це, але ще одна важлива причина не використовувати динамічний розподіл пам’яті - це те, що вона являє собою невизначеність у часі; багато причин використовувати вбудовані системи - для додатків у режимі реального часу.
  • RTTI (інформація про тип часу виконання) - вартість пам'яті досить велика
  • винятки - певне " ні-ні" через швидкість виконання

Дякуємо за вклад. Цікаво і дуже схоже на те, що я прочитав.
Кортук

1
Насправді динамічне розподіл пам’яті добре, а іноді й неминуче. У цьому полягає проблема динамічного розподілу пам'яті (та подальшого повторного використання). RTTI - це кабач пам'яті, я згоден на це. Але в чому проблема з винятками?
Wouter van Ooijen

1
@WoutervanOoijen: Проблема з винятками полягає в тому, що якщо fooвиклики barв межах try/ catchблоку і barстворюють деякі об'єкти та виклики boz, що викидає виняток, система повинна якось викликати деструктори для об'єктів, barстворених перед поверненням до управління foo. Якщо винятки повністю не вимкнено, barвони не зможуть знати, чи bozможе викинути якесь, і, таким чином, повинні включати додатковий код, щоб дозволити цю можливість. Я хотів би побачити варіацію C ++ із "перевіреними винятками", щоб вирішити це; якщо підпрограми, які могли б уникнути винятків ...
supercat

1
... довелося оголосити таким, тоді компілятору потрібно було б включити код обробці виключень у викликах таких процедур. Безумовно, додавання в усі необхідні декларації, сподіваючись, уникаючи зайвих, було б дещо обтяжливим, але це дозволило б використовувати винятки в місцях, де вони корисні, без додавання накладних, де їх немає.
supercat

3
@WoutervanOoijen: До речі, якби я розробляв ABI для такої обробки винятків на ARM, я б вказав, що код, який викликає процедуру, яка може вийти через виняток, повинен мати R14 вказівку на адресу в два байти до потрібної зворотної адреси (це буде виникають природним чином, якщо абонент дотримувався інструкції CALL з 16-бітним словом). Потім виклик звичайної програми виходитиме нормально через, add r15,r14,#2а не mov r15,r14; щоб вийти через виключення ldrhs r0,[r14] / add r15,r14,r0. Нульовий цикл коштує для нормального виходу, а також ніяких обмежень кадру стік.
supercat

36

Так, C ++, безумовно, підходить для вбудованих систем. Спочатку давайте вияснимо кілька помилок щодо різниці між C і C ++:

У вбудованому мікрофоні вам завжди потрібно обережно використовувати мови високого рівня, якщо вас турбують обмеження часу та простору. Наприклад, багато MCU не добре обробляють покажчики, і тому вони дуже неефективні при використанні стека. Це означає, що вам слід бути обережними щодо передачі змінних функціям, використання масивів та покажчиків та рекурсії. Простий рядок на C:

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

може генерувати близько 4 сторінок інструкцій залежно від характеру цих змінних.

Щоразу, коли ви використовуєте будь-яку мову високого рівня, і вас турбують обмеження часу та простору, тоді вам потрібно знати, як кожна функція цієї мови перетворюється на машинні інструкції вашого MCU (принаймні, кожну функцію, яку ви використовуєте). Це справедливо для C, C ++, Ada, як би там не було. Напевно, усі мови будуть містити функції, які не переводять ефективно на невеликих MCU. Завжди перевіряйте списки розбирання, щоб переконатися, що компілятор не генерує копії інструкцій для чогось тривіального.

Чи підходить C для вбудованих MCU? Так, поки ви стежите за згенерованим кодом.
Чи підходить C ++ для вбудованих MCU? Так, поки ви стежите за згенерованим кодом.

Ось чому я вважаю, що C ++ кращий за C навіть у 8-бітних MCU: C ++ забезпечує покращену підтримку:

  • Приховування даних
  • Більш сильне введення / перевірка
  • Мульти-периферійна прозорість за допомогою класів
  • Шаблони (як завжди, якщо використовуються обережно)
  • Списки ініціалізації
  • const

Жодна з цих особливостей не є важчою, ніж типові риси С.

По мірі переміщення до 16 або 32 бітних MCU, тоді починає мати сенс використовувати більш важкі функції C (стек, купа, вказівники, масиви, printf тощо). Таким же чином, на більш потужному MCU стає відповідним використовувати більш важкі функції C ++ (стек, купа, посилання, STL, нове / видалення).

Отже, не потрібно здригатися від думки про C ++ на PIC16. Якщо ви правильно знаєте свою мову та свій MCU, тоді ви знатимете, як їх ефективно використовувати разом.


3
Це дуже добре виражена і розумна відповідь на питання. +1 Привіт!
vicatcu

1
" a[i] = b[j] * c[k];може генерувати близько 4 сторінок інструкцій залежно від характеру цих змінних." Якщо ваш MCU / компілятор робить це, то це тому, що ви використовуєте деякий гарабі-хобі-процесор з 80-х.
Лундін

@Lundin - зітхання. Ні, це означає, що ви використовуєте маленький недорогий MCU, розроблений таким чином, щоб бути максимально дешевим і дешевим, не мати складних речей, таких як індексація стеків.
Rocketmagnet

2
@Rocketmagnet Добре, можливо, у 1990-х? На сьогоднішній день хитрі 8 гірок виходять за тією ж ціною, що і 32 гірки. Єдина причина, що залишилася для вибору колишнього - це споживання струму. А щодо тих надзвичайно хитрих 8-бітових біт без стека: якщо ви пишете C замість асемблера для такого обмеженого MCU, ви, ймовірно, робите це неправильно. Створені 4 сторінки - це ваша вина для написання занадто складних програм для центрального процесора, і по суті, C - це неправильний інструмент для виконання завдання. (Я це робив у минулому на Freescale RS08, це була дуже дурна ідея.)
Лундін,

32-бітний процесор @Lundin не потрібен швидше, ніж 16-розрядний. Це було очевидним ще в той час, коли в світі ПК відбувався перехід програм на 16 -32-бітний.
Barleyman

24

Я завжди вважаю ці дискусії цікавими для читання. Не стільки для інтелектуальної дискусії щодо плюсів і мінусів різних доступних мов, а тому, що зазвичай можна прив’язати чиюсь позицію до цієї теми, виходячи з їх роботи / досвіду / сфери, що цікавить. Тут прямо з аргументами "передчасної оптимізації" були спеціалісти CS та програмісти з технічного обслуговування, які цитують Knuth зліва і справа, і ті, хто працює в реальному світі, де важливі питання, вважають, що вони всі божевільні (я член останньої групи бути справедливим).

Зрештою, ви можете розробити чудове програмне забезпечення на C або C ++ або вставити мову тут . Це зводиться до можливостей розробника, а не до мови. Бути знавцем мови, як правило, потрібно лише в тому випадку, якщо ви вибрали неправильну мову для початку і тепер вам потрібно перетворити її на вирішення своєї проблеми, в більшості випадків це єдині ситуації, коли вам потрібно зануритися в незрозумілі функції або компілятор хитрощі для досягнення мети.

Я часто чую, як люди починають ці аргументи як "Я знавець мови X і бла-бла". Я чесно негайно дискредитую цих людей, тому що, на мою думку, вони вже підійшли до проблеми з неправильного кута, і все після цього заплямовано бажанням використовувати свій інструмент для вирішення проблеми та показати, наскільки це "круто".

Я так часто спостерігаю, як розробники вибирають набір інструментів першим і намагаються зв'язати його зі своєю проблемою вдруге, що абсолютно неправильно і призводить до лайм-рішень.

Як я згадував у коментарі до іншої відповіді, ці мовні війни часто переростають у аргументацію того, що мова X дозволяє програмісту робити більш німі речі. Хоча читати цікаво, всі ці твердження справді означають, що у вас є проблема з наймом хороших розробників, і вам потрібно вирішити це питання безпосередньо, а не намагатися надавати допомогу ситуації, продовжуючи наймати поганих розробників і вибираючи такі інструменти, які вони можуть робити як мало можливо пошкодження.

На мій погляд, хороші розробники, будь то розробка програмного забезпечення або обладнання, досліджуйте проблему, розробляйте рішення та знаходьте інструменти, які дозволять їм висловити рішення найкращим чином. Не має значення, чи потрібний вам інструмент є те, що ви ніколи раніше не використовували, після того як ви використовували 3-4 мови / інструменти розробки для проектів, що вибирали новий, повинні мати мінімальний вплив на час вашої розробки.

Звичайно, "найкращий спосіб" є суб'єктивним терміном, і його також слід визначити на етапі дослідження. Потрібно розглянути безліч питань: продуктивність, простота вираження, щільність коду тощо на основі наявної проблеми. Я не включав ремонтопридатність у цей список з причини, мені все одно, яку мову ви вибрали, якщо ви вибрали відповідний інструмент і знайшли час, щоб зрозуміти проблему, це повинно вийти "безкоштовно". Складне підтримання коду часто є результатом вибору неправильного інструменту або поганої структури системи, це призводить до некрасивого хакітського безладу, щоб змусити його працювати.

Стверджувати, що будь-яка мова є «кращою», ніж будь-яка інша, нерозумно, не визначаючи конкретної проблеми, що цікавить. Об'єктно-орієнтований підхід не завжди кращий, ніж функціональний підхід. Є деякі проблеми, які дуже добре піддаються об'єктно-орієнтованій парадигмі дизайну. Є багато, що цього не роблять. Це ж твердження можна зробити про багато мовних особливостей, на які люди, схоже, люблять харчуватися.

Якщо ви витрачаєте більше 20% свого часу на проблему, яка фактично набирає код, ви, ймовірно, створюєте дуже погану систему, або у вас дуже погані розробники (або ви все ще навчаєтесь). Ви повинні витратити більшу частину свого часу на переднє діаграмування проблеми та визначення взаємодії різних частин програми. Залишивши групу талановитих розробників у приміщенні з маркерною дошкою та вирішити проблему та сказати їм, що їм заборонено писати будь-який код чи вибирати будь-які інструменти, поки вони не почуватимуться комфортно з усією системою, вони зроблять більше для покращення якості Вихід та швидкість розвитку, ніж вибір будь-якого гарячого нового інструменту гарантовано покращить час розробки. (розгляньте розвиток scrum як орієнтир для полярного, протилежного моєму аргументу)

Часто прикрою реальністю є те, що багато підприємств можуть виміряти цінність розробника лише за кількістю написаних рядків або за допомогою «відчутного результату». Вони розглядають 3 тижні в приміщенні з маркером як втрату продуктивності. Розробники часто змушені швидко пройти стадію роздумів або змушені використовувати інструмент, встановлений політичним питанням компанії: "Брат мого начальника працює на IBM, щоб ми могли використовувати лише їх інструменти", такий сміття. . Або ще гірше, ви отримуєте від компанії постійно мінливий набір вимог, оскільки вони не здатні провести належне дослідження ринку або не розуміють впливу змін на цикл розвитку.

Вибачте за те, що я злегка не ставлю тему з цією розпустою, я маю досить сильні думки щодо цієї теми.


2
Тепер я не перебиваю тести одиниць на рівні програми (вище драйвера) для певних вбудованих систем. Існує деяка цінність миттєвого зворотного зв’язку щодо тестування одиниць та усунення помилок на початку фази розробки, але вся парадигма TDD, що породила дизайн, мені здається трохи нерозумною. Я вважаю за краще витратити деякий час, щоб "подумати" про проблему і скласти схему в голові, на папері чи на дошці, перш ніж починати кодувати. Я також думаю, що TDD закликає ринок не робити передових досліджень вимог, тому що він повинен допомогти у постійній зміні вимог.
Джей Аткінсон

2
І щоб зробити остаточну примітку до мого супер-довгого коментаря. Нам не потрібні мовні експерти для роботи над дизайном. Нам потрібні експертні дизайнери, які можуть працювати на мовах.
Джей Аткінсон

1
PRD = документ про вимоги до товару, MRD = документ про вимоги до маркетингу, TRD = документ про технічні вимоги. TDD = Тестова розробка.
Джей Аткінсон

1
@Mark - Я погоджуюся з вашими настроями дизайну, але лише до певного моменту. Я думаю, що важкі проектні роботи окупаються, якщо: а) Ви вимоги досить стабільні / відомі; б) розробники, які займаються дизайном, мають досвід . У поперед. робота, мені було доручено займатися дизайном, і це було сильно оброблене тимчасовим керівництвом моєї команди, і я подумав: "Що за тупа штука! Дизайн-вперед-це економить гроші (пор. Код Повна книга) ??" Але в кодуванні я виявив багато речей, яких я не знав шукати. Якби я зробив багато дизайну і мінімізував час коду, це було б марно. JME.
Дж. Полфер

1
@sheepsimulator Я, очевидно, погоджуюся з другим моментом, я вважаю, що провідні архітектори системи - досвідчені розробники. По першому моменту я фактично не згоден. Я думаю, що чим більше ви очікуєте, що вимоги зміняться, тим більше часу ви повинні витратити на етапі проектування, оскільки вам потрібно створити хороший, легкий для зміни дизайн. Я знаю, деякі філософії пропонують швидкий розвиток. У деяких випадках це добре працює, як багато поганих або недосвідчених програмістів на персоналі. Усі ці філософії дизайну зводиться до того, що "я не молюся про створення гнучкої системи, тому не витрачайте час на пробування".
Марк

17

Для вбудованої системи може підійти будь-яка мова. Вбудований просто означає: частина більшого апарату, на відміну від безкоштовного у користуванні комп'ютера.

Питання має більшу актуальність, коли його задають (у жорсткий) режим у режимі реального часу або з обмеженими ресурсами .

Для системи в режимі реального часу C ++ є однією з найвищих мов, яка все ще підходить при програмуванні суворих часових обмежень. За винятком використання купи (вільний оператор), він не має конструкцій, що мають невизначений час виконання, тому ви можете перевірити, чи відповідає ваша програма тимчасовим вимогам, і, маючи додатковий досвід, ви можете навіть передбачити це. Звичайно, слід уникати використання купи, хоча нового оператора все ще можна використовувати для одноразового розподілу. Конструкції, які C ++ пропонує над C, можуть бути використані у вбудованій системі: OO, винятки, шаблони.

Для дуже обмежених ресурсів (8-бітні мікросхеми, менше декількох КБ оперативної пам’яті, недоступний стек) повний C ++ може бути непридатним, хоча він все ще може використовуватися як «кращий C».

Я думаю, що прикро, що Ада, здається, використовується лише в деяких нішах. Багато в чому це Pascal ++, але без тягаря до того, щоб бути вгору сумісним з мовою, яка вже була серйозним безладом. (редагувати: серйозний безлад, звичайно, C. Паскаль - прекрасна, але дещо непрактична мова.)

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

EDIT: Я набирав відповідь на нове запитання ("У яких випадках потрібен C ++, коли ми програмуємо мікроконтролери"?), Яке було закрито з посиланням на це, тому я додам те, що написав:

Ніколи не існує всеосяжної причини використання будь-якої мови програмування, але можуть бути аргументи, які мають більшу чи меншу вагу в конкретній ситуації. Дискусії з цього приводу можна знайти в багатьох місцях, з позицій, що займають від "ніколи не використовувати C ++ для мікроконтролера" до "завжди використовувати C ++". Я більше з останньою позицією. Я можу навести кілька аргументів, але вам доведеться самостійно вирішити, яку вагу вони несуть у певній ситуації (і в якому напрямку).

  • Компілятори C ++ рідше, ніж компілятори C; для деяких цілей (наприклад, 12 і 14 бітових ядерних ПІК) взагалі немає компіляторів C ++.
  • (хороші) Програмісти на C ++ зустрічаються рідше, ніж (хороші) програмісти на С, особливо серед тих, хто також (дещо) знає електроніку.
  • C ++ має більше конструкцій, ніж C, які не підходять для невеликих систем (наприклад, винятки, RTTI, часте використання купи).
  • C ++ має більш багатий набір (стандартних) бібліотек, ніж C, але наслідком попереднього пункту є те, що бібліотеки C ++ часто використовують функції, які не підходять для малих систем і, отже, не можуть бути використані для малих систем.
  • C ++ має більше конструкцій, ніж C, які дозволяють стріляти собі в ногу.
  • C ++ має більше конструкцій, ніж C, які дозволяють вам не допустити себе стріляти в ногу (так, IMO це та попереднє - це істинно).
  • C ++ має більш багатий набір механізмів абстрагування, тому він забезпечує кращі способи програмування, особливо для бібліотек.
  • Мовні функції C ++ (наприклад, конструктори / деструктори, функції перетворення) ускладнюють перегляд коду для створення сформованої машини, а отже, витрат у просторі та часі мовної конструкції.
  • Мовна конструкція C ++ робить менш необхідним усвідомлювати, як саме переводяться на машинний код, оскільки вони роблять «правильну справу» більш абстрактно.
  • Мовний стандарт C ++ швидко розвивається і швидко приймається великими компіляторами (gcc, clang, microsoft). C розвивається досить суворо, і прийняття деяких нових особливостей (варіантів масивів) лякає і навіть було повернено в більш пізньому стандарті. Цей момент, зокрема, цікавий тим, що різні люди використовують його для підтримки протилежних позицій.
  • C ++ - це, безсумнівно, більш гострий інструмент, ніж C. Чи довіряєте ви своїм програмістам (або собі) використовувати такий інструмент для створення красивої скульптури, чи ви боїтесь, що вони самі собі зашкодять, і чи бажаєте ви скористатися менш красивим, але з меншим ризиком продуктом ? (Я пам'ятаю , що мій учитель скульптури одного разу сказав мені , що тупі інструменти можуть в деяких ситуаціях бути більш небезпечними , ніж гострі з них.)

У моєму блозі є деякі статті щодо використання C ++ у невеликих системах (= мікроконтролерів).


15

На мій досвід, C ++ зазвичай погано підходить для невеликих вбудованих систем. Під якими я маю на увазі мікроконтролери та пристрої без ОС.

Багато методів C ++ OOP покладаються на динамічне розподілення пам'яті. Цього часто не вистачає в невеликих системах.

STL та Boost дійсно демонструють потужність C ++, обидва - це величезна відстань.

C ++ заохочує програміста відмовитися від машини, де в обмежених системах її потрібно прийняти.

Минулого року я переніс комерційний віддалений настільний продукт на мобільні телефони. Він був написаний на C ++ і працював у Windows, Linux та OSX. Але він значною мірою покладався на STL, динамічну пам’ять та винятки C ++. Щоб продовжувати роботу в WinCE, Symbian і ОС, що не потребують ОС, найефективнішим варіантом було перезапис C.


Я погоджуюсь стосовно малих систем, але я думаю, що ми маємо різні визначення малих систем. Коли у вас є 1 КБ ПЗУ і добре написаний код C, він займає весь, крім 1 байт ПЗУ, тобто невелика система.
Кортук

6
Я не стверджую, що C не може мати менший слід, але ви могли б все-таки використати C ++ і отримали дуже подібний результат для проектування того, що тільки обговорювалося. Я думаю, що проблема полягає в тому, що більшість програмістів OOP використовуються для систем з динамічною пам'яттю і використовують дуже неефективні конструкції, що призводить до абсолютно марного коду для систем з меншою потужністю.
Кортук

4
так що ви говорите: ви не хочете використовувати C ++, ви хочете використовувати щось між C і C ++ (давайте просто назвати це C +?). У цьому випадку я погоджуюся, що багато лайно у C ++ людей використовують лише тому, що це доступно, а не тому, що його оптимально. Практично будь-яка мова здатна створювати хороший, швидкий код, питання про те, як його використовувати. Більшість святих воєн за мови не є результатом можливостей мов, а міркуванням про те, як легко ідіоту робити ідіотичні речі, що насправді є ідіотським аргументом: p
Марк

2
"Більшість святих воєн за мови не є результатом можливостей мов, а міркуванням про те, як легко ідіоту робити ідіотичні речі, що насправді є ідіотичним аргументом". Було дуже приємне речення. Мені потрібно твоє прізвище, щоб я міг його процитувати.
Кортук

1
Я дійсно також не використовую динамічну пам'ять в С. Ніде я не маю цього мати. В довгостроковій перспективі я читав, що вона може дуже сегментуватися і почати створювати проблеми. Мені потрібно мати дуже чітко розроблені корпуси для втрати пам’яті, і мені потрібно мати можливість стежити, скільки точно залишилось.
Кортук

11

Я сподіваюся додати більше світла, ніж тепла для цієї дискусії про C ++ для систем з обмеженим металом та обмеженими ресурсами.

Проблеми в C ++:

  • Винятки становлять особливість оперативної пам'яті, оскільки необхідний "аварійний буфер" (де виняток з пам'яті йде, наприклад) може бути більшим, ніж наявна оперативна пам'ять, і, безумовно, є витратою на мікроконтролери. Для отримання додаткової інформації див. N4049 та n4234 . Їх слід вимкнути (що наразі не визначена поведінка, тому будьте впевнені і ніколи не кидайте). SG14 зараз працює над кращими способами цього.

  • RTTI, мабуть, ніколи не коштує накладних витрат, його слід вимкнути

  • Великі налагодження складаються, хоча це не проблема в класичній розробці робочого столу, якщо налагодження не поміщається на мікросхемі, це може бути проблемою. Проблема виникає з-за шаблонного коду або додаткових викликів функцій, доданих для ясності. Ці додаткові функціональні дзвінки знову будуть видалені оптимізатором, і додаткова чіткість або гнучкість можуть бути великою перевагою, однак при складанні налагоджень це може бути проблемою.

  • Виділення купи. Хоча STL дозволяє використовувати власні алокатори, це може бути складним для більшості програмістів. Розподіл купи не детермінований (тобто не важкий у реальному часі), і фрагментація може призвести до виникнення несподіваних ситуацій із пам'яттю, незважаючи на те, що працювали в тестуванні. Зберігання книг, необхідне купі для того, щоб відслідковувати вільний простір та різний розмір, може бути проблемою для невеликих предметів. Зазвичай краще використовувати розподіл пулу (і в C, і в C ++), але це може бути ненормально для програмістів на C ++, які звикли використовувати лише купу.

  • Поліморфізм під час виконання та інші непрямі дзвінки, як правило, є великим ударом, проблема, як правило, більше, оскільки оптимізатор не може бачити через них більше, ніж власне отримання та стрибки на адресу. З цієї причини слід уникати непрямих викликів в C і C ++, де, як і в C ++, вони більше вбудовані в культуру (і є досить корисними в інших областях).

  • неявна взаємодія з clib може бути проблематичною. Можливо, контрінтуїтивним є те, що проблеми клібу є категорією C ++, але проблема виникає внаслідок неявного спільного використання ресурсів у одночасних середовищах (обмін є більш чітким у С). Використання загальної реалізації newLib часто тягне за собою велику кількість руху, яка зазвичай не потрібна в ОК, з іншого боку, newLibNanno не є ретентом, тому доступ до нього повинен бути серіалізованим (тут надмірне спрощення). Це також проблема для C, але доступ є більш явним. Як правило, слід нічого не використовувати з простору імен std в контексті ISR, якщо ви впевнені, що він не отримує доступ до стану в clib (наприклад, errorno або купи). Це також важливо, якщо ви використовуєте потоки (я віддаю перевагу RTC), щоб замінити нові та видалити, щоб синхронізувати доступ до malloc та free.

На закінчення C ++ має деякі проблеми, але вони, по суті, всі, які можна виправити або уникнути.

Тепер для C тут проблема вищого порядку. У мене немає синтаксичної здатності в C абстрагувати речі таким чином, що я можу виконати оптимізацію або перевірити інваріанти під час компіляції. Тому я не можу належним чином інкапсулювати речі таким чином, що користувачеві не потрібно знати, як вони працюють, щоб їх використовувати, і більшість моїх виявлень помилок проводиться під час виконання (що не лише запізнилося, але й додає витрати). По суті єдиний спосіб бути загальним у C - це через дані, я передаю рядок формату printf або scanf, який оцінюється, наприклад, під час виконання. Тоді компілятору досить важко довести, що я не використовую деякі варіанти, які теоретично можливі при передачі правильних даних, що означає потенційне генерування мертвого коду та втрату потенціалу оптимізації.

Я знаю, що тут я можу розв’язати тугу, але мій досвід роботи з 32-бітовими мікроконтролерами полягає в тому, що в порівнянні C і C ++ від яблук до яблук, написаних експертами (як у C ++, можливо, дуже шаблонно), C ++ є набагато ефективнішою мовою, як тільки будь-що повинно бути взагалі загальним (як і в будь-якій бібліотеці), і вони по суті є еквівалентними у не загальних випадках. Початківцю також простіше використовувати досвід експерта-виконавця бібліотеки в C ++.

У той же час, насправді є дійсно мало функцій, до яких я не можу передати невірні дані, як тільки вхід не є int, а a, somethingдля якого я, мабуть, використовує int як метод подання, то є потенціал отримати його неправильно (передайте недійсне значення або "otherThing", а не "щось"). У моєму єдиному способі перевірити, чи не помилився користувач, це під час виконання. У мові C ++ я маю можливість виконувати деякі перевірки, не всі перевірки, але деякі перевірки під час компіляції, які є безкоштовними.

Зрештою, команда C часто настільки ж потужна, як і її найслабший програміст, і в результаті коду вигода має або мультиплеєра 1, або продуктивного штрафу. Що я маю на увазі під цим, це або висока ефективність для однієї і лише однієї унікальної роботи в унікальному середовищі унікальних дизайнерських рішень, або вона є загальною для використання в різних середовищах (інший мікроконтролер, інша стратегія управління пам'яттю, інші затримки vs. пропускна спроможність тощо тощо), але має властиву собівартість.

У C ++ речі фахівці можуть бути інкапсульовані та використані у багатьох середовищах, коли компіляція часового коду адаптується до конкретної задачі, а статична перевірка не дозволяє користувачам робити дурні речі за нульових витрат. Тут у нас набагато менше торгівлі між загальним та швидким, і, в кінцевому рахунку, з точки зору витрат та вигод ефективніша, безпечніша та продуктивніша мова.

Це обґрунтована критика того, що все ще існує великий дефіцит гарних бібліотек C ++ для вбудованих, це може призвести до прагматичних рішень щодо використання в основному C на компіляторі C ++. Рішення використовувати лише C у проекті, по суті, або ідеологічно спричинене, не потребуючи застарілої підтримки або визнання, що команда недостатньо дисциплінована, щоб утриматися від дуже вибраного набору дурних речей, які можна робити в C ++, але не в C і в той же час достатньо дисциплінований, щоб не робити жодного з набагато більших наборів дурних речей, від яких не можна захиститись в С, але міг би в С ++.


Приємне доповнення до моєї відповіді :) Хто був би цей таємничий коханець C ++? У його профілі зазначено: "Мабуть, цей користувач вважає за краще зберігати в них таємницю". (погана англійська, BTW) АЛЕ AHA місцезнаходження "Бохум, Німеччина" ..... До зустрічі на конференції!
Wouter van Ooijen

Ага так, оновив мій профіль;) Приємно знати, що ти прийдеш до emBO ++, це буде гарна натовп
odinthenerd

10

Моє передумови: тільки поза шкільною підготовкою за старими програмістами Bell Labs; працював 3 роки, 2 над науково-дослідним проектом з нижчого рівня; збирання даних / управління процесами у VB.NET. Провів 1,5 роки, працюючи над додатком бази даних підприємства в VB6. В даний час працює над проектом для вбудованого ПК з 2 Гб пам’яті, 512 Мб оперативної пам’яті, процесор 500 МГц x86; декілька додатків, що працюють одночасно, записані на C ++ з механізмом IPC між ними. Так, я молода.

Моя думка: Я думаю, що C ++ може ефективно працювати в умовах середовища, про який я писав вище . Справді, продуктивність у режимі реального часу не є вимогою для додатка, на якому я перебуваю, а в деяких вбудованих додатках це може бути проблемою. Але ось чого я навчився:

  • C ++ принципово відрізняється від C (тобто немає C / C ++). Хоча все, що є дійсним C, є дійсним C ++, C ++ - це зовсім інша мова, і потрібно навчитися програмувати на C ++, а не на C, щоб ефективно використовувати його в будь-якій ситуації. У C ++ потрібно програмувати об'єктно-орієнтовано, а не процедурно, а не гібрид двох (великі класи з великою кількістю функцій). Загалом, вам слід зосередитись на створенні малих класів з кількома функціями, а всі маленькі класи разом скласти у більші рішення. Один з моїх колег пояснив мені, що я програмував процедурно в об'єктах, що є великим безладом і важко підтримувати. Коли я почав застосовувати більше об'єктно-орієнтовані методи, я виявив, що ремонтопридатність / читабельність мого коду зросла.

  • C ++ надає додаткові функції у вигляді об'єктно-орієнтованої розробки, які можуть запропонувати спосіб спростити код, щоб полегшити читання / підтримку . Чесно кажучи, я не думаю, що багато чого в шляху покращення ефективності продуктивності та простору у виконанні OOP. Але я думаю, що OOP - це техніка, яка може допомогти розбити складну проблему на безліч дрібних шматочків. І це корисно для людей, що працюють над кодом, елементом цього процесу, який не слід ігнорувати.

  • Багато аргументів проти C ++ пов'язані в першу чергу з динамічним розподілом пам'яті. У C теж є ця проблема. Ви можете написати об'єктно-орієнтовану програму, не використовуючи динамічну пам'ять, хоча одна з переваг використання об'єктів полягає в тому, що ви можете динамічно розподіляти ці речі динамічно. Як і в C, ви повинні бути обережними, як керувати даними, щоб зменшити витоки пам'яті, але техніка RAII робить це простішим у C ++ (зробити динамічну пам'ять автоматично руйнуючись шляхом інкапсуляції її в об'єкти). У деяких програмах, де нараховується кожне місце пам’яті, це може бути занадто дико & вуха для управління.

Редагувати:

  • Напишіть питання "Arduino C ++" : я б стверджував, що C ++ без динамічного управління пам'яттю все ще може бути корисним. Ви можете впорядкувати свій код в об'єкти, а потім розмістити ці об’єкти в різних місцях у вашій програмі, встановити інтерфейси зворотного виклику тощо. Тепер, коли я розроблявся в C ++, я бачу багато способів застосування програми з усіма даними, виділеними на стек все ще може бути корисним для об'єктів. Я визнаю, хоча - я ніколи фактично не писав такого вбудованого додатка для Arduino, тому у мене немає доказів щодо моєї претензії. У мене є деякі можливості зробити якусь розробку Arduino в майбутньому проекті - сподіваюся, я можу перевірити свою претензію там.

2
Я хотів би прокоментувати ваш другий пункт, ви говорите, що це допомагає розбити складну проблему на безліч дрібниць, і цю особливість слід ігнорувати. Це точна причина, що я настільки про-С ++. Дуже великий обсяг досліджень програмування показує, що лінійне зростання розмірів програми дає експоненціальне зростання часу розвитку. це відбувається навпаки, якщо ви можете правильно розділити програму, то ви можете дати експоненціальний розпад у часі розробки. Це, безумовно, найважливіше.
Кортук

і щодо вашого другого пункту: Просто використання методології проектування OOP не дає більш деталізованого коду. Маючи гарний базовий дизайн, як висловити, що дизайн залишається розробнику. OOP не визначає, що ви відокремлюєте свій код належним чином, він надає інший варіант, і навіть більше, зовнішній вигляд, який ви зробили так, але це, звичайно, не вимагає хорошого дизайну, тобто на розробника.
Марк

Це завжди правда. Я ніколи не чув про мову, яка наклала б гарний дизайн. Я думаю, що ми здебільшого маємо на увазі, що це робота розробників, і що C ++ дозволяє легко використовувати та реалізовуватись організовано.
Кортук

@ Марк - я згоден. Це був для мене процес навчання.
Дж. Полфер

7

Так, проблема з C ++ полягає в збільшенні коду.

У деяких системах ви підраховуєте байти, і в такому випадку вам доведеться прийняти вартість роботи, що наближається до меж ваших систем, збільшується вартість розробки C.

Але навіть у С, для добре розробленої системи потрібно тримати все в капсулі. Добре розроблені системи важкі, а C ++ дають програмістам місце для дуже структурованого та керованого методу розробки. Навчання OOP є вагомим, і якщо ви хочете перейти на нього, ви дуже приймаєте його, і в багатьох випадках керівництво скоріше продовжить роботу з C і не оплатить вартість, оскільки важко виміряти результати перемикання, які підвищує продуктивність праці. Ви можете подивитися статтю гуру вбудованих систем Джека Гансле тут .

Динамічне управління пам’яттю - диявол. Насправді диявол - це автоматичний маршрут, динамічне управління пам’яттю чудово працює на ПК, але ви можете розраховувати на перезавантаження ПК принаймні кожні кілька тижнів. Ви побачите, що вбудована система продовжує працювати протягом 5 років, що динамічне управління пам’яттю дійсно може закрутитися і фактично почати виходити з ладу. У своїй статті Ganssle обговорює такі речі, як стек та купа.

У C ++ є деякі речі, які є більш схильними до виникнення проблем і використання багатьох ресурсів, видалення динамічного управління пам’яттю та шаблонів - це великі кроки для того, щоб слід C ++ наблизився до сліду C. Це все-таки C ++, вам не потрібна динаміка управління пам'яттю або шаблони для написання хорошого C ++. Я не усвідомлював, що вони вилучили винятки, вважаю винятки важливою частиною мого коду, яку я видаляю у випуску, але використовую до цього моменту. Під час польового тестування я можу за винятками генерувати повідомлення, щоб повідомити про потрапляння винятку.


1
Раніше я погоджувався, що слід коду - це проблема, але останнім часом здається, що розмір спалаху дуже сильно впливає на ціну мікроконтролера, набагато менше розміру оперативної пам’яті або кількості штифтів IO.
Wouter van Ooijen

Аргумент щодо динамічної пам'яті є важливішим IMO. Я бачив промислові системи, які могли працювати тижнями безперервно, але діагностичний шар (написаний на C ++) обмежив би час на перезапуск приблизно до 12 годин.
Дмитро Григор’єв

6

Я вважав, що ця анти-C ++ розмова Лінуса Торвальда була цікавою.

Однією з найгірших особливостей C ++ є те, як це робить багато речей настільки залежними від контексту - це просто означає, що коли ви дивитесь на код, місцевий погляд просто рідко дає достатній контекст, щоб знати, що відбувається.

Він говорить не про світ вбудованих систем, а про розробку ядра Linux. Для мене актуальність випливає з цього: C ++ вимагає розуміння більш широкого контексту, і я можу навчитися використовувати набір шаблонів об'єктів, я не довіряю собі запам’ятовувати їх, коли мені доведеться оновити код за кілька місяців.

(З іншого боку, я зараз працюю над вбудованим пристроєм за допомогою Python (не C ++, але використовую ту саму парадигму OOP), яка матиме саме таку проблему. На мою захист, це вбудована система, досить потужна, щоб її називали ПК 10 років тому.)


5
Ми можемо відрізнятися, але я вважаю, що відкриваючи будь-який проект, я не можу сказати, що відбувається негайно, але якщо я знаю щось про те, що він робить, і у мене є щось добре закодовано в C, а щось добре закодовано в C ++, C ++ завжди здається більше ясний. Вам все-таки потрібно здійснити інкапсуляцію для гарного розвитку C, що робить C ++ дуже просто. Грамотне використання класів може чітко зрозуміти, де ви перебуваєте інтерфейси, і з ними можна повністю обробляти об’єкт.
Кортук

Повністю домовились про інкапсуляцію та заняття. Перевантаження і спадкування оператора, не так вже й багато.
pingswept

1
Так, так, перевантаження оператора може використовуватися для придушення функції коду. Якщо хтось є оператором перевантаженим, це потрібно робити з зрозумілих причин або зовсім не робити. Спадкування слід застосовувати лише у конкретних випадках, коли ви насправді робите щось таке, що схоже на батьків з кількома доповненнями. Я думаю, я б не використовував будь-яку функцію в OOP. Я використовував і те, і інше, але у вбудованій системі не можу придумати випадок, як би я. Як я вважаю, компілятор з обмеженням 80 символів для змінних імен повинен бути негайно знятий.
Кортук

2
Я просто трохи кинув у рот при думці програмувати MCU на Python ...
vicatcu

Ви не єдиний, але якщо це працює добре і ефективно, я можу пробачити.
Кортук

6

Я думаю, що інші відповіді дали гарний випадок за плюси і мінуси та фактори рішення, тому я хотів би просто підсумувати та додати кілька коментарів.

Для маленьких мікроконтролерів (8-бітових) ніяк. Ви просто просите поранити себе, вигоди немає, і ви відмовитеся занадто багато ресурсів.

Для мікроконтролерів високого класу (наприклад, 32-розрядні, 10s або 100s МБ для оперативної пам’яті та пам’яті), які мають гідну ОС, це цілком нормально, і, смію сказати, навіть рекомендується.

Тож питання: де межа?

Я точно не знаю, але одного разу я розробив систему для 16-розрядного UC з 1 Мб оперативної пам’яті та 1 Мб пам’яті в C ++, щоб потім пошкодувати про це. Так, це спрацювало, але зайвої роботи я не вартувала. Мені довелося зробити так, щоб такі речі, як винятки, не створювали протікань (підтримка OS + RTL була досить гнучкою і ненадійною). Більше того, програма OO, як правило, робить багато невеликих виділень, і нагромадження для них було ще одним кошмаром.

Враховуючи цей досвід, я вважаю, що для майбутніх проектів я виберу C ++ лише в системах, принаймні 16-розрядних, і принаймні 16 Мб оперативної пам’яті та пам’яті. Це довільна межа і, ймовірно, буде змінюватися залежно від типу додатків, стилів кодування та ідіом тощо. Але, враховуючи застереження, я рекомендую подібний підхід.


2
Я тут не погоджуюся, це не раптова точка, коли C ++ стає прийнятним завдяки системним ресурсам, хороша практика проектування може зберегти слід C ++ там, де знаходиться слід C. Це призводить до коду з проектами OOP, які займають однаковий простір. Погано написаний C може бути так само погано.
Кортук

1
Ну, це залежить від того, наскільки великим є ваш додаток і наскільки ви використовуєте певні функції, які потребують більше місця (наприклад, шаблони та винятки). Але особисто я скоріше використовую C, ніж мушу обмежувати себе стриманим C ++. Але навіть тоді ви матимете накладні витрати більшого RTL, віртуального методу громозахисту, виклик ланцюга конструктора / деструктора ... ці ефекти можуть бути пом’якшені ретельним кодуванням, але тоді ви втрачаєте головну причину використання C ++, абстрагування та перспектива високого рівня.
fceconel

4

Є деякі функції C ++, які корисні у вбудованих системах. Є й інші, як винятки, які можуть бути дорогими і витрати яких не завжди можуть бути очевидними.

Якби я мав свої барабани, то була б популярна мова, яка поєднала б найкраще з обох світів і включала б деякі функції, яких не вистачає в обох мовах; деякі постачальники включають кілька таких функцій, але немає стандартів. Я хотів би побачити кілька речей:

  1. Виняток обробляє трохи більше, як Java, де функції, які можуть кидати або витікати винятки, повинні бути оголошені як такі. Хоча вимога до таких декларацій може дещо дратувати з точки зору програмування, вона б підвищила чіткість коду у випадках, коли функція може повернути довільне ціле число, якщо це вдасться, але може також і не виконати. Багато платформ можуть недорого впоратися з цим кодом, наприклад, маючи повернене значення в реєстрі та вказівку успіху / відмови у прапорці.
  2. Перевантаження тільки статичних і вбудованих функцій; я розумію, що органи зі стандартів для C уникають перевантаження функцій, щоб уникнути необхідності керувати іменами. Дозволення лише перевантажень статичних та вбудованих функцій дозволило б уникнути цієї проблеми, і це дало б 99,9% переваги від перевантаження зовнішніх функцій (оскільки .h файли можуть визначати вбудовані перевантаження з точки зору інакше названих зовнішніх функцій)
  3. Перевантаження для довільних або конкретних постійних значень параметрів компіляції за часом. Деякі функції можуть вбудовуватися дуже ефективно, коли передаються з будь-яким постійним значенням, але вбудовані дуже погано, якщо передано змінну. Інший раз код, який може бути оптимізацією, якщо значення постійне, може бути песимізацією, якщо це не так. Наприклад:
    inline void copy_uint32s (uint32_t * dest, const uint32_t * src, __is_const int n)
    {
      якщо (n <= 0) повернути;
      інакше, якщо (n == 1) {dest [0] = src [0];}
      інакше, якщо (n == 2) {dest [0] = src [0]; dest [1] = src [1];}
      інакше, якщо (n == 3) {dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2];}
      інакше, якщо (n == 4) {dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2]; dest [3] = src [3];}
      else memcpy ((void *) dest, (const void *) src, n * sizeof (* src));
    }
    
    Якщо 'n' можна оцінити під час компіляції, вищевказаний код буде більш ефективним, ніж виклик memcpy, але якщо 'n' неможливо оцінити під час компіляції, сформований код буде набагато більшим і повільнішим, ніж код, який просто називається memcpy.

Я знаю, що батько C ++ не надто захоплюється вбудованою версією C ++, але я думаю, що це може запропонувати значні вдосконалення щодо простого використання C.

Хтось знає, чи розглядається щось подібне до будь-якого типу стандарту?



@Joby Taffey: Я думаю, що я відредагував свою публікацію, щоб пропустити згадку про те, що творець C ++ не захоплювався вбудованим підмножиною; Я усвідомлюю, що були зусилля, але, наскільки я розумію, вони насправді так далеко не досягли. Я думаю, було б певне використання для стандартизованої мови, яка піддавалася б 8-бітовим процесорам, і такі функції, як я описав вище, здадуться корисними на будь-якій платформі. Ви чули про будь-які мови, які пропонують такі речі, як №3 вище? Здавалося б, дуже корисно, але я ніколи не бачив, щоб жодна мова пропонувала це.
supercat

"Батько С ++" має нульовий досвід програмування вбудованих систем, так чому б хтось хвилювався його думкою?
Лундін

@Lundin: Той факт, що деякі впливові люди, як видається, переймаються його думкою з різних питань, здавалося б, сам по собі є причиною для інших людей. Я думаю, що, оскільки я писав вище, зростаюча потужність шаблонів, можливо, додала нових можливостей для перевантажень на основі того, що константи можна вирішити під час компіляції, хоча набагато менш чисто, ніж якби така річ підтримувалася як компіляція - функція часу (з того, що я розумію, можна вказати шаблон, який повинен спробувати різні речі по порядку і йти з першим, що не виходить з ладу ...
supercat

... але це вимагає від компілятора витратити неабияку кількість зусиль, збираючи потенційні заміни, які згодом будуть відкинуті. Уміння більш чітко сказати "Якщо це константа, зробіть це, інакше це зробити", без будь-яких "помилкових стартів", здавалося б, більш чистий підхід.
supercat

3

C ++ - це більше, ніж одна мова програмування:

а) Це "краще" С б) Це об'єктно орієнтована мова в) Це мова, яка дозволяє нам писати загальні програми

Хоча всі ці функції можна використовувати окремо, найкращі результати досягаються, коли три з них використовуються одночасно. Тим не менш, якщо ви вирішите вибрати лише одну з них, якість вбудованого програмного забезпечення підвищиться.

а) Це "кращий" С

C ++ - сильна набрана мова; сильніший за C. Ваші програми скористаються цією функцією.

Деякі люди бояться вказівників. C ++ включає посилання. Перевантажені функції.

І варто сказати: жодна з цих функцій не виникає у великих чи повільніших програмах.

б) Це об'єктно-орієнтована мова

Хтось сказав у цьому дописі, що абстрагувати машину мікроконтролерами - це не дуже гарна ідея. Неправильно! Усі ми, вбудовані інженери, завжди абстрагували машину, тільки з іншим синтаксисом, ніж у C ++. Проблема, яку я бачу в цьому аргументі, полягає в тому, що деякі програмісти не звикли мислити об'єктами, тому вони не бачать переваг OOP.

Щоразу, коли ви готові використовувати периферійний апарат мікроконтролера, ймовірно, що периферійний апарат був абстрагований для нас (від себе чи третьої сторони) у формі драйвера пристрою. Як я вже говорив раніше, цей драйвер використовує sintax C, як показано в наступному прикладі (взято безпосередньо з прикладу NXP LPC1114):

/ * Налаштування таймера для відповідності та переривання в 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);

Ви бачите абстракцію? Отже, при використанні C ++ з тією ж метою, абстракція виводиться на наступний рівень через механізм абстракції та інкапсуляції C ++, за нульової вартості!

в) Це мова, яка дозволяє нам писати загальні програми

Загальні програми досягаються за допомогою шаблонів, а шаблони також не мають витрат на наші програми.

Крім того, статичний поліморфізм досягається за допомогою шаблонів.

Віртуальні методи, RTTI та винятки.

Існує компроміс при використанні віртуальних методів: краще програмне забезпечення проти певного штрафу у виконанні. Однак пам’ятайте, що динамічне прив'язування, ймовірно, буде реалізовано за допомогою віртуальної таблиці (масив функціональних покажчиків). Я робив те ж саме в C багато разів (навіть регулярно), тому не бачу недоліків у використанні віртуальних методів. Більше того, віртуальні методи в C ++ є більш елегантними.

Нарешті, порада про RTTI та винятки: НЕ ВИКОРИСТОВУЙТЕ ЇМ у вбудованих системах. Уникайте їх за будь-яку ціну !!


2

Мій фон, вбудований (mcu, pc, unix, інше), в режимі реального часу. Важлива безпека. Я ввів попереднього роботодавця в STL. Я більше цього не роблю.

Деякий вміст полум'я

Чи підходить C ++ для вбудованих систем?

Мех. C ++ - це біль писати і боліти за підтримку. C + начебто добре (не використовуйте деякі функції)

C ++ у мікроконтролерах? RTOS? Тостери? Вбудовані ПК?

Знову кажу Мех. C + не надто погано, але АДА менш болючий (і це насправді щось говорить). Якщо вам пощастить, як я, ви отримаєте вбудовану Java. Перевірений доступ до масиву та відсутність арифметики вказівника не забезпечує дуже надійний код. Збирачі сміття у вбудованій Java не є найвищим пріоритетом, і є обсяг пам'яті та повторне використання об'єктів, тому добре розроблений код може працювати назавжди без GC.

Чи корисний OOP на мікроконтролерах?

Звичайно, є. UART - це об'єкт ..... DMAC - це об'єкт ...

Машини об'єктного стану дуже легкі.

Чи C ++ віддаляє програміста занадто далеко від обладнання, щоб бути ефективним?

Якщо це не PDP-11, C - це не ваш процесор. C ++ спочатку був препроцесором на вершині C, тому Bjarne Stroustrup перестане засміятися за те, що він мав повільні імітаційні симуляції, перебуваючи в AT&T. C ++ - це не ваш процесор.

Ідіть, отримайте MCU, який запускає Java-байт-коди. Програма на Java. Сміяйтеся над хлопцями С.

Чи слід вважати C ++ Arduino (без динамічного управління пам'яттю, шаблонами, винятками) "справжнім C ++"?

Ні. як і всі утилізовані компілятори C для MCU.

По-друге, вбудована Java або вбудована ADA стандартизовані (ish); все інше - горе.


2
Чи легко знайти мікроконтролери, що підтримують Java? Я думаю, що це значно обмежить вибір. І який у вас досвід щодо покарання за ефективність роботи (оскільки в ОК зазвичай не було б JIT)? Як щодо впливу непередбачуваності ГК у системах реального часу?
fceconel

2
Які MCU там підтримують вбудовану Java?
Дж. Полфер

www.ajile.com для початківців.
Тім Вілліскрофт

+1 для Ада. Для цього вкладається багато, в тому числі і Arduinos.
Брайан Драммонд

портативний java VM для мікрофонів, написаних на c, є відкритим кодом. dmitry.co/index.php?p=./04.Thoughts/…
Тім Вілліскрофт

-2

Вбудовані системи розроблені для того, щоб виконувати якусь конкретну задачу, а не бути комп'ютером загального призначення для декількох завдань. Вбудована система - це поєднання комп'ютерного обладнання та програмного забезпечення. С - рідна мова всіх сучасних мов. Це низький рівень, але потужність, повна мова і має справу з усіма видами обладнання. Таким чином, C / C ++ є оптимальним вибором для розробки програмного забезпечення для вбудованої системи, яке дуже повно використовується для кожної вбудованої системи. Як ми знаємо, C є мовою, що розвивається. Операційна система UNIX написана на C. Оскільки успішна розробка програмного забезпечення так часто стосується вибору найкращої мови для даного проекту, дивно виявити, що мова C / C ++ зарекомендувала себе як підходяща як для 8-бітних, так і для 64-бітних процесорів. ; в системах з байтами, кілобайтами та мегабайтами пам'яті. C має перевагу незалежності процесора, що дозволяє програмістам концентруватися на алгоритмах та програмах, а не на деталях конкретної архітектури процесора. Однак багато з цих переваг стосуються інших мов високого рівня. Але C / C ++ вдалося там, де стільки інших мов значною мірою не вдалося?


6
Я дійсно не впевнений, що це додає дискусії.
Трейд Дейва

-3

<агент>

Я думаю, що С ++ - це хитра мова в першу чергу. Якщо ви хочете використовувати OOP, пишіть програми Java. C ++ не робить нічого для того, щоб застосувати парадигми OOP, оскільки прямий доступ до пам'яті повністю у вашій можливості (або) використовувати.

Якщо у вас є MCU, ви говорите про, швидше за все, менше ніж 100 КБ флеш-пам’яті. Ви хочете програмувати мовою, абстракція пам'яті: коли я оголошую змінну чи масив, вона отримує пам'ять, період; malloc (він же "нове" ключове слово в C ++) повинен бути більш-менш заборонений до використання у вбудованому програмному забезпеченні, за винятком, можливо, в рідкісних випадках одного дзвінка під час запуску програми.

Пекло, є (часто) часи у вбудованому програмуванні, де C недостатньо низький рівень, і вам потрібно робити такі речі, як виділення змінних до регістрів, і написати вбудовану збірку, щоб посилити ваші процедури переривання служби (ISR). Такі ключові слова, як "непостійний", стають досить важливими для розуміння. Ви витрачаєте багато свого часу на маніпулювання пам'яттю на бітовому рівні, а не на об'єктному рівні.

Чому ви хочете обманути себе на думці, що речі простіші, ніж вони є насправді?

</rant>


Моя проблема тут просто, чому я хочу знати складність драйвера, який був написаний для управління USART1, якщо він повністю розроблений для обробки інтерфейсу.
Кортук

1
Я вас не проголосував, але хотів би зазначити, що C ++ не потребує застосування OOP, а лише дає інструменти для цього. Забезпечення хороших стандартів кодування - робота розробника. Це може допомогти, якщо мова спрощує, але мова ніколи не зробить це самостійно. C може бути нечитабельним у деяких випадках.
Кортук

1
Усі мови для чогось корисні. C ++ швидко. OOP, якщо це зроблено добре, багато розробникам значно полегшує роботу паралельно та кодує невідоме. Я думаю, саме тому він має стільки тяги в розвитку ігор.
Тобі Джаффі

1
Так, я згоден. Причина, яку я бачу у вбудованому світі, полягає в тому, що велика кількість функцій та функцій додається до багатьох різних систем, що вже існують, та нових систем, що розробляються. Проект стає все більшим та більшим. Або нам знадобиться більше часу, щоб їх розробити, або ми почнемо застосовувати та спотворювати те, що світ CS вже зробив на ПК.
Кортук

5
Ще одна людина, яка не розуміє C ++ належним чином. Мене завжди дивує, скільки їх є.
Rocketmagnet
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.