OpenBSD manual page server

Manual Page Search Parameters

PRINTF(3) Library Functions Manual PRINTF(3)

printf, fprintf, sprintf, snprintf, asprintf, dprintf, vprintf, vfprintf, vsprintf, vsnprintf, vasprintf, vdprintfformatted output conversion

#include <stdio.h>

int
printf(const char *format, ...);

int
fprintf(FILE *stream, const char *format, ...);

int
sprintf(char *str, const char *format, ...);

int
snprintf(char *str, size_t size, const char *format, ...);

int
asprintf(char **ret, const char *format, ...);

int
dprintf(int fd, const char * restrict format, ...);

#include <stdarg.h>
#include <stdio.h>

int
vprintf(const char *format, va_list ap);

int
vfprintf(FILE *stream, const char *format, va_list ap);

int
vsprintf(char *str, const char *format, va_list ap);

int
vsnprintf(char *str, size_t size, const char *format, va_list ap);

int
vasprintf(char **ret, const char *format, va_list ap);

int
vdprintf(int fd, const char * restrict format, va_list ap);

The () family of functions produce output according to the given format as described below. This format may contain “conversion specifiers”; the results of such conversions, if any, depend on the arguments following the format string.

The () and () functions write output to the standard output stream, ; () and () write output to the supplied stream pointer stream; () and () write output to the given file descriptor; sprintf(), snprintf(), vsprintf(), and vsnprintf() write to the character string str; () and () write to a dynamically allocated string that is stored in ret.

These functions write the output under the control of a format string that specifies how subsequent arguments (or arguments accessed via the variable-length argument facilities of va_start(3)) are converted for output.

() and () write at most size-1 characters to str, followed by a terminating ‘\0’. If size is zero, no characters are written and str may be a NULL pointer.

() and () effectively assume an infinite size; their use is not recommended.

The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream, and conversion specifications, each of which results in fetching zero or more subsequent arguments. The arguments must correspond properly (after type promotion) with the conversion specifiers.

The overall syntax of a conversion specification is:

%[argno$][flags][width][.precision][size]conversion

Not all combinations of these parts are meaningful; see the description of the individual conversion specifiers for details.

The parts of a conversion specification are as follows:

A literal percent character begins a conversion specification.
argno$
An unsigned decimal digit string followed by a dollar character specifies the index of the next argument to access. By default, the argument following the last argument accessed is used. Arguments are numbered starting at 1.
flags
Zero or more of the following flag characters can be given:
(hash)
Use an alternate form for the output. The effect differs depending on the conversion specifier.
‘ ’ (space)
For signed conversions, print a space character before a positive number.
(plus)
For signed conversions, always print a sign before the number, even if it is positive. This overrides the space flag if both are specified.
(zero)
Pad numbers with leading zeros instead of space characters to fill the field width. This flag is ignored if the precision modifier is also given, which in this case specifies mindigits.
- (minus)
Left adjust: pad to the field width with space characters on the right rather than on the left. This overrides the ‘0’ flag if both are specified.
width
An unsigned decimal digit string specifies a minimum field width in bytes. Unless the ‘0’ or ‘-’ flag is given, the value is right adjusted in the field and padded with space characters on the left. By default, no padding is added. In no case does a non-existent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.
.precision
The meaning of an unsigned decimal digit string prefixed with a period character depends on the conversion specifier: it provides the minimum number of digits for integer conversions, of decimals for some floating point conversions and of significant digits for others, or the maximum number of bytes to print for string conversions.

A field width or precision, or both, may alternatively be indicated as *[argno$], i.e. as an asterisk optionally followed by an unsigned decimal digit string and a dollar sign. In this case, an additional int argument supplies the field width or precision. If a single conversion specification tries to use arguments both with and without argno$ modifiers, the result is undefined.

