Printf



The printf format string is a control parameter used by a class of functions in the input/output libraries of C and many other programming languages. The string is written in a simple template language: characters are usually copied literally into the function's output, but format specifiers, which start with a % character, indicate the location and method to translate a piece of data (such as a number) to characters.

"printf" is the name of one of the main C output functions, and stands for "print formatted". printf format strings are complementary to scanf format strings, which provide formatted input (lexing aka. parsing). In both cases these provide simple functionality and fixed format compared to more sophisticated and flexible template engines or lexers/parsers, but are sufficient for many purposes.

Many languages other than C copy the printf format string syntax closely or exactly in their own I/O functions.

Mismatches between the format specifiers and type of the data can cause crashes and other vulnerabilities. The format string itself is very often a string literal, which allows static analysis of the function call. However, it can also be the value of a variable, which allows for dynamic formatting but also a security vulnerability known as an uncontrolled format string exploit.

History
Early programming languages such as Fortran used special statements with completely different syntax from other calculations to build formatting descriptions. In this example, the format is specified on line 601, and the WRITE command refers to it by line number:

ALGOL 68 had more function-like API, but still used special syntax (the $ delimiters surround special formatting syntax):

But using the normal function calls and data types simplifies the language and compiler, and allows the implementation of the input/output to be written in the same language. These advantages outweigh the disadvantages (such as a complete lack of type safety in many instances) and in most newer languages I/O is not part of the syntax.

C's printf has its origins in BCPL's writef function (1966). In comparison to C and printf, *N is a BCPL language escape sequence representing a newline character (for which C uses the escape sequence \n) and the order of the format specification's field width and type is reversed in writef:

Probably the first copying of the syntax outside the C language was the Unix printf shell command, which first appeared in Version 4, as part of the port to C.

Format placeholder specification
Formatting takes place via placeholders within the format string. For example, if a program wanted to print out a person's age, it could present the output by prefixing it with "Your age is ", and using the signed decimal specifier character d to denote that we want the integer for the age to be shown immediately after that message, we may use the format string:

Syntax
The syntax for a format placeholder is
 * %[parameter][flags][width][.precision][length]type

Parameter field
This is a POSIX extension and not in C99. The Parameter field can be omitted or can be:
 * {| class="wikitable"

! Character ! Description For example, printf("%2$d %2$#x; %1$d %1$#x",16,17) produces 17 0x11; 16 0x10. This feature mainly sees its use in localization, where the order of occurrence of parameters vary due to the language-dependent convention.
 * n is the number of the parameter to display using this format specifier, allowing the parameters provided to be output multiple times, using varying format specifiers or in different orders. If any single placeholder specifies a parameter, all the rest of the placeholders MUST also specify a parameter.
 * n is the number of the parameter to display using this format specifier, allowing the parameters provided to be output multiple times, using varying format specifiers or in different orders. If any single placeholder specifies a parameter, all the rest of the placeholders MUST also specify a parameter.
 * n is the number of the parameter to display using this format specifier, allowing the parameters provided to be output multiple times, using varying format specifiers or in different orders. If any single placeholder specifies a parameter, all the rest of the placeholders MUST also specify a parameter.
 * }

On the non-POSIX Microsoft Windows, support for this feature is placed in a separate printf_p function.

Flags field
The Flags field can be zero or more (in any order) of:
 * {| class="wikitable"

! Character ! Description (minus) (plus) (The default doesn't prepend anything in front of positive numbers.) (space) (The default doesn't prepend anything in front of positive numbers.) (zero) For example, printf("%4X",3) produces, while printf("%04X",3) produces 0003. (apostrophe) (hash) For and  types, trailing zeros are not removed. For, , , , , types, the output always contains a decimal point. For, , types, the text , , , respectively, is prepended to non-zero numbers.
 * Left-align the output of this placeholder. (The default is to right-align the output.)
 * Prepends a plus for positive signed-numeric types. positive =, negative =.
 * Prepends a space for positive signed-numeric types. positive =, negative = . This flag is ignored if the  flag exists.
 * When the 'width' option is specified, prepends zeros for numeric types. (The default prepends spaces.)
 * The integer or exponent of a decimal has the thousands grouping separator applied.
 * Alternate form:
 * }

Width field
The Width field specifies a minimum number of characters to output and is typically used to pad fixed-width fields in tabulated output, where the fields would otherwise be smaller, although it does not cause truncation of oversized fields.

The width field may be omitted, or a numeric integer value, or a dynamic value when passed as another argument when indicated by an asterisk *. For example, printf("%*d", 5, 10) will result in  being printed, with a total width of 5 characters.

Though not part of the width field, a leading zero is interpreted as the zero-padding flag mentioned above, and a negative value is treated as the positive value in conjunction with the left-alignment - flag also mentioned above.

Precision field
The Precision field usually specifies a maximum limit on the output, depending on the particular formatting type. For floating-point numeric types, it specifies the number of digits to the right of the decimal point that the output should be rounded. For the string type, it limits the number of characters that should be output, after which the string is truncated.

