As embedded system developers, we are often baned to work with archaic vendor compilers and more often than not, to base our work on historic code bases. One of the major flip sides of this is that we do not get to use and slowly lose touch with some of the relatively new and exciting C standard and compiler features. We will look at some of them in this article.
Note you might have to use the
--std=c11 flag with your compiler to try out some of these features. I will be using
clang throughout this article. Since clang uses an extended version of C11, the explicit flag is not required. To keep things simple, I am not enabling any extra compilation flags unless otherwise specified.
Link time optimzsation (LTO)
Traditionally the C compiler compiles each file in to an object file and does optimization within these compilation units. Potential cross file optimizations where not visible to the compiler until recently. For a while, the gcc and Clang compilers have been supporting LTO. With LTO, the compiler compiles each file into a source aware annotated object file that has enough information to perform an additional round of optimization at link time. In gcc use the
-flto flag to enable this.
Gone are the days where you write long declarations like
unsigned long long int . The best way to do this now is to use the standard definitions like
uint32_t etc. that is offered by
stdint.h. But then, this is not very new to embedded system developers since we already had this convention going for a while.
In addition to the fixed length types, there are
least types defined in
stdint.h spec. Fast types like
uint_fast32_t guarantees at least
x bits of storage while it might upgrade to a larger type if it has faster performance in the platform.
least types like
int_least64_t provides the most compact number of bits to accommodate the request.
The use of
char to indicate 8 bit data is frowned upon. You should instead use
For pointer math,
intptr_t etc. This is in addition to
uintmax_t is the safest cast to hold the largest integer that a given platform can hold.
Since C99, you can declare variables right before they are used and not just at the beginning of a file or function. Loop variables can also be defined within the loops scope like:
Use of this feature makes the code more readable.
the once pragma
Most new compilers lets you place a
#pragma once at the top of your (header) file to make sure that the file is included only once so that you do not have to use the header file name definition guard in your files.
Arrays can be initialized to known values without having to do
memset by using the following :
The same holds true for structures. However, padding bits might not be initialized.