Там какая-либо причина состоит в том, чтобы использовать C вместо C++ для встроенной разработки?

Вопрос

У меня есть два компилятора на моих аппаратных средствах C++ и C89

Я думаю об использовании C++ с классами, но без полиморфизма (для предотвращения vtables). Главные причины я хотел бы использовать C++:

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

Вы видите какие-либо основания, чтобы придерживаться C89 при разработке для очень ограниченных аппаратных средств (4 КБ RAM)?

Заключение

Спасибо за Ваши ответы, они были действительно полезны!

Я продумал предмет, и я буду придерживаться C главным образом потому что:

  1. Легче предсказать фактический код в C, и это действительно важно, если у Вас есть только 4 КБ поршня.
  2. Моя команда состоит главным образом из разработчиков C, таким образом, совершенствовался, функции C++ не будут часто использоваться.
  3. Я нашел путь к подставляемым функциям в моем компиляторе C (C89).

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

77
задан allonhadaya 19 September 2014 в 19:28
поделиться

26 ответов

Две причины использования C поверх C ++:

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

Кроме того, в первоначальном вопросе и ряде комментариев упоминается 4 Кбайт RAM . Для типичного встроенного процессора объем ОЗУ (в основном) не связан с размером кода, так как код хранится и запускается с флэш-памяти.

Конечно, объем места для хранения кода следует учитывать, но как новые, более емкие, процессоры появляются на рынке,

42
ответ дан 24 November 2019 в 10:46
поделиться

Хорошая причина, а иногда и единственная причина в том, что до сих пор нет компилятора C ++ для конкретной встроенной системы. Это касается, например, микроконтроллеров Microchip PIC . Их очень легко написать, и у них есть бесплатный компилятор C (на самом деле, небольшой вариант C), но в поле зрения нет компилятора C ++.

5
ответ дан 24 November 2019 в 10:46
поделиться

Для системы с ограничением до 4 Кбайт памяти я бы использовал C, а не C ++, просто чтобы вы могли быть уверены, что видите все, что происходит. Что касается C ++, так это то, что очень легко использовать гораздо больше ресурсов (как процессора, так и памяти), чем это выглядит как беглый взгляд на код. (О, я просто создам еще один BlerfObject для этого ... упс! Из памяти!)

Вы можете сделать это в C ++, как уже упоминалось (без RTTI, без vtables и т. Д.), Но вы вы потратите столько же времени, чтобы убедиться, что ваше использование C ++ не уйдет от вас, как вы делали бы эквивалент в C.

5
ответ дан 24 November 2019 в 10:46
поделиться

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

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

8
ответ дан 24 November 2019 в 10:46
поделиться

Нет. Любые функции языка C ++, которые могут вызвать проблемы (полиморфизм во время выполнения, RTTI и т. Д.), Могут быть исключены при выполнении встроенной разработки. Существует сообщество разработчиков встраиваемых C ++ (я помню чтение колонок разработчиками встраиваемых систем, использующих C ++ в старом журнале пользователей C / C ++), и я не могу себе представить, что они были бы очень громкими, если бы выбор был таким плохим.

25
ответ дан 24 November 2019 в 10:46
поделиться

Я написал код для встроенной в ARM7 paltform в IAR Workbench. Я настоятельно рекомендую полагаться на шаблоны для оптимизации времени компиляции и прогнозирования пути. Избегайте динамического заброса, как чума. Используйте преимущества / политики в своих интересах, как предписано в книге Андрея Александреску Современный дизайн C ++ .

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

6
ответ дан 24 November 2019 в 10:46
поделиться

Я не вижу причин использовать C вместо C ++. Что бы вы ни делали в C, вы можете делать это и в C ++. Если вы хотите избежать накладных расходов на VMT, не используйте виртуальные методы и полиморфизм.

Однако C ++ может предоставить некоторые очень полезные идиомы без накладных расходов. Один из моих любимых это RAII. Классы не обязательно дорогие с точки зрения памяти или производительности ...

7
ответ дан 24 November 2019 в 10:46
поделиться

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

Кроме того, ++ касается упоминания о Embedded C ++ в ответах. Этот стандарт не на 100% соответствует моим вкусам, но он полезен при принятии решения о том, какие части C ++ вы можете отбросить.

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

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

