Подходит ли C ++ для встраиваемых систем?


168

Общий вопрос, здесь и в других местах. Подходит ли C ++ для встраиваемых систем?

Микроконтроллеры? RTOSes? Тостеры? Встроенные ПК?

ООП полезен на микроконтроллерах?

С ++ удаляет программиста слишком далеко от оборудования, чтобы быть эффективным?

Следует ли рассматривать Arduino C ++ (без динамического управления памятью, шаблонов, исключений) как «настоящий C ++»?

(Надеюсь, эта вики послужит местом для размещения этой потенциальной священной войны)


5
Быстрый вопрос: когда вы говорите, встроенный , вы имеете в виду микроконтроллер? микропроцессор? встроенный x86 / встроенный ПК?
Дж. Полфер

1
Я не собирался вызывать священную войну; цель состояла в том, чтобы узнать, что ваши аргументы были против этого.
Дж. Полфер

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

4
C ++ против встроенного является спорным вопросом. У меня есть твердое мнение, но я не думаю, что было бы справедливо ставить вопрос и играть за очки. Я надеюсь, что вики сообщества сделает обсуждение более сбалансированным.
Тоби Джаффей

13
Это плохой вопрос, поскольку «встроенный» является бессмысленным атрибутом при решении вопроса о том, подходит ли конкретный язык и связанный с ним багаж. Дело в том, что система небольшая по сравнению с большими системами, где на небольших системах нет ОС, они имеют ограниченную память, могут не быть фон Неймана, могут иметь различные аппаратные ограничения для стеков вызовов, стеков данных, вы не можете просто динамически выделять Мб или даже кб и т. д. Большинство микроконтроллеров представляют собой «маленькие» системы. Обычно встраиваются одноплатные компьютеры, но обычно это «большие» системы.
Олин Латроп

Ответы:


135

Да, C ++ все еще полезен во встроенных системах. Как уже говорили все, это все еще зависит от самой системы, так как 8-битный UC, вероятно, был бы нет-нет в моей книге, даже если там есть компилятор, и некоторые люди делают это (вздрагивает). Еще есть преимущество использования C ++, даже когда вы уменьшаете его до чего-то вроде «C +» даже в 8-битном микромире. Что я имею в виду под "C +"? Я имею в виду, что не используйте new / delete, избегайте исключений, избегайте виртуальных классов с наследованием, возможно, избегайте наследования все вместе, будьте очень осторожны с шаблонами, используйте встроенные функции вместо макросов и используйте constпеременные вместо #defines.

Я работаю как на C, так и на C ++ во встраиваемых системах уже более десяти лет, и часть моего юношеского энтузиазма по поводу C ++ определенно исчезла из-за проблем реального мира, которые сотрясают наивность. Я видел худшее в C ++ во встраиваемых системах, которое я хотел бы назвать «программисты CS сумасшедшие в мире EE». На самом деле, это то, над чем я работаю со своим клиентом, чтобы улучшить эту одну кодовую базу, которую они имеют среди других.

Опасность C ++ заключается в том, что это очень очень мощный инструмент, очень похожий на обоюдоострый меч, который может отрезать вам руку и ногу, если он не обучен и не дисциплинирован должным образом в своем языке и самом общем программировании. С больше похож на односторонний меч, но все же такой же острый. С C ++ слишком легко получить очень высокие уровни абстракции и создавать запутанные интерфейсы, которые в долгосрочной перспективе теряют смысл, и это отчасти объясняется гибкостью C ++ в решении одной и той же проблемы с помощью множества различных языковых функций (шаблоны, ООП, процедурные, RTTI, ООП + шаблоны, перегрузка, встраивание).

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

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

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

Я говорю это все, чтобы сказать, что C ++ имеет свое место во встроенном мире. Вы можете ненавидеть все, что хотите, но это не уйдет. Он может быть написан очень эффективным способом, но научиться делать это правильно сложнее, чем с C. Иногда он может работать лучше, чем C, при решении проблемы, а иногда выражая лучший интерфейс, но опять же, вы должны обучай себя и не бойся учиться как.


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

3
На ноте компьютерных наук майоры сходят с ума в EE land. На моей работе худший кусок кода, который мы имеем, был написан майором CS. Мы потратили целую вечность, пытаясь научить его, что такое оборудование. Он создал структурированную систему с использованием UML и построил всю систему на ее основе в Java, используя надлежащее наследование и так далее. Это работало до тех пор, пока что-то не изменилось, а затем это была плохая работа по добавлению функций или полная модернизация. Код почти не пригоден для использования из-за того, как тщательно он запутал все это наследованием.
Кортук

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

2
UML и государственные машины. Вы действительно должны посмотреть на вещи Миро Самека на state-machine.com . Он построил эффективную систему, которую легко реорганизовать и изменить, но на это уходит некоторое время.
Джей Аткинсон

2
Это действительно зависит от вашей системы и от того, сколько памяти у вас есть. Вы пишете код на 8-битном микро с очень небольшим объемом оперативной памяти? Тогда вам лучше не сходить с ума от абстрактных интерфейсов. Если вы пишете что-то вроде 32-битных встроенных систем с кусочками памяти, сделайте это. Вы действительно должны взвесить это. Например, каждый раз, когда вы прикрепляете мир «виртуальный» к этому классу, вы получаете дополнительный указатель, который может быть 8-битным, 16-битным или 32-битным в зависимости от системы, для каждого отдельного экземпляра, который вы объявляете для этого объекта. Вы даже не поймете, а мужик,
Джей Аткинсон

