Updates:
- 2020-04-30 – Added missing semicolon in code and updated example.
NOTE: This article was originally written a few years ago, so some references may be out of date.
I have been enjoying working on the SirSound project the past month, as well as some fun challenges at my day job. Every now and then I run into something I’d like to do that is not doable in C, or doable but not proper to do in C, or … maybe doable. It’s sometimes difficult for me to find answers when I do not know how to ask the question.
With that said, I have a C question for anyone who might be able to answer it.
Using my multi-track music sequencer as an example, consider representing data like this:
[sequence]
[track]
[note /]
[note /]
[note /]
[/track]
[track]
[note /]
[note /]
[note /]
[/track]
[/sequence]
It’s easy to create a sequence like this in C. Here’s some pseudo code:
track1 = { C, C, C, C };
track2 = { E, E, E, E };
sequence1 = { track1, track 2};
I thought there might be a clever way to do all of this with one initializer. If I treat the data like nested XML (like the first example), I thought it might be possible to do something like this:
typedef struct SentenceStruct SentenceStruct;
struct SentenceStruct
{
char *Word;
SentenceStruct *Next;
};
Something like this allows me to represent that tree of data very easily, and I find many examples of building things like this in C code:
int main()
{
SentenceStruct Word1;
SentenceStruct Word2;
SentenceStruct Word3;
Word1.Word = "sequence";
Word1.Next = &Word2;
Word2.Word = "track";
Word2.Next = &Word3;
Word3.Word = "note1";
Word3.Next = NULL;
SentenceStruct *Word;
Word = &Word1;
while( Word != NULL )
{
printf("%s ", Word->Word);
if (Word->Next == NULL) break;
Word = Word->Next;
}
printf("\n");
return EXIT_SUCCESS;
}
This creates a single linked list of words, then prints them out.
I thought it might be possible to initialize the whole thing, like this:
SentenceStruct sentence =
{
{ "kitchen", { "light", { "ceiling", { "on", NULL }}}};
}
…though the address of “light” is quite different than the address of a structure which contains a pointer that should point to “light”.
I was going to make each one a pointer to an array of words, so I could have a tree of words like the earlier example (with kitchen/light and kitchen/fan):
typedef struct SentenceStruct SentenceStruct;
struct SentenceStruct
{
char *Word;
SentenceStruct *Next[];
}
Does anyone know how (or if) this can be done in C?
Thoughts?

Looks like in C11 you can use a “compound literal”. I’ve yet to mess with them, though I will, so I can keep up, and because some of the stuff there is neat, e.g. you can write
int foo[200] = {[24] = 1, [108] = 6};
and not have to explicitly initialize the elements 0-108.
Check out https://stackoverflow.com/questions/60022421/best-way-to-statically-initialize-a-linked-list-in-c
Oh, I love that. Does it say if it zeros out the rest?
The code below seems to work. The macro makes the initializer a bit less cluttered. Of course you do need to add or remove a closing brace on the last line for each word added or removed.
typedef struct SentenceStruct SentenceStruct;
struct SentenceStruct
{
char *Word;
SentenceStruct *Next;
};
#define WORD(s) &(SentenceStruct){s
SentenceStruct *sentence =
WORD(“kitchen”), WORD(“light”), WORD(“ceiling”), WORD(“on”), NULL
}}}};
Very interesting. Let me give that a shot.
That’s really cool. I was looking at a way to do this for an Arduino music sequencer. I also looked into it when I was implementing CoAP protocol. It works like URL paths. Maybe one device had a few lights and a fan and a temperature sensor on it:
I could POST to that device “/light/0/on” or “/light/2/off” to have it happen. I could GET “/thermometer/0” and get back a temperature.
To create a list of endpoints without redundancy I was trying to do them like:
light 0 1 2 fan 0 thermometer 0Now that you’ve shown me how to string things together, I’m going to see if I can use that to define it like that.