После этого стандарт Соображения использования динамической памяти применимы: в среде, ограниченной как та, которую вы упоминаете, Вы можете вообще не использовать динамическое распределение. Иногда вы можете избежать использования пулов памяти для небольших динамических распределений или «кадрового» выделения, когда вы предварительно выделяете блок и выбрасываете все это позже.

20
ответ дан 24 November 2019 в 10:46
поделиться

Для цели с очень ограниченным ресурсом, такой как 4 КБ ОЗУ, я бы протестировал воды с некоторыми образцами, прежде чем совершать много усилий, которые не могут быть легко перенесены обратно в чистую реализацию ANSI C.

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

Во встроенной среде вам действительно нужно быть осторожным с распределением памяти. Чтобы обеспечить это, вам может потребоваться определить глобальный оператор new () и его друзей для чего-то, что нельзя даже связать, чтобы вы знали, что это не так. т использовал. С другой стороны, размещение new , вероятно, станет вашим другом, если его использовать разумно вместе со стабильной, поточно-ориентированной и гарантированной с задержкой схемой распределения.

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

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

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

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

В небольшой встроенной среде вы будете либо напрямую подключаться к ядру реального времени, либо работать непосредственно на оборудовании. В любом случае, вам нужно убедиться, что ваш код запуска времени выполнения правильно обрабатывает специфичные для C ++ задачи запуска. Это может быть так же просто, как использование правильных параметров компоновщика, но поскольку обычно прямой контроль над источником для точки сброса при включении питания, вам может потребоваться проверить это, чтобы убедиться, что он делает все. Например, на платформе ColdFire, над которой я работал, инструменты dev поставлялись с модулем CRT0.S, в котором присутствовали инициализаторы C ++, но комментировались. Если бы я использовал его прямо из коробки, я был бы озадачен глобальными объектами, конструкторы которых вообще никогда не запускались.

Кроме того, во встроенной среде часто необходимо инициализировать аппаратные устройства, прежде чем их можно будет использовать, и если нет ОС и загрузчика, то это ваш код, который делает это. Вам нужно помнить, что конструкторы для глобальных объектов запускаются перед вызовом main () , поэтому вам нужно будет изменить локальный CRT0. S (или его эквивалент) для выполнения аппаратной инициализации до до вызова самих глобальных конструкторов. Очевидно, что начало main () слишком поздно.

64
ответ дан 24 November 2019 в 10:46
поделиться

I recommend using the C++ compiler, but limiting your use of C++ specific features. You can program like C in C++ (the C runtime is included when doing C++, though in most embedded applications you don't make use of the standard library anyway).

You can go ahead and use C++ classes etc., just

  • Limit your use of virtual functions (as you've said)
  • Limit your use of templates
  • For an embedded platform, you'll want to override the operator new and/or use placement new for memory allocation.
16
ответ дан 24 November 2019 в 10:46
поделиться

Как инженер прошивки / встроенных систем, я могу рассказать вам, ребята, некоторые причины, по которым C по-прежнему является выбором №1 по сравнению с C ++, и да, я бегло говорю с ними обоими.

1) У некоторых целей, которые мы разрабатываем, есть 64 КБ ОЗУ как для кода, так и для данных, поэтому вы должны убедиться, что каждый байт подсчитан, и да, я занимался оптимизацией кода, чтобы сэкономить 4 байта, что стоило мне 2 часа, это в 2008 году.

2) Каждая функция библиотеки C проверяется перед тем, как мы впускаем ее в окончательный код, из-за ограничения размера, поэтому мы предпочитаем, чтобы люди не использовали деление (без аппаратного делителя, поэтому нужна большая библиотека), malloc (поскольку у нас нет кучи, вся память выделяется из буфера данных в 512-байтовом фрагменте и требует проверки кода) или другой объектно-ориентированной практики, которая несет большие потери. Помните, что каждая библиотечная функция, которую вы используете, имеет значение.