56

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

Области C ++, которые хорошо использовать во встроенных системах, потому что они имеют низкую стоимость ресурсов:

  • модульность, обеспеченная хорошим использованием классов / структур
  • шаблоны, если компилятор делает хорошую работу по их эффективной компиляции. Шаблоны - это хороший инструмент для повторного использования алгоритмов для разных типов данных.

ОК области:

  • виртуальные функции - я был против этого, но стоимость ресурсов очень мала (один виртуальный стол на класс , а не на объект; один указатель на виртуальный стол на объект; одна операция разыменования на вызов виртуальной функции) и большое преимущество этого это то, что он позволяет вам иметь массив, содержащий несколько различных типов объектов, без необходимости знать, какого они типа. Я использовал это недавно, чтобы иметь массив объектов, каждый из которых представляет устройство I2C, каждый с отдельными методами.

Области, которые нельзя использовать, в основном из-за накладных расходов, что недопустимо в небольших системах:

  • динамическое выделение памяти - другие упоминали об этом, но еще одна важная причина не использовать динамическое выделение памяти состоит в том, что оно представляет неопределенность во времени; Многие причины использовать встроенные системы для приложений реального времени.
  • RTTI (информация о типе времени выполнения) - стоимость памяти довольно велика
  • исключения - однозначно нет-нет, из-за попадания скорости выполнения

Спасибо за вклад. Интересно и очень похоже на то, что я прочитал.
Кортук

1
На самом деле динамическое распределение памяти хорошо, а иногда и неизбежно. Проблема заключается в динамическом выделении памяти (и последующем повторном использовании). RTTI - боров памяти, я согласен с этим. Но в чем проблема с исключениями?
Вутер ван Оойен

1
@WoutervanOoijen: Проблема с исключениями состоит в том, что если fooвызовы barвнутри блока try/ catchи barсоздание некоторых объектов и вызовов boz, которые выдают исключение, система должна каким-то образом вызывать деструкторы для barсозданных объектов, прежде чем возвращать управление foo. Если исключения полностью не отключены, у barних не будет возможности узнать, bozмогут ли они быть сгенерированы, и поэтому они должны включать дополнительный код, чтобы учесть такую ​​возможность. Я хотел бы увидеть вариант C ++ с «проверенными исключениями», чтобы справиться с этим; если подпрограммы, которые могли бы позволить исключениям избегать ...
суперкат

1
... должен был быть объявлен как таковой, тогда компилятору было бы необходимо только включить код обработки исключений в вызывающие стороны таких подпрограмм. Конечно, добавление всех требуемых деклараций, хотя, как мы надеемся, избежание ненужных, будет несколько обременительным, но это позволит использовать исключения в тех местах, где они полезны, без добавления накладных расходов, где их нет.
Суперкат

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

36

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

Во встроенном микро-устройстве вам всегда нужно будет осторожно использовать языки высокого уровня, если вас беспокоит ограничение времени или пространства. Например, многие MCU плохо обрабатывают указатели и поэтому очень неэффективны при использовании стека. Это означает, что вы должны быть осторожны при передаче переменных в функции, используя массивы и указатели, а также рекурсию. Простая строка C вроде:

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

может генерировать около 4 страниц инструкций в зависимости от характера этих переменных.

Всякий раз, когда вы используете какой-либо язык высокого уровня и беспокоитесь о временных и пространственных ограничениях, вам необходимо знать, как каждая функция этого языка преобразуется в машинные инструкции на вашем MCU (по крайней мере, для каждой функции, которую вы используете). Это верно для C, C ++, Ada, что угодно. Вероятно, все языки будут содержать функции, которые не будут эффективно переводиться на небольшие микроконтроллеры. Всегда проверяйте списки разборки, чтобы убедиться, что компилятор не генерирует стопки инструкций для чего-то тривиального.

Подходит ли C для встроенных микроконтроллеров? Да, если вы следите за сгенерированным кодом.
Подходит ли C ++ для встроенных микроконтроллеров? Да, если вы следите за сгенерированным кодом.

Вот почему я думаю, что C ++ лучше, чем C, даже на 8-битных MCU: C ++ обеспечивает улучшенную поддержку:

  • Скрытие данных
  • Более сильный набор / проверка
  • Мульти-периферийная прозрачность с использованием классов
  • Шаблоны (как всегда, если использовать осторожно)
  • Списки инициализации
  • Const

Ни одна из этих функций не тяжелее, чем типичные особенности C.

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

Таким образом, нет необходимости содрогаться при мысли о C ++ на PIC16. Если вы знаете свой язык и MCU правильно, то вы будете знать, как эффективно использовать их оба вместе.


3
Это очень хорошо выраженный и разумный ответ на вопрос. +1 ура!
Викацу

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

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

