C to C++: 3 Proven Techniques for Embedded Systems Transformation
For 50 years, the C programming language has dominated the embedded software industry. Even today, more than 80% of embedded projects are using C; however, over the last few years, many teams have begun transitioning from C to C++. C++ offers embedded developers a robust, modern set of tools that can be used to write flexible, scalable, and reusable applications. As embedded applications become more complex and connected, teams need a more modern language to help them deal with the software challenges they face.
Quick Links
- Part 1: C to C++: 3 Reasons to Migrate
- Part 2: C to C++: 3 Proven Techniques for Embedded Systems Transformation
- Part 3: C to C++: Bridging the Gap from C Structures to Classes
- Part 4: C to C++: 5 Tips for Refactoring C Code into C++
- Part 5: C to C++: Using Abstract Interfaces to Create Hardware Abstraction Layers (HAL)
- Part 6: C to C++: Templates and Generics – Supercharging Type Flexibility
Unfortunately, many teams are often scared off from using C++. C++ offers a wide range of features for a variety of industries. However, not all features are fit for all purposes. In fact, embedded developers might often hear that C++ is slow, overweight, unsafe, and many other things. These rumors are just that. C++ can be a powerful tool for embedded software developers looking to create a modern embedded system. Today’s post will look at three techniques often employed in C++ and discuss how embedded software teams can leverage them to move from C to C++.
C to C++ Technique #1 – C++ as a better C
A common misconception is that if you adopt C++ for embedded systems, your system will instantly be far bigger and slower than it needs to be. That is absolutely not true. C++ was initially created as a more modern version of C that supported concepts such as objects and inheritance. That is why the language has the cheeky name C++. Its C incremented by 1, although one could argue that the constant evolution of C++ has dramatically upgraded it from C. C is mostly a subset of C++, so if needed, you can still compile your old C code and use it in your C++ applications.
When you first decide that you are going to move to C++, you don’t necessarily have to jump straight into using templates and metaprogramming. Instead, you can start by using C++ as a better C. Many pieces of literature and talks document this on the web, but here are some examples.
First, you can start by creating namespaces for code. A namespace can help you to group standard code and definitions into a single logical space. Just this alone can dramatically clean up a C program. Next, you can clean up all those macros and convert them to const. Next, conditional compilation can be cleaned up by using constexpr. Finally, all those pointers flying around an application can be replaced by references and leveraging unique_ptr to define ownership. The list goes on and on, but I think you get the idea. (We’ll discuss some of these concepts as this series progresses).
If you are interested in diving deeper now, check out Michael Wong’s talk Modern Software Needs Embedded Modern C++ Programming. (It starts slowly with an elementary introduction but gets into some critical topics within 10 minutes or so).
C to C++ Technique #2 – Object-Oriented Programming
Once developers understand the basics of the C++ language and can leverage C++ to write better C programs, they are ready to leverage the power of object-oriented programming. If you follow modern best practices for writing C code, you should find that this transition starts relatively straightforward. Your code modules are probably already organized into units that are good candidates for objects and hopefully already include encapsulation and data hiding.
You can build on your data structures to create class and struct objects at the object-oriented programming stage. The trick here for many developers is to learn the intricacies of objects. You’ll find that you must know about constructors, move semantics, copy, and other concepts to ensure appropriate application behavior. These concepts are a bit trickier to master but can provide developers with scalable and reusable software.
Large inheritance class structures are generally frowned upon because they are not easy to maintain in the long run. Instead, the most maintainable projects make heavy use of composition. So, while you might use some basic inheritance or pure abstract classes to create interfaces, you’ll need to ensure that you understand class diagrams and the various implementation methods to make classes work well together. I have found that developers struggle a little with this, mainly when an RTOS gets involved, but the challenges are easily overcome.
C to C++ Technique #3 – Template Metaprogramming
The last technique we will discuss today to move from C to C++ is adopting template metaprogramming. Templates provide a powerful technique for developers to reuse code and obtain static polymorphism in their applications. Templates can simplify code, maximize reuse, and dramatically simplify code. The techniques, though, often take a little getting used to as they are far more sophisticated than what a typical C programmer is used to encountering. Don’t let that stop you though from pursuing these techniques.
Templates can allow teams to avoid the use of virtual functions in many cases, which come with a small run-time performance hit. (Often not much worse than using a function pointer). Instead, creating objects that obtain their type at run-time can dramatically refactor code and make it far more readable and less error-prone.
Conclusions
Embedded software developers don’t have to adopt every feature supported by C++. In fact, the best C++ adoption starts with a simple transition to using C++ as a better version of C. Once developers understand the basic concepts, they can use more advanced techniques, such as template programming. Most microcontroller-based embedded systems won’t benefit from using full-out metaprogramming; however, templates can be a powerful tool in many applications. What is important is recognizing what features can help improve your code and reuse and which ones are too heavy for a resource-constrained environment.
What you need to decide is how you want to transition from C to C++. Are you going to do it in a single shot, all at once, or gradually adopt C++ techniques and styles? There is no correct answer except for the one that will work best for you and your team.
In the next post, we will look at classes and objects and explore some of their fundamental characteristics.
Other blogs in this series:
Part 1 - C to C++: 3 Reasons to Migrate
- Comments
- Write a Comment Select to add a comment
Hi, I've written something about the Technique #3: Static polymorphism and static interfaces through the CRTP C++ pattern, in case someone wants the benefits of polymorphism, but without incouring in its costs. Maybe it's not pure metaprogramming, but it might clarify the point that the use of certain characteristics of C++ are really good for our embedded systems.
Hope it's useful: https://fjrg76.wordpress.com/2021/05/18/my-view-on...
And in this other post in my main blog I wrote about "How to create interchangeable software components for embedded systems. Decouple the logic from hardware" that walks you though implementing components in C++ for embedded systems, of course:
http://fjrg76.com/2022/04/28/software-components-f...
I did experiment with migrating from C to C++ on one of the projects at work. At first, I felt overwhelmed with the amount of features C++ brings to the table as compared to C. I took the jump and now I am slowly starting to learn and use more of the C++ features. Its may be a long time before I am truly able to use all the "useful" C++ features w.r.t. embedded design.
The object oriented programming does help in keeping the entire codebase clean and easily understandable. Of course, the same can be achieved with C but I experienced that c++ does it better and it might be fruitful in the long run.
Did you know that you can program with objects in plain C? OOP isn't tied to any programming language, but a way of thinking. So in that fashion it's possible to "think" in objects in both C and Pascal.
Abstractions, encapsulation, data hiding, inheritance and polymorhism all that can be achieved with C, but with a syntax that isn't as fancy as that of OOP languages.
Thats true. Its the syntax of C++ that makes OOP a bit pleasant as compared to C.
To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.
Please login (on the right) if you already have an account on this platform.
Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: