Ranges in Array Initializers

In the C language, you need to declare your variables before you can use them. Declare just means that you have to tell the compiler the name of the variable and what type to associate with it.

char key;          /* a single character called "key" */
char response[10]; /* an array of 10 characters called "response" */
uint16_t val;      /* a single unsigned 16-bit value called "val" */

Using variables before initializing them is a common source of bugs, so it’s best practice to initialize your variables before you use them.  In this post, we’ll review C’s ways of initializing variables, and then we’ll take a look at a feature in GCC that might be useful in your code.

The Ways

To avoid bugs, you might expect that variables should have a default value. But variables that are declared inside of a function are not initialized at all, so their value is unpredictable. Global variables can default to zero, but you need to be careful. In embedded systems you can opt to suppress variable zeroing to save time starting the processor. It’s a good habit to explicitly initialize all of your variables and don’t rely on the defaults.

There are two ways to initialize variables; direct assignment and supplying an initial value in the declaration.

char key;
key = '*';          /* Initialization by assignment */

uint16_t val = 42;  /* initial value in the declaration */

Initializing simple variables is reasonably straight forward, you add an assignment to a constant to the declaration of a variable.

The syntax for initializing arrays is a bit weird, see my previous post for examples, but starting in C99, you can specify the elements of an array that you want to initialize and the compiler will provide code to initialize all of the other elements to zero.

int8_t ary_sparse[10] = { [0] = 42, [5] = 17, [9] = 99 };

Should give the same result as:

int8_t ary_sparse[10] = { 42, 0, 0, 0, 0, 17, 0, 0, 0, 99};

Initializing Using Ranges

GCC has provided another range extension to the language to simplify the initialization of arrays further. Instead of initializing single elements of the array, you can specify ranges of elements to initialize. This is a non-standard extension to C, so it might not be appropriate for safety critical programs where all language behaviours must be compliant to a standard. This extension works in compilers other than GCC, like clang, so give it a try and see if your compiler complains.

int8_t ary_simple[10] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 3};
int8_t ary_range[10] = { [0 ... 4] = 1, [5 ... 8] = 2, [9] = 3 };

In this example we have two arrays that are initialized to the same values. The first line spells out each of the values explicitly. The second line uses ranges to achieve the same result.

Of course, you don’t have to specify values for all elements of the array, the compiler will still generate code to fill in the uninitialized values with zero. Be sure to check that there are no weird interactions if you suppress the normal zeroing of memory to speed up the boot process.

Deinitialize

There are a few options for initializing variables and the compilers are giving some richer facilities for initializing arrays. Give them a try and see if they are right for your code.

For more examples of the wacky contortions available for you to initialize your data, see this web page.


This post is part of a series. Please see the other posts here.


ArrayInit.png

 Music to work by: Brian Eno and Harold Bud, The Pearl. 1984 E.G. Records. Produced by Canadian Daniel Lanois.