Thought Leadership

Embedded code: clear or clever?

By Colin Walls

When developing embedded code, there are various priorities. Top of the list, obviously, is delivering the required functionality and performance. This can be challenging enough. A key requirement is a clear, unambiguous and stable specification. However, at a lower level, the code developer has lots of everyday decisions to make around a number of sometime opposing priorities …

The design of desktop applications is driven by a single criterion: user satisfaction. So, given the design [the user interface in particular] is up to scratch, the main thing is speed. Embedded systems are different as there may or may not be a UI; the device may or may not be real time; cost can be a big issue. The list goes on, but ultimately it results in some prioritization when implementing the code:

  1. code for highest performance
  2. code for predictable performance [deterministic]
  3. code for minimum size
  4. code for minimum power consumption
  5. code for maintainability

Of these, 1-4 are often in tension and finding the balance is the challenge and that depends on the application. To a significant extent these factors are influenced by the higher-level aspects of the implementation: using a real-time operating system, with a power-management framework perhaps; maybe implementing a multicore design. Beyond that, understanding the fine tuning of code generation is worthwhile, as a compiler generally knows best how to achieve many of these goals.

The outlier is #5. Software development is expensive. More time is spent maintaining code [fixing, updating and augmenting] than developing new applications. This means that any effort spent making the code clearer is an investment in the future. There are two bonuses: clearer code is generally more reliable, which means that it needs less maintenance; code written for clarity is very rarely slower or larger than a less clearly expressed algorithm.

Writing clear, maintainable code is possible in most programming languages. Although this may be challenging in, say, Forth of LISP. It is [very] easy to write highly obfuscated code in C, but writing clear code is not difficult. There are numerous coding style guides around and even using a programming standard like MISRA C, that is designed to help make code reliable, tends to lead to more maintainable code. To some extent, a “higher level” language may be helpful, as algorithms may be expressed more naturally. C++ is an obvious possibility. Here is an example:

If an application uses complex numbers, a means to represent them and operate on them is required. In C, a structure makes sense:

struct cx
{
   float real;
   float imag;
};

Then, we can create two variables, initialize them and add one to the other thus:

struct cx x, y;

x.real = 1.0;
x.imag = 2.0;

y.real = 3.0;
y.imag = 4.0;

x.real += y.real;
x.imag += y.imag;

This is reasonably clear and succinct, but can C++ do better? I would say the answer is yes. We can define a class to represent the data, which can include a constructor function to take care of initialization and a function to perform the addition:

class cx
{
   float real;
   float imag;
public:
   cx(float r, float i)
   {
      real = r;
      imag = i;
   }
   void add(cx n)
   {
      real += n.real;
      imag += n.imag;
   }
};

This enables complex variables to be set up and added thus:

cx x(1.0, 2.0), y(3.0, 4.0);

x.add(y);

Although this is neater/clearer that C, there is room for improvement. The add() function can be replaced by an operator overloading function [which has identical code]:

void operator+=(cx n)
{
   real += n.real;
   imag += n.imag;
}

The result is handling of complex numbers in a very natural way:

cx x(1.0, 2.0), y(3.0, 4.0);

x += y;

These features of C++ can certainly help clarify code, particularly the operator overloading. However, a word of warning. It is essential to maintain the intuitive functionality of the operator, as I have here. The += does exactly what the reader of the code would expect. Many years ago, when I was first learning C++, I read a book that demonstrated the overloading of the + operator, which would result in a statement like this:

x + y;

This would add y to x. Go figure.

Leave a Reply

This article first appeared on the Siemens Digital Industries Software blog at https://blogs.sw.siemens.com/embedded-software/2020/07/13/embedded-code-clear-or-clever/