snprintf.c
- a portable implementation of snprintf,
including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf

snprintf is a routine to convert numeric and string arguments to formatted strings. It is similar to sprintf(3) provided in a system's C library, yet it requires an additional argument - the buffer size - and it guarantees never to store anything beyond the given buffer, regardless of the format or arguments to be formatted. Some newer operating systems do provide snprintf in their C library, but many do not or do provide an inadequate (slow or idiosyncratic) version, which calls for a portable implementation of this routine.

Author

Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
Copyright © 1999,2000,2001,2002 Mark Martinec. All rights reserved.

Terms and conditions ...

This program is free software; it is dual licensed, the terms of the "Frontier Artistic License" or the "GNU General Public License" can be chosen at your discretion. The chosen license then applies solely and in its entirety. Both licenses come with this Kit.

Features

Supported conversion specifiers and data types

This snprintf only supports the following conversion specifiers: s, c, d, o, u, x, X, p (and synonyms: i, D, U, O - see below) with flags: '-', '+', ' ', '0' and '#'. An asterisk is supported for field width as well as precision.

Length modifiers 'h' (short int), 'l' (long int), and 'll' (long long int) are supported.

NOTE:

If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the length modifier 'll' is recognized but treated the same as 'l', which may cause argument value truncation! Defining SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also handles length modifier 'll'. long long int is a language extension which may not be portable.

Conversion of numeric data (conversion specifiers d, o, u, x, X, p) with length modifiers (none or h, l, ll) is left to the system routine sprintf, but all handling of flags, field width and precision as well as c and s conversions is done very carefully by this portable routine. If a string precision (truncation) is specified (e.g. %.8s) it is guaranteed the string beyond the specified precision will not be referenced.

Length modifiers h, l and ll are ignored for c and s conversions (data types wint_t and wchar_t are not supported).

The following common synonyms for conversion characters are supported:

The D, O and U conversion characters are nonstandard, they are supported for backward compatibility only, and should not be used for new code.

The following is specifically not supported:

It is permitted for str_m to be zero, and it is permitted to specify NULL pointer for resulting string argument if str_m is zero (as per ISO C99).

The return value is the number of characters which would be generated for the given input, excluding the trailing null. If this value is greater or equal to str_m, not all characters from the result have been stored in str, output bytes beyond the (str_m-1) -th character are discarded. If str_m is greater than zero it is guaranteed the resulting string will be null-terminated.

NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, but is different from some older and vendor implementations, and is also different from XPG, XSH5, SUSv2 specifications. For historical discussion on changes in the semantics and standards of snprintf see printf(3) man page in the Linux programmers manual.

Routines asprintf and vasprintf return a pointer (in the ptr argument) to a buffer sufficiently large to hold the resulting string. This pointer should be passed to free(3) to release the allocated storage when it is no longer needed. If sufficient space cannot be allocated, these functions will return -1 and set ptr to be a NULL pointer. These two routines are a GNU C library extensions (glibc), and are present in *BSD libc as well.

Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 characters into the allocated output string, the last character in the allocated buffer then gets the terminating null. If the formatted string length (the return value) is greater than or equal to the str_m argument, the resulting string was truncated and some of the formatted characters were discarded. These routines present a handy way to limit the amount of allocated memory to some sane value.

Availability

http://www.ijs.si/software/snprintf/

Mailing list

There is a very low-traffic mailing list snprintf-announce@ijs.si where announcements about new versions will be posted as well as warnings about threatening bugs if discovered. The posting is restricted to snprintf developer(s).

To subscribe to (or unsubscribe from) the mailing list please visit the list server's web page http://mailman.ijs.si/listinfo/snprintf-announce

You can also subscribe to the list by mailing the command SUBSCRIBE either in the subject or in the message body to the address snprintf-announce-request@ijs.si . You will be asked for confirmation before subscription will be effective.

The list of members is only accessible to the list administrator, so there is no need for concern about automatic e-mail address gatherers.

Questions about the mailing list and concerns for the attention of a person should be sent to snprintf-announce-admin@ijs.si

There is no general discussion list about portable snprintf at the moment. Please send comments and suggestion to the author.

Known problems with the latest version 2.2

Please add the following two #include directives to file snprintf.h if your compiler complains:
#include <stddef.h>
#include <stdarg.h>
Only if using test.c, please replace the line 266:
assert(str_full[sizeof(str_full)-1] == '\0');
in file test.c, with:
assert(str_full[len1f] == '\0');

(Thanks to Tuomo A Turunen for reporting the later problem.)

This will be fixed in the next version.

Revision history

Version 1.3 fixes a runaway loop problem from 1.2. Please upgrade.
Version 2.2 fixes a potential %c conversion problem present in all previous versions.

1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si>

Other implementations of snprintf

I am aware of some other (more or less) portable implementations of snprintf. I do not claim they are free software - please refer to their respective copyright and licensing terms. If you know of other versions please let me know.

Related work

Some notable references

Some references to my portable snprintf as I happened to come across:

Information about applications and packages using my snprintf is appreciated.


In retrospect, it appears that a lot of effort was wasted by many people for not being aware of what others are doing. Sigh.


mm
Last updated: 2003-07-22
(promoting ISO 8601 / EN 28601 standard for specifying date and time!)

Valid HTML 4.0!