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

82

Вопрос

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

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

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

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

Заключение

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

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

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

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

Петр Чапла
источник
11
Одно: всегда четко указывайте, на каком языке вы пишете. Не пытайтесь писать программу на "C / C ++". Пишите на C или на C ++, зная, какие языковые функции вы будете использовать, а какие нет.
Дэвид Торнли,
1
См. Также stackoverflow.com/questions/649789/…
Suma
Дайте определение «встроенная разработка»
Марко ван де Вурт,
@DavidThornley, возможно, вы правы в отношении встроенных кейсов, но я был очень приятно удивлен тем, насколько хорошо смешанный код C и C ++ сочетается друг с другом, когда я хочу расширить стандартные отраслевые приложения с открытым исходным кодом, такие как Kamailio, с помощью STL. Я официально поддерживаю такое использование кода STL и C, так как он предлагает огромные функциональные возможности и простоту обслуживания в будущем, создавая при этом почти нулевые проблемы (отсутствие встроенных структур в C ++ является ужасным преступлением против C ++ и должно быть исправлено как можно скорее. ).
user2548100
Пища для размышлений: вот отличная статья, в которой дизайнер и автор ZeroMQ обсуждает, почему он сожалеет о написании кодовой базы на C ++ вместо C. Не то, что я ожидал, и по причинам, не найденным в других местах на этой странице. 250bpm.com/blog:4
user2548100

Ответы:

48

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

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

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

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

Об использовании подмножества C ++ для использования со встроенными системами: теперь существует стандарт MISRA C ++ , на который, возможно, стоит обратить внимание.

РЕДАКТИРОВАТЬ: См. Также этот вопрос , который привел к спору о сравнении C и C ++ для встроенных систем.

Стив Мельникофф
источник
2
См. Мой более длинный ответ ниже: C ++ имеет тенденцию очень затруднять размещение постоянных данных во FLASH.
jakobengblom2
3
Потенциально хорошей причиной использовать C вместо C ++ является стандартный ABI C. Просто для полноты картины.
Крис Лутц,
66

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

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

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

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

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

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

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

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

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

RBerteig
источник
1
Этому нужно больше голосов, чем я могу дать! ОТЛИЧНЫЙ ответ.
Харпер Шелби,
+1, отличный ответ. Но я считаю, что единственный экземпляр шаблона, о котором вам действительно нужно беспокоиться, - это (относительно редкий) рекурсивный тип - для «обычного» нерекурсивного типа создание экземпляров сводится к коду, который вы все равно вводили бы вручную.
j_random_hacker
2
@j_random_hacker, правда. Но привычка к шаблонам может приводить к случайным сюрпризам, когда появляется второй (или третий) экземпляр, когда правильное приведение типа в момент использования могло бы предотвратить это. Это просто то, чего нужно остерегаться.
RBerteig
@RBerteig: Хороший момент, шаблоны допускают меньше возможностей приведения типов => возможно, создаются более четкие экземпляры, чем с нешаблонным кодом.
j_random_hacker
26

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

Харпер Шелби
источник
20

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

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

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

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

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

Leander
источник
16

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

Вы можете использовать классы C ++ и т. Д., Просто

  • Ограничьте использование виртуальных функций (как вы сказали)
  • Ограничьте использование шаблонов
  • Для встроенной платформы вы захотите переопределить оператор new и / или использовать размещение new для выделения памяти.
ковчег
источник
8
Конечно, если вы уже в основном пишете C, вы можете сделать его официальным.
Чак
6
Почему вы ограничиваете использование шаблонов? Я думал, что функции шаблонов могут быть действительно полезны во встроенных системах, например, для развертывания циклов.
Петр Чапла
1
Вы все еще можете использовать шаблоны, но я был бы с ними очень осторожен, поскольку они могут быстро увеличить размер выходного двоичного файла. Конечно, если ваш код запускается непосредственно из ПЗУ или аналогичного, и у вас есть свободное место в ПЗУ, тогда конечно, но кроме этого вам нужно быть осторожным с тем, что вы делаете с шаблонами (каждый экземпляр шаблона - это в основном весь шаблонный код, дублированный снова в финальном исполняемом файле в худшем случае).
arke
14

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

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

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

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

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

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

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

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

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

-какая прошивка парень от SanDisk.