2
@ RocketMagnet Хорошо, может быть, в 1990-х? В настоящее время дерьмовые 8 биттеров продаются по той же цене, что и 32 биттера. Единственная причина, по которой можно выбрать первое - это потребление тока. А что касается тех сверххитрых 8-битных без стека: если вы пишете C вместо ассемблера для такого ограниченного MCU, вы, вероятно, делаете это неправильно. Сгенерированные 4 страницы являются вашей собственной ошибкой в ​​написании слишком сложных программ для ЦП, и, по сути, C является неподходящим инструментом для этой задачи. (Я делал это в прошлом на Freescale RS08, это была очень глупая идея.)
Лундин

32-битный процессор @Lundin не нужен быстрее 16-битного. Это было очевидно еще в тот день, когда в мире ПК происходил переход с 16 на 32 бита.
Барлиман

24

Я всегда нахожу эти дебаты интересными для чтения. Не столько для интеллектуальной дискуссии о плюсах и минусах различных доступных языков, сколько потому, что вы обычно можете придерживаться чьей-то позиции по теме, основываясь на их работе / опыте / сфере интересов. Это прямо там с аргументами «преждевременной оптимизации», когда майоры и программисты CS цитировали Кнута влево и вправо и тех, кто работает в реальном мире, где вопросы производительности думают, что они все сумасшедшие (я член последней группы по честному).

В конце концов, вы можете разработать отличное программное обеспечение на C или C ++ или вставить язык здесь . Все сводится к возможностям разработчика, а не к языку. Быть экспертом по языку обычно требуется только в том случае, если вы выбрали неправильный язык для начала, и теперь вам нужно обратить его в решение вашей проблемы, в большинстве случаев это единственные ситуации, когда вам нужно погрузиться в неясные функции или компилятор трюки для достижения цели.

Я часто слышу, как люди начинают эти аргументы как «Я эксперт по языку X и бла-бла». Я честно немедленно дискредитирую этих людей, потому что, по моему мнению, они уже подошли к проблеме с неправильной точки зрения, и все, что после этого испорчено по их желанию использовать свой инструмент для решения проблемы и показать, как это круто.

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

Как я упоминал в комментарии к другому ответу, эти языковые войны часто сводятся к утверждению, что язык X позволяет программисту делать более глупые вещи. Несмотря на то, что читать интересно, все эти утверждения действительно означают, что у вас есть проблема с наймом хороших разработчиков, и вам нужно обратиться к этой проблеме напрямую, а не пытаться объединить усилия для помощи ситуации, продолжая нанимать плохих разработчиков и выбирая инструменты так, чтобы они могли делать как можно меньше повреждение как можно

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

Конечно, «лучший способ» - это субъективный термин, который также должен быть определен на этапе исследования. Нужно учитывать множество вопросов: производительность, простота выражения, плотность кода и т. Д. В зависимости от рассматриваемой проблемы. Я не включил ремонтопригодность в этот список по какой-то причине, мне все равно, какой язык вы выберете, если вы выбрали подходящий инструмент и нашли время, чтобы понять проблему, которая должна появиться «бесплатно». Трудно поддерживать код часто является результатом выбора неправильного инструмента или плохой структуры системы, что приводит к ужасному хаосу, который заставляет его работать.

Утверждать, что любой язык «лучше», чем любой другой, глупо без определения конкретной проблемы, представляющей интерес. Объектно-ориентированный подход не всегда лучше, чем функциональный подход. Есть некоторые проблемы, которые очень хорошо подходят для объектно-ориентированной парадигмы проектирования. Есть много, которые этого не делают. То же самое можно сказать и о многих языковых особенностях, которые люди, похоже, любят использовать.

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

Часто прискорбная реальность такова, что многие компании могут измерить ценность разработчика только по количеству написанных строк или по «ощутимому результату». Они рассматривают 3 недели в комнате с маркером как потерю производительности. Разработчики часто вынуждены проходить через «продуманную» стадию разработки или вынуждены использовать набор инструментов из-за какой-то политической проблемы внутри компании: «Брат моего босса работает на IBM, поэтому мы можем использовать только их инструменты», такого рода мусор , Или, что еще хуже, вы получаете от компании постоянно изменяющийся набор требований, потому что они не способны проводить надлежащее исследование рынка или не понимают влияния изменений на цикл разработки.

Извините за то, что немного не в теме с этой напыщенной работой, у меня есть довольно сильные мнения по этой теме


2
Теперь я не стучу юнит-тестами на уровне приложения (выше драйвера) в некоторых встроенных системах. Существует некоторая ценность мгновенной обратной связи модульного тестирования и устранения ошибок на ранних этапах разработки, но вся парадигма TDD, порождающая дизайн, кажется мне немного мозговой мертвецом. Я предпочитаю потратить некоторое время, чтобы «подумать» о проблеме и нарисовать ее в своей голове, на бумаге или на доске, прежде чем начинать кодировать. Я также думаю, что TDD поощряет рынок не проводить предварительное исследование требований, поскольку оно должно помочь в постоянном изменении требований.
Джей Аткинсон

2
И напоследок отметим мой супер длинный комментарий. Нам не нужны языковые эксперты для разработки дизайна. Нам нужны опытные дизайнеры, которые могут работать на языке (ах).
Джей Аткинсон

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