3) Вы когда-нибудь слышали о термине "наложение"? у вас так мало места для кода, что иногда вам приходится заменять его другим набором кода. Если вы вызываете библиотечную функцию, она должна быть резидентной. Если вы используете его только в функции наложения, вы тратите много места, полагаясь на слишком много объектно-ориентированных методов. Таким образом, не предполагайте, что какая-либо функция библиотеки C, не говоря уже о C ++, будет принята.

4) Приведение и даже упаковка (где невыровненная структура данных пересекает границу слова) необходимы из-за ограниченного дизайна оборудования (т. Е. Механизма ECC, который подключен определенным образом) или чтобы справиться с аппаратной ошибкой. Вы не можете предполагать слишком много неявно, так почему объектно-ориентированный его слишком много?

5) Худший сценарий: устранение некоторых из объектно-ориентированных методов заставит разработку думать, прежде чем они будут использовать ресурсы, которые могут взорваться (т.е. выделение 512 байт в стеке, а не из буфера данных), и предотвратить некоторые из потенциально наихудших сценариев, которые не проверяются, или полностью исключить весь путь кода.

6) Мы используем много абстракций, чтобы сохранить аппаратное обеспечение из программного обеспечения и сделать код максимально переносимым и удобным для моделирования. Доступ к оборудованию должен быть заключен в макрос или встроенную функцию, которые условно скомпилированы между разными платформами, тип данных должен быть приведен как размер байта, а не конкретный целевой, использование прямого указателя не допускается (поскольку некоторые платформы предполагают, что ввод-вывод с отображением памяти является То же, что и память данных) и т. д.

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

14
ответ дан 24 November 2019 в 10:46
поделиться

Для проблемы выделения памяти я могу рекомендовать использовать Quantum Platform и ее состояние машинный подход, так как он выделяет все, что вам нужно во время инициализации. Это также помогает облегчить конфликтные ситуации.

Этот продукт работает как на C, так и на C ++.

0
ответ дан 24 November 2019 в 10:46
поделиться

Это зависит от компилятора.

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

Но, учитывая хороший хороший компилятор , нет, нет никаких причин не использовать C ++.

0
ответ дан 24 November 2019 в 10:46
поделиться

Единственная причина, по которой я предпочитаю C IMHO, заключается в том, что компилятор C ++ для вашей платформы не в хорошей форме (с ошибками, плохой оптимизацией и т. Д.).

1
ответ дан 24 November 2019 в 10:46
поделиться

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

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

3
ответ дан 24 November 2019 в 10:46
поделиться

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

1
ответ дан 24 November 2019 в 10:46
поделиться

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

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

2
ответ дан 24 November 2019 в 10:46
поделиться

В общем, нет. C ++ - это супер-набор C. Это было бы особенно актуально для новых проектов.

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

Обратите внимание, что некоторые вещи, такие как полиморфизм, могут быть очень полезными - по сути, это указатели на функции. Если они вам нужны, используйте их с умом.

Также

1
ответ дан 24 November 2019 в 10:46
поделиться

Видите ли вы какую-либо причину придерживаться C89 при разработке для очень ограниченных аппаратное обеспечение (4 КБ ОЗУ)?

Лично, когда речь идет о встроенных приложениях (когда я говорю «встроенные», я не имею в виду winCE, iPhone и т. д. сегодня раздутые встроенные устройства). Я имею в виду ресурс с ограниченными устройствами. Я предпочитаю C, хотя я тоже немного работал с C ++.

Например, устройство, о котором вы говорите, имеет 4 КБ ОЗУ, ну просто по этой причине я бы не стал рассматривать C ++. Конечно, вы можете создать что-то маленькое с использованием C ++ и ограничить его использование в своем приложении, как предлагали другие посты, но C ++ может «потенциально» усложнить / раздуть ваше приложение под прикрытием.

Собираетесь ли вы ссылка статически? Вы можете сравнить статическое фиктивное приложение, используя c ++ и c. Это может привести вас к рассмотрению C вместо. С другой стороны, если вы можете создать приложение C ++ в соответствии с требованиями к памяти, сделайте это. [Тысяча двести девяносто-один] ИМХО, Вообще во встроенных приложениях мне нравится знать все, что происходит. Кто использует память / системные ресурсы, сколько и почему? Когда они освобождают их?

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

2
ответ дан 24 November 2019 в 10:46
поделиться

