Recently I overheard someone lamenting how much they disliked the printf statement in the C language, the main reason being that it’s insecure, and could easily be exploited as a security vulnerability. Well, it can probably easily be abused, which could lead to security issues, but I think a bigger issue with it is that it is not very type safe, leading to various types of bugs. I also feel that it’s not very intuitive to read when it comes to using some of its many formatting specifiers.
This got me thinking about how one could output text in both a typesafe and a more intuitive way.
Well, the first and most obvious way is to simply by writing a library with all the different printf options wrapped by function calls.
The header file may look something like this:
and you would use it like this:
That was simple enough and would work. However, it’s not a very elegant solution. After all, languages like C++ have some really nice syntaxes such as:
Well, we cannot exactly do that in C since there isn’t any overloading and there isn’t any operator overloading. So how else can we achieve something a bit more user-friendly?
Thinking a little out of the box…
Now, what features does C offer us that may be constructive? Well, there are two things that seem useful. We know that C is good with function pointers (in a raw sort of a way). We also know that in C, functions can return structures (or more importantly, pointers to structures). Structures elements can be of the struct type (and of the same struct type as that in which they reside – i.e. a recursive declaration), and functions pointers stored in structures can also be defined to return the structure type in which they reside (also recursive).
What can we build with these simple facts? Well, I came up with a little C idiom that does exactly what we need, allowing chaining using this form of recursion, so let’s see how much cleaner and easier it looks. Here is an example (which should explain the idiom):
…and an implementation…
Now, let’s try using it:
I find the actual usage quite clean and easy to read (in C terms anyway), and when you actually use it, your IDE (if you are using one) syntax completion feature should also help you choose legal members by prompting you with valid options. What is also nice about it is that it keeps the member names within the struct, allowing you to keep them very short (less chance of name collision) and could be seen as a sort of a namespace idiom. Keeping access to the functions behind a struct improves encapsulation and makes it more difficult to dig through the source code (something not generally recommended) and the actual implementations being static reduces their misuse and the potential of them being accessed in a non-intended way. Accessing the struct through a single function call acts as a sort of a gateway, and keeps things looking consistent and regular.
This idiom is not only useful for printf but potentially also useful for any module where you need to chain-related functions together to perform a compound task, as is often done in other languages. If you need to get more sophisticated, you could require the instantiation of a context object to pass to each function as a parameter (as is often done in object-oriented C). Note that there are no clean ways to get decent object orientated behaviour in C since function implementations are completely unaware of which structure their pointers are stored.
In some ways, the implementation of the example above could be seen to have some of the characteristics of a static object in some object-oriented languages (e.g. C#, C++). Note that generally, I am not too much in favour of some of the OO idioms in C when attempts are made to be too object-oriented, especially when inheritance is attempted. I find they get very hackish and not very type-safe.
Like any pattern, it is as important to know when not to use this idiom as it is to know when to use it.
Function pointers can often make the flow of your code difficult to navigate, so try to only use this when you want to actually encapsulate a module. They can also make certain types tools such as local stack size calculators fail to give a correct result. Another price you will pay for the improvements is that it will usually result in a slightly larger binary (a concern on some small embedded devices), and it will likely be slightly slower (worrying about this may, however, might be premature optimization).
Generally, I would recommend this type of idiom to be used in a module that needs good encapsulation and isolation from the rest of the code so that it doesn’t break the flow of the code too much.
Function pointers do have their uses, and when used to make your code safer, more encapsulated, and more readable such as is shown in the example above [if correctly used], and you are not too constrained by memory, I am a lot more comfortable using them.
This has been a fairly brief introduction to the chaining concept in the C language, and one could easily build on it by using it in other contexts. I expect the encapsulation and the clean safe syntax users are encouraged to implement when using this idiom will improve overall system designs. If you have further ideas or comments on the subject please don’t forget to share them.
https://en.wikipedia.org/wiki/Method_chaining This mainly explains the idiom with respect to object-oriented languages.
http://www.gotw.ca/gotw/057.htm This is a very roughly similar C++ implementation that gave me some of the ideas behind this C idiom.