1
@ Марк - я согласен с вашими предварительными настроениями, но только в точку. Я думаю, что тяжелые работы по проектированию окупаются, если: а) ваши требования довольно стабильны / известны, и б) разработчики, занимающиеся дизайном, имеют опыт . В пред. На моей работе мне было поручено заняться дизайном, и это было в значительной степени запрограммировано руководителем моей команды, и я подумал: «Что за глупость! Дизайн впереди экономит деньги (ср. Code Complete book) ??» Но в кодировании я обнаружил множество вещей, которые я не знал, чтобы искать. Если бы я много занимался дизайном и минимизировал время написания кода, это было бы пустой тратой. ЮМЭ.
Дж. Полфер

1
@sheepsimulator Я, очевидно, согласен со вторым пунктом, я полагаю, что ведущие архитекторы систем являются опытными разработчиками. С первым пунктом я действительно не согласен. Я думаю, чем больше вы ожидаете, что требования изменятся, тем больше времени вам придется потратить на этапе проектирования, потому что вам нужно создать хороший, простой в изменении дизайн. Я знаю, что некоторые философии предлагают быстрое развитие. В некоторых случаях это работает хорошо, как много плохих или неопытных программистов в штате. Все эти философии дизайна сводятся к тому, что «я не молюсь о разработке гибкой системы, поэтому давайте не будем тратить время на попытки».
Марк

17

Любой язык может подойти для встроенной системы. Встроенный просто означает: часть большего устройства, в отличие от бесплатного компьютера.

Вопрос более актуален, когда его спрашивают о (жесткой) системе в реальном времени или с ограниченными ресурсами .

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

Для систем с очень ограниченными ресурсами (8-битные микросхемы, меньше, чем несколько килобайт ОЗУ, нет доступного стека) полный C ++ может оказаться неподходящим, хотя все еще может использоваться как «лучший C».

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

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

РЕДАКТИРОВАТЬ: Я печатал ответ на новый вопрос («В каких случаях C ++ необходим, когда мы программируем микроконтроллеры»?), Который был закрыт со ссылкой на этот вопрос, поэтому я добавлю то, что я написал:

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

  • Компиляторы C ++ встречаются реже, чем компиляторы C; для некоторых целей (например, 12 и 14-битных PIC ядра) компиляторы C ++ вообще отсутствуют.
  • (хорошие) программисты на 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 ++ основаны на динамическом распределении памяти. Это часто отсутствует в небольших системах.

STL и Boost действительно демонстрируют мощь C ++, оба занимают огромное место.

C ++ поощряет программиста абстрагироваться от машины, где в стесненных системах она должна использоваться.

В прошлом году я перенес коммерческий продукт для удаленного рабочего стола на мобильные телефоны. Он был написан на C ++ и работал на Windows, Linux и OSX. Но он сильно зависел от STL, динамической памяти и исключений C ++. Чтобы запустить его в средах WinCE, Symbian и без ОС, перезапись C была самым разумным вариантом.


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

6
Я не утверждаю, что C не может иметь меньшую площадь, но вы могли бы использовать C ++ и получить очень похожий результат для разработки того, что только что обсуждалось. Я думаю, что проблема заключается в том, что большинство программистов ООП привыкли к системам с динамической памятью и используют очень неэффективные конструкции, что приводит к совершенно бесполезному коду для систем с низким энергопотреблением.
Кортук

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

2
«Большинство священных войн за языки - это не результат языковых возможностей, а аргумент в пользу того, как легко идиоту делать идиотские вещи, что на самом деле является идиотским аргументом». Было очень приятное предложение. Мне нужна твоя фамилия, чтобы я мог процитировать ее.
Кортук

1
Я действительно не использую динамическую память в C, хотя все же. Там нет нигде, что я должен иметь это. В долгосрочной перспективе я прочитал, что он может быть очень сегментирован и начать вызывать проблемы. Мне нужно иметь очень четко спроектированные чехлы для нехватки памяти, и я должен быть в состоянии точно контролировать, сколько осталось.
Кортук

11

Я надеюсь добавить больше света, чем тепла в эту дискуссию о C ++ на голом металле и системах с ограниченными ресурсами.

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

  • Исключением является, в частности, проблема с оперативной памятью, поскольку требуемый «аварийный буфер» (где, например, используется исключение нехватки памяти) может быть больше доступной оперативной памяти и, безусловно, является пустой тратой на микроконтроллеры. Для получения дополнительной информации см. N4049 и n4234 . Они должны быть отключены (что в настоящее время является неопределенным поведением, поэтому будьте уверены и никогда не бросайте). SG14 в настоящее время работает над лучшими способами сделать это.

  • RTTI, вероятно, никогда не стоит накладных расходов, его следует отключить

  • Большие отладочные сборки, хотя это не проблема при разработке классического десктопа, если отладка не помещается в чип, это может быть проблемой. Проблема возникает из шаблонного кода или дополнительных вызовов функций, добавленных для ясности. Эти дополнительные вызовы функций будут снова удалены оптимизатором, и дополнительная ясность или гибкость могут быть большим преимуществом, однако в отладочных сборках это может быть проблемой.

  • Распределение кучи. Хотя STL допускает использование пользовательских распределителей, это может быть сложным для большинства программистов. Распределение кучи недетерминировано (т. Е. Не является жестким в реальном времени), и фрагментация может привести к неожиданным ситуациям нехватки памяти, несмотря на то, что они работали в тестировании. Бухгалтерский учет, необходимый куче для отслеживания свободного места и разного размера, может быть проблемой для небольших объектов. Обычно лучше использовать распределение пула (как в C, так и в C ++), но это может быть ненормально для программистов на C ++, которые привыкли использовать только кучу.

  • Полиморфизм во время выполнения и другие косвенные вызовы, как правило, сильно снижают производительность, проблема обычно заключается в том, что оптимизатор не может видеть сквозь них больше, чем фактическая выборка и переход к адресу. По этой причине следует избегать косвенных вызовов в C и C ++, где, как и в C ++, они более укоренились в культуре (и весьма полезны в других областях).

  • неявное взаимодействие с clib может быть проблематичным. Может показаться нелогичным, что проблемы с клибом находятся в категории C ++, но проблема возникает из-за неявного совместного использования ресурсов в параллельных средах (совместное использование более очевидно в C). Использование общей реализации newLib часто приводит к большому количеству раздувания, которое обычно не требуется в uC, с другой стороны, newLibNanno не является реентерабельным, поэтому доступ к нему должен быть сериализован (упрощенное здесь). Это проблема и для C, но доступ более явный. Как правило, по существу ничего не следует использовать из пространства имен std в контексте ISR, если вы не уверены, что оно каким-то образом не обращается к состоянию в clib (например, errorno или куча). Также важно, если вы используете потоки (я предпочитаю RTC) для переопределения новых и удаления для синхронизации доступа к malloc и free.