Мой выбор обычно определяется библиотекой C, которую мы решаем использовать, которая выбирается в зависимости от того, что устройство должно делать. Итак, 9/10 раз ... в конечном итоге это uclibc или newlib и C. Ядро, которое мы используем, также сильно влияет на это, или если мы пишем наше собственное ядро.

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

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

Конечный результат - Устройство либо будет работать и пройти приемочные испытания, либо не будет.

2
ответ дан 24 November 2019 в 10:46
поделиться

Вы встроены в C99. Может быть, вы любите ctors, но дело в том, чтобы правильно получить dtors, может быть грязным. Если оставшаяся единственная причина не использовать C - это пространства имен, я бы действительно придерживался C89. Это потому, что вы можете портировать его на немного другую встроенную платформу. Позже вы можете начать писать на C ++ в том же коде. Но учтите следующее, где C ++ НЕ является надмножеством C. Я знаю, что вы сказали, что у вас есть компилятор C89, но в любом случае это сравнение C ++ с C99, поскольку первый элемент, например, верен для любого C, начиная с K & R.

sizeof 'a' > 1 в C, а не в C ++. Если оставшаяся единственная причина не использовать C - это пространства имен, я бы действительно придерживался C89. Это потому, что вы можете портировать его на немного другую встроенную платформу. Позже вы можете начать писать на C ++ в том же коде. Но учтите следующее, где C ++ НЕ является надмножеством C. Я знаю, что вы сказали, что у вас есть компилятор C89, но в любом случае это сравнение C ++ с C99, поскольку первый элемент, например, верен для любого C, начиная с K & R.

sizeof 'a' > 1 в C, а не в C ++. Если оставшаяся единственная причина не использовать C - это пространства имен, я бы действительно придерживался C89. Это потому, что вы можете портировать его на немного другую встроенную платформу. Позже вы можете начать писать на C ++ в том же коде. Но учтите следующее, где C ++ НЕ является надмножеством C. Я знаю, что вы сказали, что у вас есть компилятор C89, но в любом случае это сравнение C ++ с C99, поскольку первый элемент, например, верен для любого C, начиная с K & R.

sizeof 'a' > 1 в C, а не в C ++. В C у вас есть массивы переменной длины VLA. Пример: func (int i) {int a [i] . В C у вас есть члены массива переменных VAM. Пример: struct {int b; int m [];} .

1
ответ дан 24 November 2019 в 10:46
поделиться

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

Конечно, в В этом случае вы можете проверить два конкретных компилятора.

2
ответ дан 24 November 2019 в 10:46
поделиться

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

Это было предоставлено Bjarne Страуструп на своей домашней странице :

Чтобы узнать, как можно использовать ISO C ++ для программирования серьезных встроенных систем, см. стандарты кодирования C ++ для авиационных транспортных средств JSF .

0
ответ дан 24 November 2019 в 10:46
поделиться

Сколько у вас ПЗУ / флэш-памяти?

4 КБ ОЗУ все еще могут означать, что есть сотни килобайт флэш-памяти для хранения фактического кода и статических данных. ОЗУ такого размера, как правило, предназначается только для переменных, и если вы будете осторожны с ними, вы сможете разместить в памяти довольно большую программу с точки зрения строк кода.

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

Итак, в «малой RAM», «большой FLASH» такая среда, я бы выбрал C в любой день. Обратите внимание, что хороший промежуточный выбор - это C99, который имеет большинство хороших функций C ++ для кода, не основанного на классах.

2
ответ дан 24 November 2019 в 10:46
поделиться

Другой ответ на другой аспект вопроса:

"malloc"

В некоторых предыдущих ответах довольно много говорится об этом. Почему вы вообще думаете, что этот звонок существует? Для действительно небольшой платформы malloc обычно недоступен или определенно необязателен. Реализация динамического распределения памяти имеет смысл, когда у вас есть RTOS в нижней части вашей системы, но до тех пор это чисто опасно.

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

0
ответ дан 24 November 2019 в 10:46
поделиться

В такой ограниченной системе. Просто перейдите на Ассемблер. Дает вам полный контроль над каждым аспектом и не дает накладных расходов.

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

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

-5
ответ дан 24 November 2019 в 10:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: