Embedded Basics – Values and Side Effects

Many embedded software developers learn to program for embedded systems on the fly.  The result is usually an informal introduction to the language that often misses key terminology and leaves gaps of understanding.  Let’s explore a few common C programming language concepts that are often misunderstood by developers.

Often developers early in their career will mistake a side effect as being something bad happening with their program.  The developers’ conception couldn’t be further from the truth.  A side effect is simply stating the fact that there are changes in the state of the execution environment.  A side effect can be something as simple as assigning a variable a value, writing data to a disk or performing a calculation.  There are instances where side effects can be bad news, such as in an expression that is being evaluated by assert.

Many electrical engineers turned embedded software developer will also not have been exposed to what an lvalue or an rvalue are.  Many developers can program in ignorant bliss of what an lvalue or an rvalue really is until they show up in a compiler warning or error message.  Interestingly, lvalues and rvalues have no well-defined definition within the ANSI-C standards.  The basic idea of an lvalue is that it is an expression that refers to an object within memory.  An object in memory can be considered to be a variable or modifiable object that can be set and manipulated.  Consider for example

int Var = 2;

Var is an lvalue and gets its name from being on the left hand side of the operator.  In the example above, the numeral constant 2 is an rvalue.  The value 2 is considered by the C language to be an expression but it does not represent an object in memory and therefore cannot be modified.  Consider an attempt to assign a new value to 2 as stated below:

2 = Var;

The compiler in this instance would see the expression 2, an rvalue that does not represent an object in memory, being attempted to have a new value set to it.  The compiler will state that an lvalue is required and not compile the program.

A clever developer, usually considered to be dangerous trait in real-time systems, can take advantage of the lvalue required effect to insure that equal signs are not accidentally missed in an equivalence expression.  Take for example the following conditional

if(Var = 2)

{

/* Do something useful. */

}

The conditional has an expression that has side effects, that is the object Var has its value set to 2.  Is the side effect on purpose or a typo?  If the side effect is a typo for missing an = then a bug will be introduced to the program that may not be readily apparent to the developer.  The conditional could be rewritten as follows:

if(2 = Var)

{

/* Do something useful. */

}

The expression above will attempt to assign an rvalue and will cause a compiler error.  That’s right, a typo was just discovered that could have resulted in a bug!  Writing the correct expression as

if(2 == Var)

{

/* Do something useful. */

}

will compile correctly.  There is nothing wrong with evaluating an rvalue to see if it matches another rvalue or lvalue!  The technique of evaluating an expression against an rvalue is a trick that is often stated in the MISRA-C standard as a safe programming practice and has been useful more than once to catch a sneaky typo.

Share >

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.