В заключение, у С ++ есть некоторые проблемы, но по сути все они исправимы или их можно избежать.

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

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

В то же время на самом деле существует очень мало функций, которым я не могу передать неверные данные, как только ввод не является целым, а something для которых я использую целое число как метод представления, тогда есть вероятность получить его. неправильный (передайте неверное значение или «otherThing», а не «что-то»). В C мой единственный метод проверки, если пользователь ошибся, это во время выполнения. В C ++ у меня есть возможность выполнять некоторые проверки, не все проверки, но некоторые проверки во время компиляции, которые бесплатны.

В конце концов, команда C часто столь же сильна, как и ее самый слабый программист, и в результате получаемый код имеет многопользовательский режим 1 или снижение производительности. Под этим я подразумеваю, что это либо высокая производительность для одной и только одной уникальной работы в уникальной среде с уникальными проектными решениями, либо она достаточно универсальна для использования в нескольких средах (другой микроконтроллер, другая стратегия управления памятью, другая задержка или компромисс между пропускной способностью и т. д. и т. д.), но присущий производительности.

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

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


Хорошее дополнение к моему ответу :) Кем будет этот загадочный любитель C ++? Его профиль гласит: «По-видимому, эти пользователи предпочитают держать в тайне о них». (плохой английский, кстати), НО АХА, местоположение "Бохум, Германия" ..... До встречи на конференции!
Воутер ван Оойен

Ах да, обновил мой профиль;) приятно знать, что вы пришли на emBO ++, это будет хорошая публика
odinthenerd

10

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

Мое мнение: я думаю, что C ++ может работать эффективно, учитывая среду, которую я написал выше . По общему признанию, жесткая производительность в реальном времени не является требованием для приложения, в котором я работаю, и в некоторых встроенных приложениях это может быть проблемой. Но вот что я узнал:

  • C ++ принципиально отличается от C (то есть C / C ++ отсутствует). В то время как все, что является допустимым C, является C ++, C ++ - это совсем другой язык, и нужно научиться программировать на C ++, а не на C, чтобы эффективно использовать его в любой ситуации. В C ++ вам нужно программировать объектно-ориентированное, а не процедурное и не гибридное из двух (большие классы с большим количеством функций). В общем, вы должны сосредоточиться на создании маленьких классов с небольшим количеством функций и объединить все маленькие классы в более крупное решение. Один из моих коллег объяснил мне, что я обычно программировал на объектах, что является большим беспорядком и его трудно поддерживать. Когда я начал применять более объектно-ориентированные методы, я обнаружил, что удобство сопровождения / читаемости моего кода повысилось.

  • C ++ предоставляет дополнительные функции в форме объектно-ориентированной разработки, которые могут упростить код для облегчения его чтения / сопровождения . Честно говоря, я не думаю, что в ООП можно улучшить производительность / эффективность использования пространства. Но я думаю, что ООП - это метод, который может помочь разбить сложную проблему на множество маленьких частей. И это полезно для людей, работающих над кодом, элемент этого процесса, который нельзя игнорировать.

  • Многие аргументы против C ++ имеют отношение главным образом к динамическому распределению памяти. С тоже имеет такую ​​же проблему. Вы можете написать объектно-ориентированное приложение без использования динамической памяти, хотя одно из преимуществ использования объектов заключается в том, что вы можете легко и быстро распределять эти объекты. Как и в C, вы должны быть осторожны с тем, как управлять данными, чтобы уменьшить утечки памяти, но техника RAII делает это проще в C ++ (делает динамическое разрушение памяти автоматически, инкапсулируя ее в объектах). В некоторых приложениях, где каждая ячейка памяти имеет значение, это может быть слишком диким и шероховатым для управления.

