С++ на микроконтроллерах с малым размером
Мне кажется, люди постоянно уклоняются от или, скорее, яростно выступают против использования С++ на микроконтроллерах, но я не могу для жизни понять, почему. Если вы держитесь подальше от больших библиотек С++ (например, STL), и вы не пытаетесь использовать сложные функции, такие как RTTI или обработку исключений, действительно ли есть какая-либо заметная разница между C vs С++? Имеет ли виртуальное наследование огромное влияние на сложность или след? Я бы подумал, что это будет немного дополнительной памятью, но большая часть сложности будет обработана компилятором, но опять же я не знаю много об этой темной магии. Я просто не понимаю, почему люди очень категоричны в использовании C, за исключением, возможно, для нескольких архитектур, для которых нет компиляторов С++ (если они есть). Похоже, что преимущества модуляции и шаблонов были бы без проблем, даже если вы не могли использовать свой cin или cout.
Я спрашиваю, потому что я занимаюсь некоторыми исследованиями для некоторых хобби проектов, над которыми я хотел бы работать. В идеале, я бы хотел работать с С++ строго для возможности хорошо модулизовать вещи, а также для подхода C "SomeClass_SomeMethod (struct object * this...)" к объектной ориентации. (Я бы предпочел объект Pascal для этих проектов, но, увы, поддержка этого языка не совсем звездная...) Я бы предпочел не переходить на более способный микропроцессор, потому что А. для проектов, которые я делаю, я не нужны тонны ресурсов.. Я не планирую писать 60 государственных фильтров Калмана или кодировать видео 1080p B. (настоящий кикер) Я бы хотел использовать процессоры, доступные в пакетах DIP и QFP. Мне нужна возможность прототипа без пайки или выпечки в моей тостерной печи.
Любые мысли?
Ответы
Ответ 1
В С++ вы, по сути, платите только за то, что используете больше и больше, чем в противном случае являетесь компилятором C, а некоторые из них бесплатны.
Самая большая проблема с некоторыми компиляторами С++ для небольших целей - это полнота доступных реализаций С++ или наличие компилятора С++ вообще.
EETimes/Embedded.com за несколько лет провел ряд статей по этой теме:
В большинстве случаев эти статьи не обязательно должны использовать все С++ во встроенной системе, и они измеряют или объясняют стоимость с точки зрения памяти, скорости и детерминизма различных функций. Какие части, которые вы используете, будут зависеть от характера вашего приложения (например, от ограничений в режиме реального времени), а также от доступных ресурсов и производительности вашей целевой платформы.
Ответ 2
Комитет С++ написал (бесплатный) технический отчет по этому вопросу.
Ответ 3
Конечно, это сильно меняется.
Я бы не использовал виртуальное наследование на "маленьком" MCU. Я даже не использовал бы кучу.
Возможности С++, которые кажутся наиболее привлекательными в этом пространстве, - это пространства имен (для совместного использования программных компонентов между программами для сетевых MCU), шаблонов (например, для параметризации протоколов через порты ввода-вывода) и общих семантических улучшений, таких как static_cast
и менее грубая интеграция.
Но, по крайней мере, в моем кратком набеге на встроенный профессионал, подходящего компилятора С++ просто не было, а дрянной, который был доступен, стоил тысячи в год.
GCC является наиболее способным, широко доступным компилятором С++, доступным для встроенных платформ. Однако поддержка платформы очень неравномерна. Если у вас есть неограниченные ресурсы, EDG заявляет, что они принесут поддержку, превосходящую Comeau, на "вашу" встроенную платформу.
Ответ 4
С++ люди постоянно спрашивают: "Почему вы используете C, а не С++". Я хотел бы знать, почему я должен использовать С++, а не C.
Прежде всего, нужно прийти к осознанию того, что эти два языка являются древними, и оба они имеют ужасный синтаксис. Дискуссия часто, похоже, фокусируется вокруг "вы должны использовать С++, потому что С++ современный, а C старый". В действительности, дебаты об одном любимом вкусе мяса динозавров. Вместо того, чтобы требовать современный язык, подходящий для встраивания, люди проповедуют С++, который никогда не был чем-то вроде странного временного гибридного языка с совместимостью C, в ожидании появления лучшего языка.
Во-вторых, существует миф о том, что С++ объектно-ориентирован, а C нет. Объектная ориентация мозаичного слова сводится к трем вещам:
- 1) Модульная конструкция с автономными объектами, которые не тесно связаны ни с чем другим. Это очень важный атрибут любой программы.
- 2) Частное инкапсулирование данных и сокращение объема данных. Это довольно важный атрибут любой программы.
- 3) Полиморфизм классов: классы, которые наследуют другие классы и ведут себя по-разному, когда унаследованы. Полиморфизм весьма полезен, но гораздо меньше - в небольших встроенных системах.
1) может быть полностью достигнута как в C, так и в С++, это вопрос программирования, а не синтаксиса языка. И это самый важный атрибут OO на сегодняшний день! К сожалению, в любом языковом стандарте нет ничего, говорящего о том, как разработать свою программу. В С++ ничего нет, что автоматически приведет к лучшей модульной конструкции, все это находится в руках программиста.
2) может быть достигнуто как в C, так и в С++. Оба языка уменьшили объем данных. В C частная инкапсуляция выполняется через несколько ужасный синтаксис со статическим ключевым словом в переменных области файла. В С++ это делается более элегантно с конфиденциальными/защищенными.
3) может быть достигнуто как в C, так и в С++. Оба языка имеют ужасный синтаксис для этого. В C вы бы столкнулись со структурами и функциональными интерфейсами для его достижения. В С++ вы можете сделать это менее ужасно, используя наследие и делая функции "виртуальными". Синтаксис С++ и необходимая реализация по-прежнему остаются одним большим беспорядком, хотя немного лучше, чем способ C.
Ни один из языков не даст вам вещи, связанные с OO, красивыми и элегантными способами. Что С++ получает от немного менее неходового синтаксиса, он теряет, когда вы начинаете пробираться через undefined/неопределенное/определяемое реализацией поведение.
Казалось бы, весь аргумент OO не имеет большого значения, С++ не является большим улучшением, когда дело доходит до OO. Тогда что еще есть в С++, что мне понадобится в моей встроенной системе? Выделяется одна вещь: стандартизированный синтаксис ассемблера inline. Это, пожалуй, самое большое преимущество, которое С++ имеет над C, для встроенных систем.
Кроме того, экскременты, STL, шаблоны, RTTI, перегрузка overator, перегрузка функций и т.д. и т.д. - все более или менее бесполезные функции, без которых невозможно жить.
Тогда, в конце концов, реальность приходит, чтобы похлопать вас по лицу: очень мало, если таковые имеются, встроенных компиляторов, которым удалось полностью реализовать С++ в соответствии со стандартом.
Ответ 5
Для "малой площади", где меня будет беспокоиться, это раздувание кода. Если ваш код должен находиться в небольшом фрагменте оборудования, экземпляр класса шаблона
std::vector<int>
имеет свой собственный набор инструкций, отдельно от
std::vector<double>
Таким образом, каждый раз, когда вы создаете новый вектор, компилятор эффективно копирует код для создания нового класса с собственным набором функций, дублируя каждую инструкцию. Если у вас есть ограничения на объем памяти для хранения инструкций, это может стать проблематичным очень быстро. Это становится проблематичным для людей в не встроенных системах.
Что касается производительности во время выполнения, я думаю, что вам нечего беспокоиться. В некоторых случаях, например сортировка, С++ превосходит C.
Ответ 6
есть ли какая-либо заметная разница между C vs С++?
По моему опыту существует большая разница в использовании ОЗУ.
Например: В настоящее время я работаю над С++ для ARM uC с 512 КБ FALSH и 64 КБ ОЗУ.
Использование ОЗУ должно быть меньше 30 кБ, но в два раза больше, потому что каждая константа попадает в ОЗУ.
Это потому, что почти невозможно (по крайней мере, с целями GCC и ARM) убедить компилятор оставить члены класса const во FLASH. Единственный способ добиться этого - использовать классы без конструкторов, объявить все публичные члены const и использовать списки инициализаторов агрегатов.
Чтобы все ухудшилось, С++ не позволяет именам членов в списке инициализаторов, как вы можете делать в обычном C:
struct St { int b; int a[3]; };
static const struct St st_array[2] =
{
[1] = { .a = {1,2,3,}, .b = 10, }, // deliberately disordered to
[0] = { .b = 8, .a = { 4,5,6,}, }, // illustate the value of names.
};
Все C-компиляторы помещают эти константы в сегмент "постоянные данные" (во FLASH).
В С++ вам нужно будет сделать это:
class ClassA // cannot have constructor or destructor
{
public: // const data cannot be private for aggregate initialization
const int b;
const int a[3];
private:
int priv_fn(int i);
public:
int pub_fn();
};
static ClassA classA_array[2] =
{
{ 3, { 8, 9,10,}, }, // aggregate initialization
{ 4, { 9,10,11,}, }, // better get the order right!!!
};
В зависимости от вашего компилятора даже это может не гарантировать, что константы остаются во FLASH.
И да, я знаю, с С++ 0x вы можете использовать списки инициализаторов с конструктором, и это то, что я делаю, но в тот момент, когда у вас есть конструктор, который вызывается во время выполнения, все инициализации становятся динамическими.
Технический отчет (спасибо MSalters) подтверждает следующее:
7.1.2 Конструкторы и ПЗУ
В общем случае константные объекты классов с конструкторами должны быть динамически инициализированы.
Однако в некоторых случаях инициализация времени компиляции может быть выполнена, если статический анализ...
Суть в том, что такой статический анализ не выполняется никаким компилятором, который у меня есть, и если мне нужно ограничить себя классами без конструкторов с public const и без именования инициализатора, тогда я мог бы также написать простой (и объект -ориентированный) C.