You are on page 1of 10

Function pointers, Part 3: State machines

edn.com/function-pointers-part-3-state-machines/

Jacob Beningo February 12, 2013

Function pointers can be used for a wide variety


of applications including the implementation of
state machines. Just like any tool, it may not
always be appropriate to use function pointers for
a state machine implementation.

A couple of common methods for implementing


state machines is either the use of if/else
statements or the use of switch/case statements.
In general, it can be a good idea to use the
function pointer implementation if the state
machine has a lot of states or if there is a lot of
code associated with each state that would cause
the complexity of the state machine function to be
high.

Figure 1 contains an example state machine that will be implemented within this article. It
contains only four states and each state only has the ability to transition into one other
state. This will allow a simple examination of how to implement the function pointer
version of a state machine. However, this process can be used for any state machine with
much more complex transitions and states.

The first step to implementing the state machine is to create an enumeration of each state
in the machine. Listing 1 shows the example enumeration that has been defined using a
typedef and given a label of StateType. It contains all four states in addition to
NUM_STATES which provides the number of states in the state machine. Remember
enumerations start at 0!

1/6

Figure 1 Example state machine

Listing 1 State machine type definition


The next step in defining the state machine will be to define the structure for the state
machine. This structure should be capable of storing the state (STATE_A thru STATE_D)
in addition to being able to store a function pointer to that state.

The result of the structure is that an array can be created that holds both the state and
the function that should be executed when the state machine is in that state. Now it is
possible to skip the StateType element of the structure but when creating the state

2/6
machine table it allows the table to be much easier to read and doesn’t affect system
performance other than using a couple of extra bytes of flash. Listing 2 shows the
definition of the StateMachineType structure.

Listing 2 State machine state list


It should be noted that in this definition of StateMachineType the function pointer neither
takes nor returns anything. For a fictitious machine this is fine but in the real world each
state may take a certain type of variable or return one. The structure would be modified to
meet the requirements of the state machine.

Once the structure has been defined, an array of type StateMachineType would be
defined that contains not only each state but also the actual function that should be called
for that state. This can be seen in code Listing 3 .

It is important to keep in mind that the functions, such as Sm_StateA, should at least be
prototyped before this table definition. If it is not, then the compiler will most likely give a
warning or a full error that it cannot find the definition. In addition to the function
prototypes, it will be necessary to define a state variable to store the current state of the
machine. Listing 4 shows both the variable definition and the function prototypes.

Listing 3 State machine table

3/6

Listing 4 State variable and functions


There are a couple of different ways the actual code for the state functions could look
depending on the requirements. First, the state function could run the state code and then
update the state variable (SmState) to the next state.

Alternatively, it could be that the state code runs over and over until some external event
occurs that then causes it to perform the state transition and update the state variable.
This is highly dependent on the application and the defined transition. For simplicities
sake, this example will simply run each states code followed by a forced transition. The
function definitions can be found in code Listing 5 .

4/6

Listing 5 State machine functions


Finally, with the entire framework in place for the state machine, a function needs to be
defined that actually runs the state machine. In general, the author likes to use obvious
naming conventions so in this case the function will be Sm_Run as can be seen in code
Listing 6 .

5/6
In the Sm_Run function, a simple check is performed to make sure that the current state
of the state variable has not exceeded the number of states. If it has, then an exception
can be thrown, otherwise the function pointer to the current state function is called,
thereby running the state.

Listing 6 State machine run function


Observe that the notation used to call the state function is the same as has been used in
previous posts and how simple the state machine code is. Each state is nicely broken up
into individual functions that will make maintenance easier in the future due to
minimization of complexity.

This code could have all been implemented into a single function with an if/else statement
but the complexity of the code would be difficult especially if any of the states had a page
worth of code associated with it which wouldn’t be uncommon. In addition, adding
addition states doesn’t require a change to Sm_Run function! All one needs to do is add
the state to the enumeration, define a function and update the state machine table.

Jacob Beningo is an embedded software consultant who currently works with clients in
more than a dozen countries to dramatically transform their businesses by improving
product quality, cost and time to market. Feel free to contact him at jacob@beningo.com,
at his website www.beningo.com, and sign-up for his monthly Embedded Bytes
Newsletter here.

Related articles :

6/6
29/07/2022, 16:17 Function pointers, Part 3: State machines - EDN

development/4008260/using-finite-state-machines-to-design-software?

utm_source=aspencore&utm_medium=edn>
– Function pointers: An introduction < https://www.edn.com/electronics-
blogs/embedded-basics/4404344/function-pointers---part-1--an-
introduction->

– Function pointers, Part 2: Task scheduling <


https://www.edn.com/electronics-blogs/embedded-
basics/4404895/function-pointers---part-2--task-scheduling>

1 6 C O M M E N T S O N “ F U N C T I O N P O I N T E R S , PA R T 3 : S TAT E
MACHINES”

state-machine.com
February 13, 2013

This implementation requires enumerating states, which really shouldn't be


necessary. Also, placing the function pointers inside an array can be skipped.

States are functions (state-handler functions), so a state-variable should store a


pointer to the cur

 Log in to Reply

Totally_Lost
February 13, 2013

From a defensive programming point of view, a switch/case is SIGNIFICANTLY


safer. This is critical when memory corruption occurs, especially in multi-threaded
applications, or where attacks against the application are likely from external threats.