РЕДАКТИРОВАТЬ:

  • WRT вопрос «Arduino C ++» : я бы сказал, что C ++ без динамического управления памятью все еще может быть полезен. Вы можете организовать свой код в объекты, а затем поместить эти объекты в различные места в вашем приложении, настроить интерфейсы обратного вызова и т. Д. Теперь, когда я занимался разработкой на C ++, я вижу много способов, которыми приложение со всеми данными, размещенными на Стек все еще может быть полезен с объектами. Я признаю, хотя - я никогда не писал такого встроенного приложения для Arduino, так что у меня нет никаких доказательств в пользу моего заявления. У меня есть некоторые возможности для разработки Arduino в будущем проекте - надеюсь, я смогу проверить свои требования там.

2
Я хотел бы прокомментировать ваше второе замечание: вы говорите, что оно помогает разбить сложную проблему на множество мелких частей, и эту функцию следует игнорировать. Это точная причина того, что я так про-C ++. Очень большой объем исследований в области программирования показывает, что линейный рост размера программы дает экспоненциальный рост времени разработки. это следует противоположным образом: если вы можете правильно разделить программу, вы можете дать экспоненциальный спад во времени разработки. Это, безусловно, самая важная вещь.
Кортук

и по второму вопросу: простое использование методологии проектирования ООП не приводит к большему разделению кода. Хороший базовый дизайн делает то, как каждый выражает этот дизайн, оставлен на усмотрение разработчика. ООП не определяет, что вы правильно разделяете свой код, оно предоставляет другую опцию и, более того, внешний вид, который вы сделали, но, безусловно, не требует хорошего дизайна, который должен решать разработчик.
Марк

Это всегда так. Я никогда не слышал о языке, который навязывает хороший дизайн. Я думаю, мы в основном подразумеваем, что это работа разработчиков, и что C ++ облегчает использование и реализацию организованным способом.
Кортук

@ Марк - я согласен. Это был процесс обучения для меня.
Дж. Полфер

7

Да, проблема с C ++ заключается в увеличенном объеме кода.

В некоторых системах вы подсчитываете байты, и в этом случае вам придется принять расходы на запуск, близкие к границам ваших систем, это увеличенные затраты на разработку C.

Но даже в C для хорошо спроектированной системы вам нужно хранить все в капсуле. Хорошо спроектированные системы сложны, и C ++ дает программистам место для очень структурированного и контролируемого метода разработки. Изучение ООП обходится дорого, и, если вы хотите переключиться на него, вы очень его принимаете, и во многих случаях руководство предпочло бы продолжить с C и не платить за него, так как трудно измерить результаты переключения, которое увеличивает производительность. Вы можете увидеть статью гуру встраиваемых систем Джека Гэнсле здесь .

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

В C ++ есть некоторые вещи, которые более склонны вызывать проблемы и использовать много ресурсов, удаление динамического управления памятью и шаблонов - это большие шаги, чтобы держать след C ++ ближе к следу C. Это все еще C ++, вам не нужен динамический Управление памятью или шаблоны для написания хорошего C ++. Я не осознавал, что они удалили исключения, я считаю исключения важной частью моего кода, которую я удаляю в релизе, но использую до этого момента. В полевом тестировании я могу генерировать сообщения об исключениях, чтобы сообщить мне об обнаруженном исключении.


1
Раньше я соглашался с тем, что использование кода - это проблема, но в последнее время кажется, что размер флэш-памяти очень мало влияет на цену микроконтроллера, намного меньше, чем размер оперативной памяти или количество выводов ввода-вывода.
Воутер ван Оойен

Аргумент о динамической памяти важнее IMO. Я видел промышленные системы, которые могли работать без перерыва в течение нескольких недель, но уровень диагностики (написанный на C ++) ограничил бы время перезапуска до 12 часов.
Дмитрий Григорьев

6

Я подумал, что эта анти-С ++ разглагольствование Линуса Торвальдса было интересным.

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

Он говорит не о мире встраиваемых систем, а о разработке ядра Linux. Для меня актуальность заключается в следующем: C ++ требует понимания более широкого контекста, и я могу научиться использовать набор шаблонов объектов, я не доверяю себе, чтобы помнить их, когда мне нужно обновить код через несколько месяцев.

(С другой стороны, в настоящее время я работаю над встроенным устройством, использующим Python (не C ++, но использую ту же самую ООП-парадигму), которое будет иметь именно эту проблему. В мою защиту, это встроенная система, достаточно мощная, чтобы называться ПК 10 лет назад.)


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

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

1
Хаха, да, перегрузка операторов может быть использована, чтобы запутать функцию кода. Если кто-то перегружен оператором, это должно быть сделано по понятным причинам или не сделано вообще. Наследование следует использовать только в особых случаях, когда вы действительно делаете что-то, что похоже на родительское добавление с несколькими дополнениями. Я думаю, что я не каждый использовал бы любую функцию в ООП. Я использовал оба, но во встроенной системе не могу придумать, в каком случае я бы это сделал. Так же, как я думаю, компилятор с ограничением в 80 символов на имена переменных должен быть немедленно удален.
Кортук

2
Я чуть не
высунул

Вы не единственный, но если он работает хорошо и эффективно, я могу простить.
Кортук

6

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

Для маленьких микроконтроллеров (8-битных) никак. Вы просто просите причинить себе боль, вы ничего не получите, и вы потеряете слишком много ресурсов.

Для высокопроизводительных микроконтроллеров (например, 32-разрядных, 10 или 100 МБ для оперативной памяти и хранилища), имеющих приличную ОС, это вполне нормально и, я бы даже сказал, даже рекомендуется.

Итак, вопрос: где граница?

Я не знаю наверняка, но однажды я разработал систему для 16-битного uC с 1 МБ ОЗУ и 1 МБ для хранения на C ++, но потом пожалею об этом. Да, это сработало, но дополнительная работа, которую я имел, не стоила этого. Мне нужно было сделать так, чтобы такие вещи, как исключения, не вызывали утечек (поддержка OS + RTL была довольно ошибочной и ненадежной). Более того, приложение OO обычно делает много небольших выделений, и куча накладных расходов для них была еще одним кошмаром.

Учитывая этот опыт, я бы предположил, что для будущих проектов я выберу C ++ только в системах, по крайней мере, 16-битных, и с как минимум 16 МБ для оперативной памяти и хранилища. Это произвольный предел, и, вероятно, он будет варьироваться в зависимости от типа приложения, стилей кодирования, идиом и т. Д. Но, учитывая предостережения, я бы рекомендовал аналогичный подход.


2
Я должен не согласиться с тем, что не является неожиданной точкой, когда C ++ становится приемлемым из-за системных ресурсов, хорошая практика проектирования может сохранить влияние C ++ на то же место, что и C. Это приводит к коду с проектами ООП, которые занимают одинаковое пространство. Плохо написанный 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)
    {
      if (n <= 0) возврат;
      иначе if (n == 1) {dest [0] = src [0];}
      иначе if (n == 2) {dest [0] = src [0]; dest [1] = src [1];}
      иначе if (n == 3) {dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2];}
      иначе if (n == 4) {dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2]; dest [3] = src [3];}
      иначе memcpy ((void *) dest, (const void *) src, n * sizeof (* src));
    }
    
    Если 'n' может быть вычислено во время компиляции, приведенный выше код будет более эффективным, чем вызов memcpy, но если 'n' не может быть вычислен во время компиляции, сгенерированный код будет намного больше и медленнее, чем код, который просто называется memcpy.

Я знаю, что отец C ++ не слишком увлечен встроенной версией C ++, но я думаю, что она может предложить некоторые значительные улучшения по сравнению с использованием C.

Кто-нибудь знает, рассматривается ли что-либо подобное выше для какого-либо стандарта?



@Joby Taffey: я редактировал свой пост, чтобы не упоминать, что создатель C ++ не увлекался встроенным подмножеством; Я знаю, что были усилия, но, насколько я понимаю, они на самом деле не зашли так далеко. Я действительно думаю, что было бы определенное использование для стандартизированного языка, который поддается 8-битным процессорам, а функции, подобные описанным выше, могут показаться полезными на любой платформе. Слышали ли вы о каких-либо языках, предлагающих такие вещи, как # 3 выше? Это может показаться очень полезным, но я никогда не видел ни одного языка, предлагающего это.
суперкат

«Отец C ++» не имеет опыта программирования встраиваемых систем, так почему кого-то волнует его мнение?
Лундин

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

... но для этого потребуется, чтобы компилятор потратил немало усилий на компиляцию потенциальных замен, которые затем были бы отброшены. Возможность более аккуратно сказать: «Если это константа, делайте это; в противном случае делайте это» без каких-либо «фальстартов», казалось бы, более чистый подход.
суперкат

3

C ++ - это больше, чем один язык программирования:

а) это "лучше" C б) это объектно-ориентированный язык в) это язык, который позволяет нам писать универсальные программы

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

а) Это "лучше" C

C ++ - строго типизированный язык; сильнее, чем C. Ваши программы получат выгоду от этой функции.

Некоторые люди боятся указателей. C ++ включает ссылки. Перегруженные функции.

И стоит сказать: ни одна из этих функций не возникает в больших или медленных программах.

б) это объектно-ориентированный язык

В этом посте кто-то сказал, что абстрагирование машины в микроконтроллерах не очень хорошая идея. Неправильно! Все мы, инженеры встраиваемых систем, всегда абстрагировали машину, просто с другим синтаксисом, чем у C ++. Проблема, которую я вижу в этом аргументе, заключается в том, что некоторые программисты не привыкли мыслить объектами, поэтому они не видят преимуществ ООП.

Всякий раз, когда вы готовы использовать периферийное устройство микроконтроллера, вполне вероятно, что это периферийное устройство было выделено для нас (от вас самих или третьей стороны) в виде драйвера устройства. Как я уже говорил ранее, этот драйвер использует синтаксис 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, ПК, Unix, другие), в режиме реального времени. Безопасность критична. Я представил предыдущего работодателя в STL. Я так больше не делаю.

Некоторый контент Flame

Подходит ли C ++ для встраиваемых систем?

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

С ++ в микроконтроллерах? RTOSes? Тостеры? Встроенные ПК?

Я снова говорю Мех. C + не так уж и плох, но ADA менее болезненный (и это действительно что-то говорит). Если вам повезет, как и мне, вы сможете использовать встроенную Java. Проверенный доступ к массиву и отсутствие арифметики с указателями обеспечивает очень надежный код. Сборщики мусора во встроенной Java не имеют наивысшего приоритета, и объем памяти и повторное использование объектов ограничены, поэтому хорошо разработанный код может работать вечно без GC.

