Page 18 - EETEurope FlipBook February
P. 18
18 EE|Times EUROPE
EMBEDDED
Surprises in C Code
By Colin Walls
IMAGE: SHUTTERSTOCK
he C language is quite flexible and expressive — two of the Of course, this might be written more compactly as:
reasons that it has been successful and resilient against
replacement by “better” languages. An example of its flexi- alpha = beta = gamma = 99;
T bility is the possibility to write an expression in a number of
ways that are functionally equivalent. This enables the style of coding These are 100% equivalent. Or are they?
to be adapted to personal needs, but there’s a catch: Sometimes, Most of the time, these two constructs are entirely equivalent, but
apparently equivalent code has subtle differences. This can occur there are (at least) four situations in which choosing one or the other
even in the simplest code. might make a difference.
It is common for C to provide several ways to do something, all of First, and most prosaically, each variable is separate, and perhaps a
which are exactly equivalent. For example, given that x is a normal comment indicating why it is set to this value might be appropriate.
int variable, each of the following statements will do exactly the Second, it is always good to write maintainable code. At some point
same job: in the future, the code might need to be changed so that all three vari-
ables are not set to the same value. The first format lends itself more
x = x + 1; readily to modification.
x += 1; The third reason relates to substandard compilers, which might
x++; generate code like this for the first construct:
++x;
mov r0, #99
In each case, 1 will be added to x. The only possible difference is mov alpha, r0
that a less capable compiler might generate slightly better code for the mov r0, #99
last two options (which would be a hint that getting a better compiler mov beta, r0
would be worthwhile). mov r0, #99
The two forms of the ++ operator, used in this way, produce the same mov gamma, r0
result. However, if the value of the expression is used, the pre-
increment and post-increment are different, thus: The second construct gives the hint that r0 needs to be loaded only
once. Again, a better compiler would not need the hint.
y = x++; // x before the increment Finally, there is the question of execution order. In the first con-
y = ++x; // x after the increment struct, it is entirely clear that alpha will be assigned first and gamma
last. A compiler will interpret the second construct like this:
Interestingly, the post-increment is slightly more “expensive,” as
storage needs to be allocated to keep the old value of x. However, a alpha = (beta = (gamma = 99));
compiler would probably optimize this away. If the storage is allocated
when the expression value is not used, then a new compiler is definitely This means that the assignment order is reversed. But does that mat-
required. ter? Most of the time, it does not. But if these were device registers, not
If, instead of being an int, x were a pointer to int, the adding 1 would ordinary variables, it might make a big difference. It is very common
have the effect of adding 4 (on a 32-bit machine). If this comes as a big for hardware to need set-up values in order to be loaded in a precise
surprise, a brush-up on pointer arithmetic is in order. sequence.
However, sometimes constructs that appear to be equivalent have So I would say that the multiple assignments in one statement
very subtle differences. construct should be avoided. Overall, although C is a small language, it
Probably the simplest thing that you can do in any programming could be argued that C could be even smaller if there were fewer ways
language is assign a value to a variable. So, in C, we might write: to do things.
The result might be clearer, more maintainable code. ■
alpha = 99;
beta = 99; Colin Walls is an embedded software technologist with Siemens EDA.
gamma = 99; This article was originally published on Embedded.
FEBRUARY 2021 | www.eetimes.eu