Шинг Вонг
источник
еще в начале 90-х оверлей был очень популярной техникой (по крайней мере, в мире DOS)
psihodelia
Хорошие моменты Шинг. C ++ чувствует себя борцом сумо в телефонной будке в проектах, где функциональность ограничена, а ресурсы еще более ограничены.
4
Я считаю, что этот ответ очень субъективен и не содержит конкретных аргументов.
Venemo 05
1
C ++ не обязательно означает «объектно-ориентированный».
Мартин Боннер поддерживает Монику
1
Это просто неправда, что задачи встроенной системы не абстрактны по своей природе. Вы сами сказали в пункте 6): «мы действительно используем много абстракций, чтобы сохранить hw от sw и сделать код максимально переносимым» :-) Кстати: «абстракция» не обязательно подразумевает «полиморфизм».
Даниэле Палластрелли
9

Лично я предпочитаю C, потому что:

  • Я знаю, что делает каждая строчка кода (и стоит ли)
  • Я недостаточно хорошо знаю C ++, чтобы знать, что делает каждая строка кода (и стоит ли)

Почему люди так говорят? Вы не узнаете, что делает каждая строка C, если не проверите вывод asm. То же самое и с C ++.

Например, что asm производит этот невинный оператор:

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

Это выглядит довольно невинно, но компилятор на основе gcc создает этот asm для 8-битного микроконтроллера.

CLRF 0x1f, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1f, F, ACCESS
MOVWF 0x1e, ACCESS
MOVLW 0xf9
MOVF 0xfdb, W, ACCESS
ADDWF 0x1e, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfa
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1f, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x1c
NOP
MOVFF 0xfef, 0x1d
NOP
MOVLW 0x1
CLRF 0x1b, ACCESS
RLCF 0xfdb, W, ACCESS
ANDLW 0xfe
RLCF 0x1b, F, ACCESS
MOVWF 0x1a, ACCESS
MOVLW 0xfb
MOVF 0xfdb, W, ACCESS
ADDWF 0x1a, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfc
MOVF 0xfdb, W, ACCESS
ADDWFC 0x1b, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0xfee, 0x18
NOP
MOVFF 0xfef, 0x19
NOP
MOVFF 0x18, 0x8
NOP
MOVFF 0x19, 0x9
NOP
MOVFF 0x1c, 0xd
NOP
MOVFF 0x1d, 0xe
NOP
CALL 0x2142, 0
NOP
MOVFF 0x6, 0x16
NOP
MOVFF 0x7, 0x17
NOP
CLRF 0x15, ACCESS
RLCF 0xfdf, W, ACCESS
ANDLW 0xfe
RLCF 0x15, F, ACCESS
MOVWF 0x14, ACCESS
MOVLW 0xfd
MOVF 0xfdb, W, ACCESS
ADDWF 0x14, W, ACCESS
MOVWF 0xfe9, ACCESS
MOVLW 0xfe
MOVF 0xfdb, W, ACCESS
ADDWFC 0x15, W, ACCESS
MOVWF 0xfea, ACCESS
MOVFF 0x16, 0xfee
NOP
MOVFF 0x17, 0xfed
NOP

Количество производимых инструкций во многом зависит от:

  • Размеры a, b и c.
  • хранятся ли эти указатели в стеке или являются глобальными
  • находятся ли я, j и k в стеке или глобальные

Это особенно верно в крошечном встроенном мире, где процессоры просто не настроены для обработки C. Итак, я бы ответил, что C и C ++ так же плохи, как и друг друга, если вы всегда не проверяете вывод asm, и в этом случае они ничем не хуже друг друга.

Хьюго

Ракетмагнит
источник
2
Также обратите внимание, что в середине всего того, что на самом деле вызывает функцию умножения, есть инструкция вызова. Весь этот код даже не является инструкцией умножения!
Rocketmagnet
Кто-то, знакомый с микрометром, обычно знает простой способ изолированно обрабатывать каждую часть кода C, и достойный компилятор не должен создавать код хуже этого. Единственный способ, которым приведенное выше выражение может быть эффективно обработано, - это сделать предположения, которые могут не подходить для компилятора C.
supercat
8

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

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

user21714
источник
+1, прозрачность всегда важна, и, вероятно, в большей степени для ограниченной среды с (предположительно) ограниченными инструментами отладки.
j_random_hacker
7

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

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

