Blog: April 2014

Micro Patterns

| Nico

When I started working for E.S.R.Labs I was pretty new to these whole embedded C/C++ stuff, therefore I had and still have a lot to learn. Learning something is great. As you progress you understand more and more and grasp the intent or ideas of other programmers. Sometimes you even recognize a great idea in a piece of code which seemed to be broken in the first place.

Quite often I discovered that a piece of apparently ugly code or pre-processor construct which seemed inherently broken on first sight was perfectly fine and even clever. Most of the time my first impression was “oh thats damn bad code! That programmer hadn’t much of an idea what good code looks like!”
As I progressed and learned more about the details, the hidden advantages of some constructs were revealed. To be clear, not all of that obfuscated code constructs I discovered turned out to have hidden powers, some really just were bad code! But from others I could learn.

So I tried to think about a good idea how to share my knowledge about some of this tricky constructs. Just like any other programmer I tend to be lazy, so I searched for an existing concept on how to share these ideas. Long story short, I decided to use the basic concept of design patterns. Most software developers know about basic design patterns, or at least they know how their descriptions need to be interpreted. Therefore I will use a description similar to design pattern which I’ll call mirco patterns.

So I’ll present you the first micro pattern in an hopefully long series.

The idea behind the NAM-Pattern, by the way, can also be used for bitfields.

The NAM Pattern

Prerequisites:

A basic understanding of unions, structs and arrays.

Description:

NAM stands for Named Array Members, which gives us a basic idea what this pattern is about. It provides a name for each value of an array or pointer during debugging, without losing the properties of the array (like looping and indexing in a for loop). In order to implement the NAM pattern the array/pointer is wrapped in an union together with an struct. The struct which is also contained in the union will be used to provide a name for each value of the array/pointer (see Example). The first member name in the struct then will be mapped to the first index of the array/pointer element the second member name to the second index and so forth.

When to use:

Ease debugging by providing names for array members.

Advantages:

  • All members can be addressed in a for loop over the array no code duplication for addressing each member.
  • Ease debugging, while debugging code you have an associated name for each member of the array.

Disadvantages:

  • Each time the array size is adjusted the associated struct has to be updated.
  • The size of debug builds will increase because of the additional information which have to be stored for this construct.

Tested with:

  • gcc
  • diab
  • clang

Example:

union 
{
  struct
  {
    uint8_t duty_left_head_light;
    uint8_t duty_right_head_light;
    uint8_t duty_left_brake_light;
    uint8_t duty_right_brake_light;
    
  } DbgNameResolutionStruct;
    
  uint8_t duty[4];
    
} LampDuties;
    
for (int index = 0; index < 4; ++index)
{
   // assing duty's 
   LampDuties.duty[index] = index + 10;
}
...

Result:

Breakpoint 2 at 0x100000f25: file main.cpp, line 26.
(gdb) run
Starting program: /Users/NiCoretti/Projects/nam_pattern/a.out 
Reading symbols for shared libraries +.............................. done
  
Breakpoint 2, main (argc=1, argv=0x7fff5fbff7c8) at main.cpp:26
(gdb) print LampDuties
$1 = {
  DbgNameResolutionStruct = {
  duty_left_head_light = 10 '\n',
  duty_right_head_light = 11 '\v',
  duty_left_brake_light = 12 '\f',
  duty_right_brake_light = 13 '\r'
},
  duty = "\n\v\f\r"
}
(gdb)