The precision field may be omitted, or a numeric integer value, or a dynamic value when passed as another argument when indicated by an asterisk *. For example, printf("%.*s", 3, "abcdef") will result in abc being printed.

Length field
The Length field can be omitted or be any of:
 * {| class="wikitable"

! Character ! Description For floating-point types, this is ignored. arguments are always promoted to when used in a varargs call.
 * For integer types, causes to expect an -sized integer argument which was promoted from a.
 * For integer types, causes to expect an -sized integer argument which was promoted from a.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect an -sized integer argument which was promoted from a.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect an -sized integer argument which was promoted from a.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * For floating-point types, causes to expect a  argument.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * }
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * }
 * For integer types, causes to expect a -sized integer argument.
 * For integer types, causes to expect a -sized integer argument.
 * }
 * For integer types, causes to expect a -sized integer argument.
 * }
 * }

Additionally, several platform-specific length options came to exist prior to widespread use of the ISO C99 extensions:
 * {| class="wikitable"

! Characters ! Description
 * For signed integer types, causes to expect -sized integer argument; for unsigned integer types, causes  to expect -sized integer argument. Commonly found in Win32/Win64 platforms.
 * For integer types, causes to expect a 32-bit (double word) integer argument.  Commonly found in Win32/Win64 platforms.
 * For integer types, causes to expect a 64-bit (quad word) integer argument.  Commonly found in Win32/Win64 platforms.
 * For integer types, causes to expect a 64-bit (quad word) integer argument.  Commonly found in BSD platforms.
 * }
 * For integer types, causes to expect a 32-bit (double word) integer argument.  Commonly found in Win32/Win64 platforms.
 * For integer types, causes to expect a 64-bit (quad word) integer argument.  Commonly found in Win32/Win64 platforms.
 * For integer types, causes to expect a 64-bit (quad word) integer argument.  Commonly found in BSD platforms.
 * }
 * For integer types, causes to expect a 64-bit (quad word) integer argument.  Commonly found in BSD platforms.
 * }
 * For integer types, causes to expect a 64-bit (quad word) integer argument.  Commonly found in BSD platforms.
 * }

ISO C99 includes the  header file that includes a number of macros for use in platform-independent printf coding. These must be outside double-quotes, e.g. printf("%" PRId64 "\n", t);

Example macros include:
 * {| class="wikitable"

! Macro ! Description
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * }
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * }
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * }
 * Typically equivalent to (Win32/Win64) or
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * }
 * Typically equivalent to (Win32/Win64),  (32-bit platforms) or  (64-bit platforms)
 * }
 * }

Type field
The Type field can be any of:
 * {| class="wikitable"

! Character ! Description In Java this prints a newline.
 * Prints a literal character (this type doesn't accept any flags, width, precision, length fields).
 * as a signed integer. and  are synonymous for output, but are different when used with   for input (where using  will interpret a number as hexadecimal if it's preceded by, and octal if it's preceded by .)
 * Print decimal.
 * in normal (fixed-point) notation. and  only differs in how the strings for an infinite number or NaN are printed (,  and  for ;,  and  for ).
 * value in standard form . An conversion uses the letter  (rather than ) to introduce the exponent.  The exponent always contains at least two digits; if the value is zero, the exponent is . In Windows, the exponent contains three digits by default, e.g., but this can be altered by Microsoft-specific _set_output_format function.
 * in either normal or exponential notation, whichever is more appropriate for its magnitude. uses lower-case letters,  uses upper-case letters.  This type differs slightly from fixed-point notation in that insignificant zeroes to the right of the decimal point are not included.  Also, the decimal point is not included on whole numbers.
 * as a hexadecimal number. uses lower-case letters and  uses upper-case.
 * in octal.
 * null-terminated string.
 * (character).
 * (pointer to void) in an implementation-defined format.
 * in hexadecimal notation, starting with or .  uses lower-case letters,  uses upper-case letters.  (C++11 iostreams have a  that works the same).
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * value in standard form . An conversion uses the letter  (rather than ) to introduce the exponent.  The exponent always contains at least two digits; if the value is zero, the exponent is . In Windows, the exponent contains three digits by default, e.g., but this can be altered by Microsoft-specific _set_output_format function.
 * in either normal or exponential notation, whichever is more appropriate for its magnitude. uses lower-case letters,  uses upper-case letters.  This type differs slightly from fixed-point notation in that insignificant zeroes to the right of the decimal point are not included.  Also, the decimal point is not included on whole numbers.
 * as a hexadecimal number. uses lower-case letters and  uses upper-case.
 * in octal.
 * null-terminated string.
 * (character).
 * (pointer to void) in an implementation-defined format.
 * in hexadecimal notation, starting with or .  uses lower-case letters,  uses upper-case letters.  (C++11 iostreams have a  that works the same).
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * in octal.
 * null-terminated string.
 * (character).
 * (pointer to void) in an implementation-defined format.
 * in hexadecimal notation, starting with or .  uses lower-case letters,  uses upper-case letters.  (C++11 iostreams have a  that works the same).
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * (character).
 * (pointer to void) in an implementation-defined format.
 * in hexadecimal notation, starting with or .  uses lower-case letters,  uses upper-case letters.  (C++11 iostreams have a  that works the same).
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * (pointer to void) in an implementation-defined format.
 * in hexadecimal notation, starting with or .  uses lower-case letters,  uses upper-case letters.  (C++11 iostreams have a  that works the same).
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * in hexadecimal notation, starting with or .  uses lower-case letters,  uses upper-case letters.  (C++11 iostreams have a  that works the same).
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * Print nothing, but writes the number of characters written so far into an integer pointer parameter.
 * }

Custom format placeholders
There are a few implementations of printf-like functions that allow extensions to the escape-character-based mini-language, thus allowing the programmer to have a specific formatting function for non-builtin types. One of the most well-known is the (now deprecated) glibc's register_printf_function. However, it is rarely used due to the fact that it conflicts with static format string checking. Another is Vstr custom formatters, which allows adding multi-character format names.

Some applications (like the Apache HTTP Server) include their own printf-like function, and embed extensions into it. However these all tend to have the same problems that register_printf_function has.

The Linux kernel  function supports a number of ways to display kernel structures using the generic %p specification, by appending additional format characters. For example, %pI4 prints an IPv4 address in dotted-decimal form. This allows static format string checking (of the %p portion) at the expense of full compatibility with normal printf.

Most languages that have a printf-like function work around the lack of this feature by just using the %s format and converting the object to a string representation.

Invalid conversion specifications
If there are too few function arguments provided to supply values for all the conversion specifications in the template string, or if the arguments are not of the correct types, the results are undefined, may crash. Implementations are inconsistent about whether syntax errors in the string consume an argument and what type of argument they consume. Excess arguments are ignored. In a number of cases, the undefined behavior has led to "Format string attack" security vulnerabilities. In most C or C++ calling conventions arguments may be passed on the stack, which means in the case of too few arguments printf will read past the end of the current stackframe, thus allowing the attacker to read the stack.

Some compilers, like the GNU Compiler Collection, will statically check the format strings of printf-like functions and warn about problems (when using the flags -Wall or -Wformat). GCC will also warn about user-defined printf-style functions if the non-standard "format" __attribute__ is applied to the function.

Field width versus explicit delimiters in tabular output
Using only field widths to provide for tabulation, as with a format like %8d%8d%8d for three integers in three 8-character columns, will not guarantee that field separation will be retained if large numbers occur in the data:

1234567 1234567 1234567 123     123     123      123     12345678123

Loss of field separation can easily lead to corrupt output. In systems which encourage the use of programs as building blocks in scripts, such corrupt data can often be forwarded into and corrupt further processing, regardless of whether the original programmer expected the output would only be read by human eyes. Such problems can be eliminated by including explicit delimiters, even spaces, in all tabular output formats. Simply changing the dangerous example from before to %7d %7d %7d addresses this, formatting identically until numbers become larger, but then explicitly preventing them from becoming merged on output due to the explicitly included spaces:

1234567 1234567 1234567 123     123     123      123     12345678 123

Similar strategies apply to string data.

Memory write
Although an outputting function on the surface, printf allows writing to a memory location specified by an argument via %n. This functionality is occasionally used as a part of more elaborate format-string attacks.

The %n functionality also makes printf accidentally Turing-complete even with a well-formed set of arguments. A game of tic-tac-toe written in the format string is a winner of the 27th IOCCC.

Programming languages with printf
Not included in this list are languages that use format strings that deviate from the style in this article (such as AMPL and Elixir), languages that inherit their implementation from the JVM or other environment (such as Clojure and Scala), and languages that do not have a standard native printf implementation but have external libraries which emulate printf behavior (such as JavaScript).


 * awk
 * C
 * C++ (also provides overloaded shift operators and manipulators as an alternative for formatted output – see iostream and iomanip)
 * Objective-C
 * D
 * F#
 * G (LabVIEW)
 * GNU MathProg
 * GNU Octave
 * Go
 * Haskell
 * J
 * Java (since version 1.5) and JVM languages
 * Julia (via its Printf standard library; Formatting.jl library adds Python-style general formatting and "c-style part of this package aims to get around the limitation that @sprintf has to take a literal string argument.")
 * Lua (string.format)
 * Maple
 * MATLAB
 * Max (via the sprintf object)
 * Mythryl
 * PARI/GP
 * Perl
 * PHP
 * Python (via % operator)
 * R
 * Raku (via printf, sprintf, and fmt)
 * Red/System
 * Ruby
 * Tcl (via format command)
 * Transact-SQL (via xp_sprintf)
 * Vala (via print and FileStream.printf)
 * The printf utility command, sometimes built in to the shell, such as with some implementations of the KornShell (ksh), Bourne again shell (bash), or Z shell (zsh). These commands usually interpret C escapes in the format string.