Кэтэлин Питиш
источник
6

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

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

GregC
источник
5

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

гулять
источник
1
Comeau Computing ( comeaucomputing.com ) продает компилятор C ++, который компилируется в C.
Томас Л. Холадей
3
Фу. Этот сайт вызвал рвоту.
Shoosh 01
@shoosh: Да, дизайн сайта ужасен. Однако сам компилятор считается лидером в этой области, по крайней мере, с точки зрения соответствия стандартам (у меня нет информации о производительности).
j_random_hacker
Этот веб-сайт заставляет меня чувствовать, что я попал в ловушку живого, дышащего и ОЧЕНЬ сердитого фруктового салата.
Тим Пост
5

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

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

Майкл Кон
источник
2
Ваше последнее предложение правильное, но неуместное, поскольку C ++ предлагает другие преимущества перед C, которые (могут) склонить чашу весов. Петр уже упоминал о некоторых из этих преимуществ (нулевой стоимости).
Конрад Рудольф
5

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

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

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

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

Я, наверное, хорошо вписываюсь в форму программиста - люблю управление. На мой взгляд, это не личный недостаток программиста. Контроль - это то, за что нам платят. Точнее, БЕЗУПРЕЧНЫЙ контроль. C дает вам гораздо больше контроля, чем C ++.

Отменить
источник
Мартин Систрик, автор ZeroMQ, высказал почти то же самое в своем обсуждении того, почему он теперь хочет, чтобы он написал ZeroMQ на C, а не на C ++. Проверьте это 250bpm.com/blog:8
user2548100
3

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

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

Марко ван де Вурт
источник
2

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

Если вы не собираетесь использовать возможности C ++ для удовлетворения потребностей, используйте C.

Оливер
источник
Является ли язык однозначным, зависит от того, расценивает ли он его как определение вещей, которые раньше считались здравым смыслом, но в настоящее время нет [например, компилятор для 32-битного оборудования с беззвучным переносом двух дополнительных компонентов должен обрабатывать что-то вроде того, unsigned mul(unsigned short x, unsigned short y) { return x*y;}что не имеет побочные эффекты, даже если продукт превышает 2147483647, или что следует рассматривать void get_float_bits(float *fp, uint32_t n) { *(uint32_t)fp = n; }как возможное изменение значения a float].
supercat
2

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

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

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

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

ИМХО, вообще во встраиваемых приложениях мне нравится все, что происходит. Кто использует память / системные ресурсы, сколько и почему? Когда они их освобождают?

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

Стив Лазаридис
источник
1
Я обязательно сравню два компилятора. (между прочим. Я не могу установить динамическое соединение, так как отсутствует операционная система)
Петр Чапла
2

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

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

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

В конечном итоге устройство либо будет работать и пройти приемочные испытания, либо нет. Если вы можете реализовать ограничения foo в стеке xx и yy heap, используя язык z, сделайте это, используйте все, что делает вас более продуктивным.

Лично я предпочитаю C, потому что:

  • Я знаю, что делает каждая строчка кода (и стоит ли)
  • Я недостаточно хорошо знаю C ++, чтобы знать, что делает каждая строка кода (и стоит ли)

Да, мне нравится C ++, но я знаю его не так хорошо, как стандартный C.

Теперь, если вы можете сказать обратное, хорошо, используйте то, что вы знаете :) Если он работает, проходит тесты и т.д .. в чем проблема?

Тим Пост
источник
2
> # Я знаю, что делает каждая строка кода (и сколько стоит). Написав компиляторы, я не был бы так уверен в этом ... хороший компилятор C может делать с вашим кодом довольно неожиданные вещи, так как он имеет хороший глобальный обзор вещи. Он не компилируется построчно.
jakobengblom2
@ jakobengblom2: Для встраиваемой разработки постоянная производительность часто важнее максимальной производительности. Если кто-то пытается определить, будет ли часть кода соответствовать требованиям по времени, использование компилятором оптимизаций, которые будут использоваться в «тестовой» прошивке, которая не будет работать в реальной прошивке, будет менее чем полезным.
supercat
2

Сколько у вас ROM / FLASH?

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

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

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

jakobengblom2
источник
3
Есть ли причина, по которой та же структура, которая была бы помещена во флэш-память в C, не попала бы в Flash в C ++? Вам не нужно добавлять конструктор в вашу структуру на C ++.
jalf
1

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

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

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

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

