This page is a rough comparison between various printf() implementaions. Not all printf() implementations are equal, while almost all will do the 'd', 'ld', 'u', 'lu', and 's' convertions ... even just adding a precision to one of the int formatters might not do the right thing.
Note that if you want a portable version of printf() in your code, you are much better off using something that natively parses the format string. This ensures that you get the same parsing behaviour on all platforms. Otherwise you are just waiting for your code to be run on some weird platform, and crash or possibly have a security problem. Note that this page gives information about what you should look for in a string library printf implementation, and the problems with just using the host implementation sprintf()/snprintf() calls.
For a comparison of string libraries, some of which include a portable printf() like function, you should look at this page
If you want to learn how printf() implementations are written, you can look at this simple printf code. However if you want to use one I'd recommend one of the better ones from the below list as they have more features and comply to the standards better.
Looks like a conformaing implementation, I reported a couple of corner case bugs that were fixed for 2.3.x. However there is an "issue" where if you pass an invalid multibyte string to the printf like functions then it fails only if you give it a precision.
There is a 'I' flag extension, which is pretty much zero availability elsewhere. There are also the std. extentions of 'S' and 'C'. User formatters are possible, but static format checkers can't cope, and they are limited to single characters.
Looks like a conformaing implementation.
There are quite a few "extentions" like 'D', 'O', 'U' and 'qd' ... which have limited availability elsewhere, however they are deprecated. There are also the std. extentions of 'S' and 'C'. No way to have user defined formatters.
This looks like a conforming implementation.
Supports a bunch of common extentions, like 'm', 'q', 'I'. Has register_printf_function() which is an API copy from GNU libc, and works the same way .. however it has a hard limit on the number of formatters you can add. Currently has a bug where using a i18n positional precision/width will error out of the printf function, if the custom format is defined to not take any arguments.
A simple printf() like function. It's not very stds. compliant, but the code itself is quite nice (mainly because it doesn't try to follow the stds. in many cases) ... if you just need the different types of int outputing, C style strings and don't care about complete stds. compliance this is a good place to start. Note however that I'm somewhat biased, as a very old version of this is what the Vstr printf() like function evolved from.
A simple printf() like function. It's not very stds. compliant, and the code itself is a terrible #ifdef and goto hell which looks much worse than many full implementations. As well as non support for some asspects of the std. 'g' is implemented and broken, precision support is just brainddead and it actually has an option to disable NULL checking in printf (a single if statement -- which stops your programs from crashing) but yet always leaves in and extension which does integer output in base 2.
A conformaing implementation.
There are ways to specify custom formatters, and do it in such a way that static checkers of format strings won't be confused. For a lot more information, see other pages on this site. Note that I wrote this, so I'm possibly biased.
The printf() like function appears to be stds. compliant, note that the previous versions had a number of issues and as other projects just copy the C files into their build you should check which version of trio they used. Of particular note, glib-2.2.1 and libxml2-2.4.24 both have buggy versions. Also worth noting is that the i18n format parameter modifiers have an arbitrary limit, and the double output is custom code that may well not produce the same output as a real implementation and as an I/O library the output model isn't very good for a dynamically expanding string.
User defined formaters are supported, however they are done in such a way that the gcc warning parser (and any other static, non programable, format checker) makes them useless.
The printf implementation calls the host implementation of sprintf/asprintf/etc. if it looks like a valid C99 implementation, and uses the trio library internally otherwise (this is only true as of version 2.2.0 though -- before that it'll just crash in some instances). So it's impossible to have custom formatters (the most obvious annoying fallout of this is that you can't add a GString to a GString as part of a printf() call) and portability is a problem (Although it is supposed to be valid to work with data that has NIL bytes in it doing so loses data in certain cases -- I've submitted a patch for the last problem).
Doesn't understand 'A', 'a', 'F', 'hhd', 'td', 'zd', 'ls', 'lc' or thousands seperators.
There are quite a few "extentions" like 'D', 'O', 'U' and 'qd' ... which have limited availability elsewhere. No way to have user defined formatters.
Not a bad implementation for what is actually done (it seems to be fairly stds. compliant, and has optional platform specific behaviour, it seems to have been written by reading man pages from what I can see -- no small feat), however there is a lot of missing functionality (most of which it readily admits to on the web page). Probably the most noticable are the missing 'F', 'f', 'E', 'e', 'zu', 'zd', 'ju', 'jd', 'td', 'hhd', 'n' etc. formats. Next being missng i18n format modifiers, and the 'n' format.
No way to have user defined formatters.
This code was originally posted to BrugTraq, and has since been hacked on by at least four more people. This is the version in Samba, however there are other versions of this code floating around as it was a favourite for people to just copy and paste into their project. Note that the version of patrick powell's code in in samba is improved upon the original.
This is very poor for stds. compliance, it doesn't even support '#x' to print a leading "0x" before the number. '\'' (thousand modifiers), 'A', 'a', 'F', 'zd', 'td', 'hhd', etc. and i18n format parameter modifiers are all completly missing. An empty precision format doesn't make the precision zero. Unspecified precisions are wrong on double values, and zero specified ones aren't correct for octal etc.
'\'' (thousand modifiers), 'a', 'F', 'Lf', 'lld', 'td', 'zd', 'hhd' , etc. and i18n format parameter modifiers are all completly missing (although 'qd' is available for "long long" ints). 'A' isn't the std. formatter but a custom one. Unspecified precision is broken, as is corner cases for octal etc. also infinity/nan output is not correct with regard to case. Buffer overflows are possible in the integer formatting paths
Apart from the static extensions 'A' and 'I', this is the basis of the OSSP str library implementation.
The sfio97 version available here is the version I looked at, it's possible that the 2002 versions fixes some of the problems. However I didn't get access to it.
This is fairly stds. compliant, for when it was written. However it doesn't support '\'' (thousand seperators) 'td', 'jd', 'zd', 'hhd', 'a', 'A', or i18n parameter modifiers etc. Also double printing of infinity is wrong with regard to case.
This code contains a bunch of static extensions, and no way to define your own.
The printf() like function is a version of Patrick Powell's snprtinf() with a really bad version of a floating point formatter added to it.
Note that before 2003-02-25 the failure path was broken, and would crash.
Note that before 2003-02-25 the failure path was broken, and would crash.
Any corrections or omissions you see in the above, feel free to contact me at the address below