Having

 Log in to Reply

Totally_Lost
February 13, 2013

Definitely a simpler, easier, implementation, but avoids the implicit type checking
that occurs while using states declared with typedef enum, many would say NOT
better for production code that will be maintained by a junior team over long periods
of time.

 Log in to Reply

Never shut shop with Learn Mo


Totally_Lost
Shopify Plus.
February 15, 2013

https://www.edn.com/function-pointers-part-3-state-machines/ 7/14
29/07/2022, 16:17 Function pointers, Part 3: State machines - EDN

I believe your assumption “The cyclomatic complexity of switch/case statements


rises much more drastically than that of the function pointer based state machine.”
only applies with certain coding styles which fall thru into the next case, that are
problema

 Log in to Reply

Totally_Lost
February 15, 2013

Hi Jacob,

I've been writing drivers and systems level code in C since 1974 … I use function
pointers for personal code, and STRONGLY advocate they should NEVER be used
in production code, unless there is NO OTHER WAY.

As implemented above, switch/case

 Log in to Reply

Totally_Lost
February 15, 2013

Market windows frequently define success and failure of a product, company and
your career. These all hang on the developers ability to write and debug code
quickly, and not introduce failure modes that are difficult to near impossible to
debug.

A piece o

 Log in to Reply

Totally_Lost
February 17, 2013

When using the above case/else state machine design, there is a rigorous safe form
that prevents miscoding state transitions. First we define an explicit PANIC state that
is zero to catch coding/design errors where the next state is not explicitly assigned

 Log in to Reply

David in Norway
February 20, 2013

You don't need to check that the value stored in your variables are valid. You simply
ensure that the variables are always initialised before use, and that every
assignment to them later is valid. This applies to /all/ types of data – enum values,
functi

 Log in to Reply

David in Norway
Never shut shop with
February 20, 2013
Learn Mo
Shopify Plus.
You don't get type checking with enums – in C, they are equivalent to integers. With
the latest C++ enum classes, you get proper type-checking with enums – but not in
https://www.edn.com/function-pointers-part-3-state-machines/ 8/14
29/07/2022, 16:17 Function pointers, Part 3: State machines - EDN
C.

With function pointers, however, you /do/ get proper type checking. In particular,

 Log in to Reply

David in Norway
February 20, 2013

The dispatch function in the article is totally independent of the state machine, the
number of states, and the state changes. You don't get cleaner, easier to
understand, easier to maintain, and safer than that.

It is possible that your methods are bett

 Log in to Reply

David in Norway
February 20, 2013

As you use it here, the state machine struct should not have the state value in it –
only the function pointer. Your definition of StateMachine[] looks like you can order it
any way you want, such as by putting { STATE_B, Sm_StateB } before state A. But

 Log in to Reply

vishu489
June 21, 2013

interesting article jacob for beginner !!!!!!!

can you suggest me any book which will improve my firmware knowledge??

 Log in to Reply

Jacob Beningo
November 16, 2015

Thanks for your comments! In certain respects to whether code is safer I think could
be open to great debate (especially we play devils advocate). A switch/case
statement from a first glance would appear safer. However, if the machine has many
states an

 Log in to Reply

Jacob Beningo
November 16, 2015

One thing I think worth mentioning about junior engineers is that using function
pointers in the code does force them to wrap their minds around new concepts in C.

I remember when I was a junior engineer using large and complex switch/case
statements, I

Never shut shop with


 Log in to Reply
Learn Mo
Shopify Plus.
Jacob Beningo
https://www.edn.com/function-pointers-part-3-state-machines/ 9/14
29/07/2022, 16:17 Function pointers, Part 3: State machines - EDN

November 16, 2015

Thanks for the comments! That is certainly another way to do it! Depending on the
application that may even be a better way.

I like to use the enumeration because it provides a way to check the value stored in
the state variable is valid before the fu

 Log in to Reply

Jacob Beningo
November 16, 2015

Thanks for comments!

 Log in to Reply

L EAVE A REPLY

You must Sign in < https://login.aspencore.com/d045a02d-767d-4f3f-80d7-


695dce25d142/login/authorize?
response_type=code&scope=profile%20email%20openid&client_id=cf5f876c-2b69-4672-
892d-
1a3f9cd881ea&state=6b27ad7b57acdfbabcc2400419ad7046&redirect_uri=https%3A%2F%2Fw
connect-authorize> or
Register < https://login.aspencore.com/d045a02d-767d-4f3f-80d7-
695dce25d142/login/authorize?
response_type=code&scope=profile%20email%20openid&client_id=cf5f876c-2b69-4672-
892d-
1a3f9cd881ea&state=9f63a0f8d116409ec222175cea7c878a&redirect_uri=https%3A%2F%2Fww
connect-authorize> to post a comment.

P R E V I O U S P O S T < H T T P S : / / W W W. E D N . C O M / I N L I G H T E N - D E V E L O P S - S M A R T-
C A R D - A C T I VAT E D - K I O S K S - F O R - U - S - A I R - F O R C E - B A S E S / >
N E X T P O S T < H T T P S : / / W W W. E D N . C O M / N E W- L E D - D R I V I N G - T E C H N I Q U E S -
REDUCE-POWER-IN-LCD-TVS/>

Never shut shop with Learn Mo


Shopify Plus.
https://www.edn.com/function-pointers-part-3-state-machines/ 10/14

You might also like