size
An argument size modifier. The syntax, the precise meaning, and the default size of the argument depend on the following conversion character.
conversion
Each conversion specification ends with a conversion specifier, which is a single letter determining which argument type is expected and how it is formatted.

The conversion specifiers are:

%[argno$][#][ |+][-|0][width][.hexadecimals][L|l]a

The double argument is converted to the hexadecimal notation [-]h.hhh±d with one digit before the hexadecimal point. If specified, the number is rounded to hexadecimals after the hexadecimal point; otherwise, enough digits are printed to represent it exactly. The hexadecimal point is only printed if at least one digit follows it or if the ‘#’ flag is given.

The exponent is expressed in base 2, not in base 16. Consequently, there are multiple ways to represent a number in this format. For example, 0x3.24p+0, 0x6.48p-1, and 0xc.9p-2 are all equivalent. The format chosen depends on the internal representation of the number, but the implementation guarantees that the length of the mantissa is minimized. Zeroes are always represented with a mantissa of ‘0’ (preceded by a sign if appropriate) and an exponent of ‘+0’.

If the argument is infinity, it is converted to ‘[-]inf’. If the argument is not-a-number (NaN), it is converted to ‘[-]nan’.

%La is similar to %a except that it takes an argument of long double. %la (ell a) is an alias for %a.

Identical to %a except that upper case is used, i.e. ‘0X’ for the prefix, ‘0123456789ABCDEF’ for the digits, ‘P’ to introduce the exponent, and ‘[-]INF’ and ‘[-]NAN’ for infinity and not-a-number, respectively.
%[argno$][-][width]c

The int argument is converted to an unsigned char, and the resulting single-byte character is written, with optional padding.

%[argno$][-][width]lc

The wint_t argument is converted to a multibyte character according to the current LC_CTYPE locale(1), and that character is written. For example, under a UTF-8 locale on OpenBSD, ‘printf("%lc", 0x03c0)’ writes the greek letter pi, whereas the same call fails under the default POSIX locale. Padding assures at least width bytes are printed; the number of characters printed may be smaller, and the number of display columns occupied may be smaller or larger.

%[argno$][ |+][-|0][width][.mindigits][size]d

The int argument is converted to signed decimal notation. If specified, at least mindigits are printed, padding with leading zeros if needed. The following are similar to %d except that they take an argument of a different size:

signed char
signed short
signed int
signed long (percent ell dee)
signed long long (percent ell ell dee)
intmax_t
ptrdiff_t
ssize_t
quad_t (deprecated)
A deprecated alias for %ld.
%[argno$][#][ |+][-|0][width][.decimals][L|l]e

The double argument is rounded and converted to the scientific notation [-]d.dddddd±dd with one digit before the decimal point and decimals, or six digits by default, after it. If decimals is zero and the ‘#’ flag is not given, the decimal point is omitted. The exponent always contains at least two digits; if the value is zero, the exponent is ‘+00’. If the argument is infinity, it is converted to ‘[-]inf’. If the argument is not-a-number (NaN), it is converted to ‘[-]nan’.

%Le is similar to %e except that it takes an argument of long double. %le (ell e) is an alias for %e.

Identical to %e except that upper case is used, i.e. ‘E’ instead of ‘e’ to introduce the exponent and ‘[-]INF’ and ‘[-]NAN’ for infinity and not-a-number, respectively.
%[argno$][#][ |+][-|0][width][.decimals][L|l]f

The double argument is rounded and converted to the decimal notation [-]ddd.dddddd with decimals, or six digits by default, after the decimal point. If decimals is zero and the ‘#’ flag is not given, the decimal point is omitted. If a decimal point appears, at least one digit appears before it. If the argument is infinity, it is converted to ‘[-]inf’. If the argument is not-a-number (NaN), it is converted to ‘[-]nan’.

%Lf is similar to %f except that it takes an argument of long double. %lf (ell eff) is an alias for %f.

Identical to %f except that upper case is used, i.e. ‘[-]INF’ and ‘[-]NAN’ for infinity and not-a-number, respectively.
%[argno$][#][ |+][-|0][width][.significant][L|l]g

The double argument is converted in style %f or %e (general floating point notation) with significant digits, or six significant digits by default. If significant is zero, one is used instead. Style %e is used if the exponent from its conversion is less than -4 or greater than or equal to significant. Unless the ‘#’ flag is given, trailing zeros are removed from the fractional part of the result, and the decimal point only appears if it is followed by at least one digit.

%Lg is similar to %g except that it takes an argument of long double. %lg (ell gee) is an alias for %g.

Identical to %g except that upper case is used, i.e. ‘E’ instead of ‘e’ to introduce the exponent and ‘[-]INF’ and ‘[-]NAN’ for infinity and not-a-number, respectively.
An alias for %d, supporting the same modifiers.
%[argno$][size]n

The %n conversion specifier has serious security implications, so it was changed to no longer store the number of bytes written so far into the variable indicated by the pointer argument. Instead a syslog(3) message will be generated, after which the program is aborted with SIGABRT.

%[argno$][#][-|0][width][.mindigits][size]o

Similar to %u except that the unsigned int argument is converted to unsigned octal notation. If the ‘#’ flag is given, mindigits is increased such that the first digit printed is a zero, except if a zero value is printed with an explicit mindigits of zero.

A deprecated alias for %lo.
The void * pointer argument is printed in hexadecimal, similar to %#x or %#lx depending on the size of pointers.
%[argno$][-][width][.maxbytes]s

Characters from the char * (string) argument are written up to (but not including) a terminating NUL character. If maxbytes is specified, at most maxbytes bytes are written; in that case, no NUL character needs to be present.

%[argno$][-][width][.maxbytes]ls

The wchar_t * (wide character string) argument is converted to a multibyte character string according to the current LC_CTYPE locale(1) up to (but not including) a terminating NUL character, and that multibyte character string is written. If maxbytes is specified, at most maxbytes bytes are written; in that case, no NUL character needs to be present. If a multibyte character does not fit into the rest of maxbytes, it is omitted together with the rest of the argument string; partial characters are not written. Locale dependency and padding work in the same way as for %lc.

%[argno$][-|0][width][.mindigits][size]u

The unsigned int argument is converted to unsigned decimal notation. If specified, at least mindigits are printed, padding with leading zeros if needed. The following are similar to %u except that they take an argument of a different size:

unsigned char
unsigned short
unsigned int
unsigned long (percent ell u)
unsigned long long (percent ell ell u)
uintmax_t
unsigned type of same size as ptrdiff_t
size_t
u_quad_t (deprecated)
A deprecated alias for %lu.
%[argno$][#][-|0][width][.mindigits][size]x

Similar to %u except that the unsigned int argument is converted to unsigned hexadecimal notation using the digits ‘0123456789abcdef’. If the ‘#’ flag is given, the string ‘0x’ is prepended unless the value is zero.

Identical to %x except that upper case is used, i.e. ‘0X’ for the optional prefix and ‘0123456789ABCDEF’ for the digits.
A single percent sign (‘%’) is written. No argument is converted. The complete conversion specification is ‘%%’; no modifiers can be inserted between the two percent signs.

For all these functions if an output or encoding error occurs, a value less than 0 is returned.

The printf(), dprintf(), fprintf(), sprintf(), vprintf(), vdprintf(), vfprintf(), vsprintf(), asprintf(), and vasprintf() functions return the number of bytes printed (not including the trailing ‘\0’ used to end output to strings).

The snprintf() and vsnprintf() functions return the number of bytes that would have been output if the size were unlimited (again, not including the final ‘\0’). A return value greater than or equal to the size argument indicates that the string was too small and some characters were discarded.

The asprintf() and vasprintf() functions return the number of bytes that were output to the newly allocated string (excluding the final ‘\0’). A pointer to the newly allocated string is returned in ret; it should be passed to free(3) to release the allocated storage when it is no longer needed. If sufficient space cannot be allocated or some other error occurs, these functions return -1. The value of ret in this situation is implementation-dependent. On OpenBSD, ret is set to the NULL pointer, but other implementations may leave ret unchanged.

The character encoding locale(1). It decides which wchar_t values represent valid wide characters for the %lc and %ls conversion specifiers and how they are encoded into multibyte characters. If unset or set to "C", "POSIX", or an unsupported value, %lc and %ls only work correctly for ASCII characters and fail for arguments greater than 255.

To print a date and time in the form `Sunday, July 3, 10:02', where weekday and month are pointers to strings:

#include <stdio.h>

fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
    weekday, month, day, hour, min);

To print pi to five decimal places:

#include <math.h>
#include <stdio.h>

fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));

To allocate a 128-byte string and print into it:

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

char *
newfmt(const char *fmt, ...)
{
	char *p;
	va_list ap;

	if ((p = malloc(128)) == NULL)
		return (NULL);
	va_start(ap, fmt);
	(void) vsnprintf(p, 128, fmt, ap);
	va_end(ap);
	return (p);
}

In addition to the errors documented for the write(2) system call, the printf() family of functions may fail if:

[]
An invalid wide character code was encountered.
[]
Insufficient storage space is available.
[]
The return value would be too large to be represented by an int.

printf(1), scanf(3), wprintf(3)

The fprintf(), printf(), snprintf(), sprintf(), vfprintf(), vprintf(), vsnprintf(), and vsprintf() functions conform to ISO/IEC 9899:1999 (“ISO C99”). The dprintf() and vdprintf() functions conform to IEEE Std 1003.1-2008 (“POSIX.1”).

The predecessors ftoa() and itoa() first appeared in Version 1 AT&T UNIX. The function printf() first appeared in Version 2 AT&T UNIX, and fprintf() and sprintf() in Version 7 AT&T UNIX.

The functions snprintf() and vsnprintf() first appeared in 4.3BSD-Net/2.

The functions asprintf() and vasprintf() first appeared in the GNU C library. This implementation first appeared in OpenBSD 2.3.

The functions dprintf() and vdprintf() first appeared in OpenBSD 5.3.

The conversion formats %D, %O, and %U are not standard and are provided only for backward compatibility. The effect of padding the %p format with zeros (either by the ‘0’ flag or by specifying a precision), and the benign effect (i.e., none) of the ‘#’ flag on %n and %p conversions, as well as other nonsensical combinations such as %Ld, are not standard; such combinations should be avoided.

Because sprintf() and vsprintf() assume an infinitely long string, callers must be careful not to overflow the actual space; this is often impossible to assure. For safety, programmers should use the snprintf() and asprintf() family of interfaces instead. Unfortunately, the asprintf() interface is not available on all systems as it is not part of ISO/IEC 9899:1999 (“ISO C99”).

It is important never to pass a string with user-supplied data as a format without using ‘%s’. An attacker can put format specifiers in the string to mangle the stack, leading to a possible security hole. This holds true even if the string has been built “by hand” using a function like snprintf(), as the resulting string may still contain user-supplied conversion specifiers for later interpolation by printf().

Be sure to use the proper secure idiom:

int ret = snprintf(buffer, sizeof(buffer), "%s", string);
if (ret < 0 || (size_t)ret >= sizeof(buffer))
	goto toolong;

There is no way for printf() to know the size of each argument passed. If positional arguments are used, care must be taken to ensure that all parameters, up to the last positionally specified parameter, are used in the format string. This allows for the format string to be parsed for this information. Failure to do this will mean the code is non-portable and liable to fail.

On systems other than OpenBSD, the LC_NUMERIC locale(1) category can cause erratic output; see CAVEATS in setlocale(3) for details.

August 4, 2022 OpenBSD-7.3