3 more embedded software tips

In my occasional series of tips for embedded software development, I have three more. This time they are all associated with C/C++ programming …

A lot of embedded programming is about paying attention to details, particularly when using the power of the C language, when there is no safety catch. 🙂

Take care to ensure that an array index never goes negative

Arrays in C/C++ start from zero and go up to n-1 where n is the size of the array. This is straightforward, but there are two issues to think about: underflow and overflow. And these do need to be considered as there is no “run time system” to stop you making mistakes. First, overflow. It is not too hard to avoid running off of the end of array, it just needs code like this:

#define N 99
int arr[N];
for (i=0; i<N; i++)
   arr[N] = i;

Just make sure that < is never replaced by <=

To me, starting counting at zero is totally intuitive, but I started out with assembly language programming, where that is obvious. Just do not let an index get negative. This code is entirely valid:

arr[-5] = 99;

but stupid.

In C, do not set the size of an array that will hold a string; let the compiler do it

When you create an array in C that is going to hold a text string, you have two things to think about. First, you need to be sure that you know how/when the data will be placed into the array. Most embedded development toolkits take care of that, but you should be sure that you know what is going on.

The second point is array size. You could write this:

char str[13] = “Hello world!”;

That would be fine.There are 12 actual characters and a NULL terminator. Alternatively, this is easier:

char str[] = “Hello world!”;

The compiler can count! Interestingly, you can also do this:

char str[12] = “Hello world!”;

which creates a string without a NULL terminator. This would save a byte of memory, if you knew the string length elsewhere. Note that this is illegal in C++.

If a text string is never going to be changed, there is no point in it being in a program section that is [logically] in RAM and this code might be better:

char *str = “Hello world!”;

Never assume the size of data types in C/C++

The traditional data types in C – int, unsigned, char, etc. – are really non-ideal for most embedded applications, when the actual size of data is [or needs to be] know. It is much better to define typedefs with meaningful names – like UINT32 – or use a newer C language variant and utilize the rational data types like uint32_t.

Comments

4 thoughts on “3 more embedded software tips
  • Andrzej Telszewski

    Hi Colin,

    > If a text string is never going to be changed, there is no point in it being in a program section that is [logically] in RAM and this code might be better:

    > char *str = “Hello world!”;
    Haven’t you forgotten _const_ here?
    char const *str = “Hello world!”;


    Best regards,
    Andrzej Telszewski

  • @ Andrzej – It would, indeed, seem logical to say that str is pointing at a constant, though the compiler would most likely figure that out.
    Perhaps I should have:

    const char const *str = “Hello world!”;

    As str should also be a constant, I guess.

  • Andrzej Telszewski

    @Colin
    I guess you meant:
    char const * const str = “Hello world!”;

    and not:
    const char const *str = “Hello world!”;

    ?

    Has the way in which I placed _const_ in my first post mislead you in reading/understanding?
    That would be unfortunate, because I adopted a habit of placing _const_ (and _volataile_ for that matter) after _type_ specifier.
    If I recall correctly, this way comes from Barr and/or Samek.
    I agree with their opinion that after a small shift in mindset, it makes reading of declarations way easier.

    Cheers.


    Best regards,
    Andrzej Telszewski

  • @ Andrzej – I believe that it works either way. I guess I like to think in terms of a “constant char”, instead of a “char that is constant”, which feels back to front to me.

Leave a Reply