This last week I have been treated to working on a code base written entirely in C code, no C++, all C!
While this has been an interesting challenge there are definitely times when I really missed some of the features provided in C++ and realised how much the standard template library is taken for granted! Anyway, as usual I only really post things on here which are of use to myself as reference at a later date, or items I found it particularly hard to track down elsewhere on the web. This post falls into both categories, and being such a fundamental issue I’m surprised that it took so long to find a solution.
I was working on adding a small lightweight XML library to the existing C code base. I was continuously faced with the problem of requiring some form of expandable buffer, in most cases to hold c strings (null terminated character arrays). The root of the problem is that there is no string type in C, no vectors and no dynamic arrays of any kind. This means that whenever you want to use one of the string functions such as strcopy, strcat or sprintf, you are always required to know the size of the buffer upfront and allocate memory appropriately (freeing the memory when the buffer is disposed).
The main function I was concerned with was sprintf which I required in order to build up strings for the xml documents. The length of the strings produced by sprintf could be very varied and picking a fixed buffer size would in most cases be over the top, and in some cases dangerous as buffer overflows could potentially always occur, corrupting the heap. Luckily I discovered the following technique which allows you to first print the formatted string to a dummy file (no data is actually written to a file and no I/O occurs) using fprintf. Once the fprintf call has completed (assuming the format string / parameters were valid) you can then check the return value to find out exactly how many characters were written to the dummy buffer, providing you with the exact buffer size required for allocation!
Once a buffer of the correct size is allocated sprintf can then be used with the same paramaters to safely fill in the buffer. This method does have its drawbacks. I guess that there is extra overhead incurred in formatting the string twice and gaining a handle to the dummy file. However, as far as I can find this is the only way to do this properly without using fixed size buffers. One work of warning, this technique should work across platforms but “:NULL” should be replaced with “nul” on unix systems. A simple #ifdef UNIX should sort that out!
FILE* f = fopen(":NULL","w"); char* buffer = 0; int n = fprintf(f,"hello %s", "world"); buffer = (char*)malloc(n); sprintf(buffer, "hello %s", "world"); //use buffer free(buffer);