Written by Jamie Packer, VP of Customer Engineering
C++14 for Embedded Systems
Some people still argue that C++ is not suitable for embedded systems, claiming that it is necessarily inefficient or has unacceptable overheads. With modern compilers, this is no longer true. Using tools such as DRT, C++ can be used on ARM Cortex-M based devices, even those with limited on-chip memory.
Most C++ features have no extra cost in terms of code size or speed. Some features may have a small impact, but these are often worth it for the improved robustness and maintainability of the source code. When using C (or any other language) in embedded systems, it is important to have some understanding of the machine code generated and the effect of source code choices on the generated code.
Many useful features of C++ are purely syntactic and have no effect on the code generated. For example, using overloaded functions (multiple definitions of a function that take different argument types) simply generates “mangled” function names to identify the different functions. So this just automates, and hides, what you would have to do manually to provide differently named functions in C. This means clearer and therefore more maintainable code. Similarly, C++ references are just a safer equivalent to
const pointers (that is, pointers that cannot be modified). Even classes are, in the simple case, equivalent to a
struct and a set of functions that have that
struct as an implicit parameter.
The C99 standard adopted some useful C++ features, such as
const, which are useful to the programmer and allow the compiler to generate more efficient code. C++ has also evolved, with C++14 adding several new features that are useful for embedded systems. Therefore, it is important to use development tools, such as SOMNIUM DRT, that support the latest language standards. Many commercial tools only support old standards, in some cases they have not advanced beyond 2003.
The Wikipedia page has a good summary of the new features in C++14. This article will briefly discuss some of the most useful changes.
Binary literals and digit separators
Embedded code often has to directly address hardware. This can mean being familiar with binary values that represent addresses or fields within control or status registers. C++14 supports binary literals, prefixed with
The standard also introduces the use of ' as a digit separator in numeric literals (for example,
1’000'000). This can be particularly useful with binary literals because of they can, potentially, be long and hard to read. It is also a powerful way of marking byte boundaries or bit fields in registers, for example.
Generalized constant expressions
The concept of constant expressions has always existed. These are expressions that can be evaluated at compile-time, for example
2*3.141592. Such expressions are typically evaluated by the compiler and the result used in the code. The C and C++ specification require constant expressions in various places such as defining an array size or
However, until recently constant expressions were very limited and, in particular, could not contain function calls.
C++11 introduces the
constexpr keyword which can be used to define a function or object constructor that returns a compile-time constant. The C++14 standard relaxes the constraints on what a
constexpr function can contain.
This is a very powerful feature that can simplify your code and also allows the compiler to generate much more efficient code (because, for example, it knows the function has no side effects).
The deprecated attribute
A new attribute,
[[deprecated]], can be used to mark function definitions in order to generate a warning that their use is discouraged. This can be useful in large projects when libraries need to be updated. The attribute can also take a string literal argument that indicates the reason for the warning or suggests an alternative function.
Migrating to C++
If you want to migrate to C++, or just use some of the new features, it is worth noting that existing C code can (nearly always) be compiled with a C++ compiler and will produce exactly the same results. This makes it easy to start from an existing code base and gradually start using the C++ features that are most useful to you. This won’t necessarily give you all the benefits of object-oriented design but it gives you a low-risk route to get started.
For more information on C++ for embedded systems, see the article on embedded.com: Modern C++ in embedded systems.
SOMNIUM DRT Cortex-M IDE supports a wide range of microcontrollers including NXP Kinetis and LPC, Atmel SMART, and STMicroelectronics STM32 devices. DRT is compatible with standard libraries and real-time OSes, semiconductor vendor’s middleware, and makes it easy to import existing projects from other development systems. This makes adopting DRT a simple and low-risk activity.
By using DRT you can be confident that the latest compilers and standards will be supported and that each release will undergo rigorous compliance and functional testing. Our toolchain also generates smaller, faster and lower energy code even when you program in C++. The simple, low-cost licensing model results in lower cost of ownership than other tools.