Guidelines for using C++ as an alternative to C in embedded designs: Part 1
Click here to see Part 2.
Embedded software applications are most commonly written in C. For many years, C++ has been seen as the natural successor and has found greater acceptance, but the increase in its usage has been much slower than anticipated.
There are a number of reasons for this. Firstly, embedded developers are quite conservative and prefer to use solutions that are proven rather than novel " "if it ain't broke, don't fix it".
There is also the lesson of experience. Many developers have attempted to use C++ for embedded applications and failed. Such failures may sometimes be attributed to shortcomings in development tools, but most often it is the inappropriate use of the language " treating an embedded system like a desktop computer " that is to blame.
In this two part tutorial, an attempt is made to address some of these issues, to give guidelines to the effective use of C++ for embedded applications and to show that the language has some true benefits to the embedded developer.
One of the key reasons why C++ has gained popularity in the computing world in general is its history. Although it is a modern language, with object oriented capabilities, it has backward compatibility that makes its adoption " learning and application " straightforward.
Figure 1 below gives some insight into the evolution of the language. Later in this series we will look at C/C++ compatibility in more detail.
|Figure 1. The Genealogy of C++|
Limitations of C
Although C is widely used, it has limitations, as it was not designed for embedded applications or for projects of a scale that is now commonplace. Key limitations include:
1) C is extremely powerful and flexible and can therefore be dangerous.(It has low level capabilities - which are useful for embedded " but also represent many pitfalls for the unwary.)
2) Programmers need to be very methodical and disciplined
3) Programmers need to understand how the program behaves at low and high levels (large projects are thus hard to maintain)
4) Programmers need an expert knowledge of the application
However, C++ has powerful object oriented capabilities which can help significantly with addressing the limitations of C:
1) it encapsulates and hides areas of high expertise from non-experts into "objects;" (A test case will demonstrate the encapsulation of expertise later in Part 2 in this series).
2) Objects can be used intuitively by non-experts to implement conceptual designs at a high-level
Like ANSI C, C++ features many enhancements to the original C language in addition to its object oriented capabilities. C++ is not simply a super-set of C, as the two languages evolved in parallel.
However, the language may be learned and applied incrementally, as will be illustrated later in this paper. For the moment, here is a summary of some of the useful language features:
1) Dynamic memory allocation operators. The operators new and delete are alternatives to the library functions malloc() and free() and lead to more readable and less error-prone code.
2) Function prototypes. Iintroduced in C++ and adopted into ANSI C, their use is mandatory.
3) Function parameter default values. A function may have default values for trailing parameters to enhance code readability.
4) Reference parameters. Function parameters may be passed by reference instead of by value (copy). This gives the efficiency of using pointers without the great potential for errors that results from their use. Here is a simple example function:
void swap(int& a,
int temp = a;
b = temp;
4) Inline functions. The code for a (small) function may be declared as being inline " i.e. a copy of the actual code is included at each call site. This improves the speed of execution, but may increase code size. This may be achieved using the inline keyword or by including the code in the body of a class definition. This is only advice to a compiler, which will probably take account of current optimization settings.
5) Function overloading. Multiple functions may be defined with the same name. The compiler would distinguish between them by their unique number/type of parameters. This results in more readable code, with less contrived function naming.
6) Typesafe linkage. In C++, all function names are "mangled" " their names are modified to reflect parameter and returned data types. This enables the linker to perform additional cross-module checking without being required to "know" about C++. This is also the mechanism whereby function overloading is implemented.