Foredecker
источник
2
C ++, строго говоря, не является строгим надмножеством C, но эта конкретная деталь не особенно важна в данном контексте.
Arafangion
1

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

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

GregC
источник
1

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

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

Ишай
источник
1
Связано: ключевое слово restrict, насколько мне известно, является единственной связанной с оптимизацией конструкцией C, отсутствующей в C ++ (также C ++ 11).
Йохан Лундберг,
1

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

Неманья Трифунович
источник
А как насчет использования памяти / ресурсов?
Стив Лазаридис,
Что насчет этого? Для компилятора C ++ нет причин создавать менее эффективный код, чем для C, за исключением случаев, когда в коде используется RTTI, чего никто не делает во встроенных системах.
Неманья Трифунович
1

У вас есть встроенный в C99. Может быть, вам нравятся ctors, но работа с ними может быть беспорядочной. Если оставшаяся единственная причина не использовать 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
Нет. Я хочу упомянуть, что в C у вас есть (sizeof 'a') == sizeof (int). В то время как в C ++ у вас есть , что 1 == SizeOf «а»
гепт
1
Не говоря уже о "int * a; ...; a = (int *) malloc (size * sizeof (int));" - это способ выделения памяти, который работает в C и C ++, и его не следует использовать ни в одном из них. Используйте либо "a = malloc (size * sizeof (int));" или "вектор <int> a (размер);" или даже «int * a = new int [size];» вместо.
Дэвид Торнли,
1
Я не понимаю твоего мнения о докторах. Все дело в том, что они делают остальную часть вашего кода менее беспорядочной.
jalf
1
+1, не уверен, почему этот пост получил такую ​​плохую репутацию. Но я согласен с jalf, деструкторы значительно упрощают код при правильном использовании (RAII). (Можно сказать, что они «работают за кулисами», но они делают только то, что правильный код все равно делал бы вручную.)
j_random_hacker
1
Я думаю, что то, что я указываю, очень актуально для вопроса. Я также придерживаюсь своего утверждения, что dtors могут быть трудными, и причина именно в том, что это происходит автоматически. Я получил минусовые баллы - вот и все. Думаю, это потому, что я не говорю «ДА, иди на C ++, это здорово».
сентябрь
1

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

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

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

Jalf
источник
1

Сразу хочу сказать, что не существует системы с «НЕОГРАНИЧЕННЫМИ» ресурсами. Все в этом мире ограничено, и КАЖДОЕ приложение должно учитывать использование ресурсов, независимо от того, является ли оно ASM, C, JAVA или JavaScript. Манекены, которые выделяют несколько мегабайт «на всякий случай», делают iPhone 7, Pixel и другие устройства крайне утомительными. Неважно, 4кб у вас или 40Гб.

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

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

Алексей Панютин
источник
0

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

Он был предоставлен Бьярном Страуструпом на его домашней странице. :

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

Петр Чапла
источник
Что ж, летающие штуки, как правило, имеют процессоры PPC с гигабайтами оперативной памяти. Не обычная встроенная система с ограниченными ресурсами.
jakobengblom2
0

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

"маллок"

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

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

jakobengblom2
источник
0

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

mohammed_thoyyib_tk
источник
0

Я рекомендую C ++ с ограничениями и примечаниями.

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

  2. Скорость. C может быть быстрее, чем C ++, но убедитесь, что прирост скорости невелик. Итак, вы можете перейти на C ++. Разрабатывайте свои алгоритмы, тестируйте их и делайте быстрее только при необходимости (!). Используйте профилировщики, чтобы указать узкие места и переписать их внешне "C" способом для достижения скорости C. (Если это все еще медленно, внедрите эту часть в ASM)

  3. Двоичный размер. Коды C ++ больше, но вот отличный ответ, в котором рассказывается о деталях. Размер скомпилированного двоичного кода данного кода C будет одинаковым, независимо от того, был ли он скомпилирован с использованием компилятора C или C ++. «Размер исполняемого файла зависит не от языка, а от библиотек, которые вы включаете в свой проект». Переход с C ++ , но избежать дополнительных функций, как streams, string, new, virtualфункция и т.д. Обзор всех функций библиотеки , прежде чем позволить им в конечном коде, из - за ограничение размера (на основании этого ответа)

бетонталпфа
источник