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:

/*
 * printHeader.h
 */

#ifndef PRINTHEADER_H_
#define PRINTHEADER_H_

void printString(char *whatToPrint);
void printInt(int intToPrint);
void printLong(long numberToPrint);
void printFloat(float floatToPrint);

#endif /* PRINTHEADER_H_ */

 

and you would use it like this:

/*
 * usePrintHeader.c
 */
#include "../../printTestCpp/src/printHeader.h"
int main (void)
{
   int year=2016;
   char moreTalking[]=" bla bla...";
   printString("Hello world, this is year ");printInt(year);printString(moreTalking);
}

 

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:

//printTestCpp.cpp

#include <iostream>
using namespace std;

int main() 
{
   cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
   return 0;
}

 

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…
pexels-photo-12718 (1)

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):

// SimplePrint.h

#ifndef SIMPLEPRINT_H_
#define SIMPLEPRINT_H_

//Mainly to make it less verbose to use, let's have a struct definition
typedef struct PrintDefStruct PrintDef;

//now define the actual structure
struct PrintDefStruct
{
   //lets define function pointers to do some work:
   const PrintDef*(*str)(char*);
   //note these function pointers always return a pointer to a structure of the same type they reside in.
   const PrintDef*(*intgr)(int);
};

//now, expose the public functions so it can be used in a natural sort of way:
const PrintDef* ourPrint(void);

#endif /* SIMPLEPRINT_H_ */

 

…and an implementation…

//SimplePrint.c

#include "SimplePrint.h"

#include <stdio.h>
#include <stdlib.h>

//we need to declare prototypes so that we can include them in the structure below.
static const PrintDef* my_Str(char* stringToPrint);
static const PrintDef* my_i(int iToPrint);
//... any other print related functions should also be defined ...

//now, lets define our structure with the print functions we have declared.
//This could be seen almost like a "Namespace" variable and gets exposed globally (see the header file):
static const PrintDef ourPrintDef =
{
      my_Str,
      my_i,
      //... any other print related functions should also be added ...
};

//now lets define some example print functions
static const PrintDef* my_Str(char* stringToPrint)
{
   fputs(stringToPrint, stdout);
   return (&ourPrintDef);
}

static const PrintDef* my_i(int iToPrint)
{
   printf("%i", iToPrint);
   return (&ourPrintDef);
}

//add a public function to kick off the chaining action:
const PrintDef* ourPrint(void)
{
   return (&ourPrintDef);
}
//... and any other print-related functions ...

 

Now, let’s try using it:

//main.c

#include <stdio.h>
#include <stdlib.h>

//include our print module
#include "SimplePrint.h"

int main(void)
{
   //define a few things we want to print
   int year = 2016;
   char moreTalking[] = ", bla bla...";

   //now lets try stringing the elements together
   ourPrint()->str("Hello world, this is year ")->intgr(year)->str(moreTalking);

   //and we are done...
   return EXIT_SUCCESS;
}

 

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.

Precautions…

alcohol-party-dinner-drink (1)

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.

Further reading

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.


2 Comments

Avoid the abuse of Function Pointers in C - Firmware programming · December 31, 2017 at 6:16 pm

[…] and stack calculations are not an issue. Note, for example, I have recently spoken of a chaining pattern which uses function pointers in C, which improves […]

Chaining C Functions Together – Firmware Programming · July 14, 2018 at 5:55 pm

[…] This article has moved. Please visit it by clicking here. […]

Leave a Reply

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

%d bloggers like this: