How to create a list that holds different object types using `void*` in C.

I remember being in school back around 1998 and not knowing enough about C to do this. After coding in other languages, then going back to C++ and understanding at a lower level how references and pointers work, this was pretty easy to figure out.

In this exercise I store elements of different types in a forward linked list.
In order to know what to dereference as I iterate through the list’s elements, I’ve put a “.type” field, which has an int value representing the type of the object stored.

The “.value” is simply a void*, which lets me store a pointer of any kind, and it works pretty well.

Here’s the code for your enjoyment, I hope this is useful to C apprentices.

The example shows how you can store native types like int, or more complex char* or even a struct person* (which is the more useful probably to your purposes)

It’s a good exercise to see the uses of the “address of” operator “&”, which is used to initialize pointers (the ‘&’ can also be used differently to create references, which I call in my mind as ‘aliases’, but this is not shown in this example)

I also play with a not so popular syntax to access a pointer’s sub-fields:

(*myPointer).structField == myPointer->structField

to teach you that the -> is a short hand for dereferencing a pointer and accessing one of its fields.

[pastacode lang=”c” manual=”%2F%2F%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%2F%2F%20An%20exercise%20to%20play%20with%20a%20struct%20that%20stores%20anything%20using%20a%20void*%20field.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%2F%2F%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%0A%23include%20%3Cstdio.h%3E%0A%0A%23define%20TRUE%201%0A%0Aint%20TYPE_INT%20%3D%200%3B%0Aint%20TYPE_STRING%20%3D%201%3B%0Aint%20TYPE_BOOLEAN%20%3D%202%3B%0Aint%20TYPE_PERSON%20%3D%203%3B%0A%0Astruct%20node%20%7B%0A%20%20struct%20node*%20next%3B%0A%20%20int%20type%3B%0A%20%20void*%20value%3B%0A%7D%3B%0A%0Astruct%20person%20%7B%0A%20%20char*%20name%3B%0A%20%20int%20age%3B%0A%7D%3B%0A%0Aint%20main(int%20args%2C%20char%20**argv)%20%7B%0A%0A%20%20struct%20person%20aPerson%3B%0A%20%20aPerson.name%20%3D%20%22Angel%22%3B%0A%20%20aPerson.age%20%3D%2035%3B%0A%0A%20%20%2F%2F%20Define%20a%20linked%20list%20of%20objects.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%2F%2F%20We%20use%20that%20.type%20field%20to%20know%20what%20we’re%20dealing%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%2F%2F%20with%20on%20every%20iteration.%20On%20.value%20we%20store%20our%20values.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20struct%20node%20nodes%5B%5D%20%3D%20%7B%0A%20%20%20%20%7B%20.next%20%3D%20%26nodes%5B1%5D%2C%20.type%20%3D%20TYPE_INT%20%20%20%20%2C%20.value%3D1%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%7B%20.next%20%3D%20%26nodes%5B2%5D%2C%20.type%20%3D%20TYPE_STRING%20%2C%20.value%3D%22anyfing%2C%20anyfing!%22%20%7D%2C%0A%20%20%20%20%7B%20.next%20%3D%20%26nodes%5B3%5D%2C%20.type%20%3D%20TYPE_PERSON%20%2C%20.value%3D%26aPerson%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%7B%20.next%20%3D%20NULL%20%20%20%20%20%2C%20.type%20%3D%20TYPE_BOOLEAN%2C%20.value%3DTRUE%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%7D%3B%0A%0A%20%20%2F%2F%20We%20iterate%20through%20the%20list%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20for%20(%20struct%20node%20*currentNode%20%3D%20%26nodes%5B0%5D%3B%20currentNode%3B%20%20currentNode%20%3D%20currentNode-%3Enext)%20%7B%0A%20%20%20%20int%20currentType%20%3D%20(*currentNode).type%3B%0A%20%20%20%20if%20(currentType%20%3D%3D%20TYPE_INT)%20%7B%0A%20%20%20%20%20%20printf(%22%25s%3A%20%25dn%22%2C%20%22-%20INTEGER%22%2C%20(*currentNode).value)%3B%20%2F%2F%20just%20playing%20with%20syntax%2C%20same%20as%20currentNode-%3Evalue%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%7D%20else%20if%20(currentType%20%3D%3D%20TYPE_STRING)%20%7B%0A%20%20%20%20%20%20printf(%22%25s%3A%20%25sn%22%2C%20%22-%20STRING%22%2C%20currentNode-%3Evalue)%3B%0A%20%20%20%20%7D%20else%20if%20(currentType%20%3D%3D%20TYPE_BOOLEAN)%20%7B%0A%20%20%20%20%20%20printf(%22%25s%3A%20%25dn%22%2C%20%22-%20BOOLEAN%20(true%3A1%2C%20false%3A0)%22%2C%20currentNode-%3Evalue)%3B%0A%20%20%20%20%7D%20else%20if%20(currentType%20%3D%3D%20TYPE_PERSON)%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20since%20we’re%20using%20void*%2C%20we%20end%20up%20with%20a%20pointer%20to%20struct%20person%2C%20which%20we%20*dereference%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20into%20a%20struct%20in%20the%20stack.%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20struct%20person%20currentPerson%20%3D%20*(struct%20person*)%20currentNode-%3Evalue%3B%0A%20%20%20%20%20%20%20%20printf(%22%25s%3A%20%25s%20(%25d)n%22%2C%22-%20TYPE_PERSON%22%2C%20currentPerson.name%2C%20currentPerson.age)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20%20%20return%200%3B%0A%7D” message=”” highlight=”” provider=”manual”/]

The output is this:

- INTEGER: 1
- STRING: anyfing, anyfing!
- TYPE_PERSON: Angel (35)
- BOOLEAN (true:1, false:0): 1

Leave a Reply

Your email address will not be published. Required fields are marked *