ООП полезен на микроконтроллерах?

Уверенный. UART - это объект ..... DMAC - это объект ...

Объект состояний машин очень прост.

С ++ удаляет программиста слишком далеко от оборудования, чтобы быть эффективным?

Если это не PDP-11, C не ваш процессор. Изначально C ++ был препроцессором поверх C, поэтому Бьярн Страуструп перестал смеяться за медленное моделирование Simula, когда он работал в AT & T. C ++ не ваш процессор.

Принесите MCU, который запускает Java-байт-коды. Программа на Java. Смейтесь над парнями.

Следует ли рассматривать Arduino C ++ (без динамического управления памятью, шаблонов, исключений) как «настоящий C ++»?

Нет. так же, как и все убогие компиляторы C для MCU.

В-четвертых, встроенная Java или встроенная ADA стандартизированы (ish); все остальное - печаль.


2
Легко ли найти микроконтроллеры, поддерживающие Java? Я думаю, что это значительно ограничит выбор. А что вы думаете о снижении производительности (поскольку в ОК у вас обычно не было JIT)? Как насчет влияния непредсказуемости ГХ в системах реального времени?
fceconel

2
Какие микроконтроллеры поддерживают встроенную Java?
Дж. Полфер

www.ajile.com для начинающих.
Тим Уиллискрофт

+1 для Ады. В него встроено много всего, в том числе Arduinos.
Брайан Драммонд

Портативная Java-VM для micros, написанная на языке c, с открытым исходным кодом. dmitry.co/index.php?p=./04.Thoughts/…
Тим

-2

Встроенные системы предназначены для выполнения какой-то конкретной задачи, а не для универсального компьютера для выполнения нескольких задач. Встроенная система представляет собой комбинацию компьютерного оборудования и программного обеспечения. С является матерью всех современных языков. Это низкий уровень, но полный язык и работает со всеми видами оборудования. Таким образом, C / C ++ является оптимальным выбором для разработки программного обеспечения для встраиваемых систем, которое очень полно используется для каждой встраиваемой системы. Как мы знаем, C является развивающимся языком. Операционная система UNIX написана на C. Поскольку успешная разработка программного обеспечения так часто связана с выбором лучшего языка для данного проекта, удивительно обнаружить, что язык C / C ++ зарекомендовал себя как для 8-битных, так и для 64-битных процессоров. ; в системах с байтами, килобайтами и мегабайтами памяти. C имеет преимущество независимости от процессора, что позволяет программистам сосредоточиться на алгоритмах и приложениях, а не на деталях конкретной архитектуры процессора. Однако многие из этих преимуществ в равной степени применимы и к другим языкам высокого уровня. Но C / C ++ преуспел там, где многие другие языки потерпели неудачу?


6
Я действительно не уверен, что это добавляет к обсуждению.
Дэйв Твид

-3

<Напыщенная>

Я думаю, что C ++ - это дерьмовый язык в первую очередь. Если вы хотите использовать ООП, пишите программы на Java. C ++ ничего не делает для обеспечения соблюдения ООП-парадигм, так как прямой доступ к памяти полностью в вашем распоряжении (ab).

Если у вас есть MCU, вы говорите о менее чем 100 КБ флэш-памяти. Вы хотите программировать на языке, абстракция памяти которого: когда я объявляю переменную или массив, он получает память, точка; malloc (иначе называемое «новое» ключевое слово в C ++) должно быть более или менее запрещено использовать во встроенном программном обеспечении, за исключением, возможно, в редких случаях одного вызова во время запуска программы.

Черт, во встроенном программировании (часто) бывают случаи, когда C не достаточно низкоуровневый, и вам нужно делать такие вещи, как распределение переменных в регистрах и писать встроенную сборку, чтобы ужесточить процедуры обработки прерываний (ISR). Такие ключевые слова, как «изменчивый», становятся чертовски важными для понимания. Вы тратите много времени на управление памятью на уровне битов , а не на уровне объектов .

Почему вы хотите обмануть себя, думая, что все проще, чем на самом деле?

</ Декламация>


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

1
Я не голосовал против вас, но я хотел бы отметить, что C ++ не должен обеспечивать ООП, он просто предоставляет инструменты для этого. Обеспечение соблюдения хороших стандартов кодирования является задачей разработчика. Это может помочь, если язык делает это проще, но язык никогда не сделает это самостоятельно. C может быть нечитаемым в некоторых случаях.
Кортук

1
Все языки хороши для чего-то. С ++ это быстро. ООП, если он хорошо сделан, позволяет многим разработчикам работать параллельно и кодировать неизвестное. Я думаю, именно поэтому в разработке игр так много тяги.
Тоби Джаффей

1
Да, я согласен. Причина, по которой я вижу это для мира встраиваемых систем, заключается в том, что огромное количество функций и функций добавлено во многие уже существующие системы и разрабатываются новые системы. Проект становится все больше и больше. Либо нам потребуется больше времени на их разработку, либо мы начнем применять и искажать то, что мир CS уже сделал на ПК.
Кортук

5
Еще один человек, который не понимает C ++ должным образом. Меня всегда удивляет, сколько их.
Ракетный
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.