printf
Writes formatted output to stdout.
Defined in header <stdio.h>
Syntax
#include <stdio.h>
int printf(const char *format[, argument, ...]);
Portability
| DOS | UNIX | Windows | ANSI C | C++ only |
|---|---|---|---|---|
| ■ | ■ | ■ |
Remarks
printf accepts a series of arguments, applies to each a format specifier contained in the format string given by format, and outputs the formatted data to stdout. There must be the same number of format specifiers as arguments.
The format string
The format string, present in each of the ...printf function calls, controls how each function will convert, format, and print its arguments. There must be enough arguments for the format; if there are not, the results will be unpredictable and likely disastrous. Excess arguments (more than required by the format) are merely ignored.
The format string is a character string that contains two types of objects — plain characters and conversion specifications:
- Plain characters are simply copied verbatim to the output stream.
- Conversion specifications fetch arguments from the argument list and apply formatting to them.
Format specifiers
...printf format specifiers have the following form:
% [flags] [width] [.prec] [F|N|h|l|L] type
Each conversion specification begins with the percent character (%). After the % come the following, in this order:
- an optional sequence of flag characters, [flags]
- an optional width specifier, [width]
- an optional precision specifier, [.prec]
- an optional input-size modifier, [F|N|h|l|L]
- the conversion-type character, [type]
Optional format string components
These are the general aspects of output formatting controlled by the optional characters, specifiers, and modifiers in the format string:
| Character or specifier | What it controls or specifies | |
| flags | Output justification, numeric signs, decimal points, trailing zeros, octal and hex prefixes | |
| width | Minimum number of characters to print | padding with blanks or zeros |
| precision | Maximum number of characters to print; for integers, minimum number of digits to print | |
| size | Override default size of argument: N = near pointer, F = far pointer, h = short int, l = long, L = long double |
...printf conversion-type characters
The following table lists the ...printf conversion-type characters, the type of input argument accepted by each, and in what format the output appears.
The information in this table of type characters is based on the assumption that no flag characters, width specifiers, precision specifiers, or input-size modifiers were included in the format specifier. To see how the addition of the optional characters and specifiers affects the ...printf output, refer to the tables following this one.
| Type character | Input argument | Format of output |
| Numerics | ||
| d | integer | signed decimal int. |
| i | integer | signed decimal int. |
| o | integer | unsigned octal int. |
| u | integer | unsigned decimal int. |
| x | integer | unsigned hexadecimal int (with a, b, c, d, e, f). |
| X | integer | unsigned hexadecimal int (with A, B, C, D, E, F). |
| f | floating-point | signed value of the form [-]dddd.dddd. |
| e | floating-point | signed value of the form [-]d.dddd or e [+/-]ddd. |
| g | floating-point | signed value in either e or f form, based on given value and precision. Trailing zeros and the decimal point are printed only if necessary. |
| E | floating-point | Same as e, but with E for exponent. |
| G | floating-point | Same as g, but with E for exponent if e format used. |
| Characters | ||
| c | character | Single character. |
| s | string pointer | Prints characters until a null-terminator is pressed or precision is reached. |
| % | none | The % character is printed. |
| Pointers | ||
| n | pointer to int | Stores (in the location pointed to by the input argument) a count of the characters written so far. |
| p | pointer | Prints the input argument as a pointer; format depends on which memory model was used. It will be either XXXX:YYYY or YYYY (offset only). |
Conventions
Certain conventions accompany some of these specifications, as summarized in the following table:
| Characters | Conventions |
| e or E | The argument is converted to match the style [-] d.ddd...e[+/-]ddd, where one digit precedes the decimal point; the number of digits after the decimal point is equal to the precision; the exponent always contains at least two digits. |
| f | The argument is converted to decimal notation in the style [-] ddd.ddd..., where the number of digits after the decimal point is equal to the precision (if a nonzero precision was given). |
| g or G | The argument is printed in style e, E or f, with the precision specifying the number of significant digits. Trailing zeros are removed from the result, and a decimal point appears only if necessary. The argument is printed in style e or f (with some restraints) if g is the conversion character, and in style E if the character is G. Style e is used only if the exponent that results from the conversion is either greater than the precision or less than −4. |
| x or X | For x conversions, the letters a, b, c, d, e, and f appear in the output; for X conversions, the letters A, B, C, D, E, and F appear. |
Note: Infinite floating-point numbers are printed as +INF and −INF. An IEEE Not-a-Number is printed as +NAN or −NAN.
Flag characters
The flag characters are minus (-), plus (+), sharp (#), and blank ( ). They can appear in any order and combination.
| Flag | What it specifies |
| - | Left-justifies the result, pads on the right with blanks. If not given, right-justifies result, pads on left with zeros or blanks. |
| + | Signed conversion results always begin with a plus (+) or minus (-) sign. |
| blank | If value is nonnegative, the output begins with a blank instead of a plus; negative values still begin with a minus. |
| # | Specifies that arg is to be converted using an "alternate form." See the following table. |
Note: Plus (+) takes precedence over blank ( ) if both are given.
Alternate forms
If the # flag is used with a conversion character, it has the following effect on the argument (arg) being converted:
| Conversion character | How # affects arg |
| c,s,d,i,u | No effect. |
| o | 0 is prepended to a nonzero arg. |
| x or X | 0x (or 0X) is prepended to arg. |
| e, E, or f | The result always contains a decimal point even if no digits follow the point. Normally, a decimal point appears in these results only if a digit follows it. |
| g or G | Same as e and E, with the addition that trailing zeros are not removed. |
Width specifiers
The width specifier sets the minimum field width for an output value.
Width is specified in one of two ways: directly, through a decimal digit string, or indirectly, through an asterisk (*). If you use an asterisk for the width specifier, the next argument in the call (which must be an int) specifies the minimum output field width.
In no case does a nonexistent or small field width cause truncation of a field. If the result of a conversion is wider than the field width, the field is simply expanded to contain the conversion result.
| Width specifier | How output width is affected | |
| n | At least n characters are printed. If the output value has less than n characters, the output is padded with blanks (right-padded if − flag given, left-padded otherwise). | |
| 0n | At least n characters are printed. If the output value has less than n characters, it is filled on the left with zeros. | |
| * | The argument list supplies the width specifier | which must precede the actual argument being formatted. |
Precision specifiers
A precision specification always begins with a period (.) to separate it from any preceding width specifier. Then, like width, precision is specified either directly through a decimal digit string, or indirectly through an asterisk (*). If you use an asterisk for the precision specifier, the next argument in the call (treated as an int) specifies the precision.
If you use asterisks for the width or the precision, or for both, the width argument must immediately follow the specifiers, followed by the precision argument, then the argument for the data to be converted.
| Precision specifier | How output precision is affected | |
| (none given) | Precision set to default: default = 1 for d, i, o, u, x, X types; default = 6 for e, E, f types; default = all significant digits for g, G types; default = print to first null character for s types; no effect on c types | |
| .0 | For d, i, o, u, x types, precision set to default; for e, E, f types, no decimal point is printed. | |
| .n | n characters or n decimal places are printed. If the output value has more than n characters, the output might be truncated or rounded. (Whether this happens depends on the type character.) | |
| * | The argument list supplies the precision specifier | which must precede the actual argument being formatted. |
Note: If an explicit precision of zero is specified, and the format specifier for the field is one of the integer formats (that is, d, i, o, u, x), and the value to be printed is 0, no numeric characters will be output for that field (that is, the field will be blank).
| Conversion character | How precision specification (.n) affects conversion |
| d, i, o, u, x, X | .n specifies that at least n digits are printed. If the input argument has less than n digits, the output value is left-padded with zeros. If the input argument has more than n digits, the output value is not truncated. |
| e, E, f | .n specifies that n characters are printed after the decimal point, and the last digit printed is rounded. |
| g, G | .n specifies that at most n significant digits are printed. |
| c | .n has no effect on the output. |
| s | .n specifies that no more than n characters are printed. |
Input-size modifier
The input-size modifier character (F, N, h, l, or L) gives the size of the subsequent input argument:
- F = far pointer
- N = near pointer
- h = short int
- l = long
- L = long double
The input-size modifiers (F, N, h, l, and L) affect how the ...printf functions interpret the data type of the corresponding input argument arg. F and N apply only to input args that are pointers (%p, %s, and %n). h, L, and L apply to input args that are numeric (integers and floating-point).
Both F and N reinterpret the input arg. Normally, the arg for a %p, %s, or %n conversion is a pointer of the default size for the memory model. F says "interpret arg as a far pointer." N says "interpret arg as a near pointer."
h, l, and L override the default size of the numeric data input arguments: l and L apply to integer (d, i, o, u, x, X) and floating-point (e, E, f, g, and G) types, while h applies to integer types only. Neither h nor l affect character (c, s) or pointer (p, n) types.
| Input-size modifier | How arg is interpreted |
| F | arg is read as a far pointer. |
| N | arg is read as a near pointer. N cannot be used with any conversion in huge model. |
| h | arg is interpreted as a short int for d, i, o, u, x, or X. |
| l | arg is interpreted as a long int for d, i, o, u, x, or X; arg is interpreted as a double for e, E, f, g, or G. |
| L | arg is interpreted as a long double for e, E, f, g, or G. |
Return value
printf returns the number of bytes output. In the event of error, printf returns EOF.
See also
Example
#include <stdio.h>
#include <string.h>
#define I 555
#define R 5.5
int main(void)
{
int i,j,k,l;
char buf[7];
char *prefix = buf;
char tp[20];
printf("prefix 6d 6o 8x 10.2e "
"10.2f\n");
strcpy(prefix,"%");
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
for (l = 0; l < 2; l++) {
if (i==0) strcat(prefix,"-");
if (j==0) strcat(prefix,"+");
if (k==0) strcat(prefix,"#");
if (l==0) strcat(prefix,"0");
printf("%5s |",prefix);
strcpy(tp,prefix);
strcat(tp,"6d |");
printf(tp,I);
strcpy(tp,"");
strcpy(tp,prefix);
strcat(tp,"6o |");
printf(tp,I);
strcpy(tp,"");
strcpy(tp,prefix);
strcat(tp,"8x |");
printf(tp,I);
strcpy(tp,"");
strcpy(tp,prefix);
strcat(tp,"10.2e |");
printf(tp,R);
strcpy(tp,prefix);
strcat(tp,"10.2f |");
printf(tp,R);
printf(" \n");
strcpy(prefix,"%");
}
}
return 0;
}
Program output
prefix 6d 6o 8x 10.2e 10.2f
%-+#0 |+555 |01053 |0x22b |+5.50e+00 |+5.50 |
%-+# |+555 |01053 |0x22b |+5.50e+00 |+5.50 |
%-+0 |+555 |1053 |22b |+5.50e+00 |+5.50 |
%-+ |+555 |1053 |22b |+5.50e+00 |+5.50 |
%-#0 |555 |01053 |0x22b |5.50e+00 |5.50 |
%-# |555 |01053 |0x22b |5.50e+00 |5.50 |
%-0 |555 |1053 |22b |5.50e+00 |5.50 |
%- |555 |1053 |22b |5.50e+00 |5.50 |
%+#0 |+00555 |001053 |0x00022b |+05.50e+00 |+000005.50 |
%+# | +555 | 01053 | 0x22b | +5.50e+00 | +5.50 |
%+0 |+00555 |001053 |0000022b |+05.50e+00 |+000005.50 |
%+ | +555 | 1053 | 22b | +5.50e+00 | +5.50 |
%#0 |000555 |001053 |0x00022b |005.50e+00 |0000005.50 |
%# | 555 | 01053 | 0x22b | 5.50e+00 | 5.50 |
%0 |000555 |001053 |0000022b |005.50e+00 |0000005.50 |
% | 555 | 1053 | 22b | 5.50e+00 | 5.50 |
Differences from modern implementations
Draft. Items marked (manual) come from the 3.1 manual itself; the others are from general knowledge and not yet confirmed against the Borland run-time code.
intis 16 bits.%d,%u,%xand%otake a 16-bitint; use%ld/%lxfor 32-bitlong. Passing alongto%dputs two words on the stack and shifts every later argument. This is the most common source of garbage output when porting code.FandNsize modifiers (manual) select far or near pointers for%p,%sand%n. They don’t exist in modern C.%pprintsXXXX:YYYY(segment:offset) for far pointers orYYYYfor near ones (manual); glibc prints0x…and MSVC prints a zero-padded hex address.- Infinity and NaN are printed as
+INF,-INF,+NANand-NAN, always signed and in upper case (manual). C99 printsinf/nan(INF/NANfor%E,%G,%F), with a sign only for negative values or with the+flag. - No C99 additions: no
hh,ll,j,z,tlength modifiers, no%a/%A(hex float) and no%Fconversion. 32-bitlongis the widest integer type. printfreturns the number of bytes output (manual). In text mode each\nbecomes CR LF on the way to DOS; whether the return value counts the inserted CR is not stated. To be checked in the run-time code.- Not available in Windows programs: the portability table leaves the Windows column empty
for
printf(there is nostdoutin a Windows GUI application). According to their extracted tables,sprintfandfprintfare marked for Windows. - The example’s output (manual, page 406) is identical to what glibc prints today for the same
program, so the flags, width and precision handling of
d,o,x,eandfmatch modern behaviour.
Modern references
- cppreference: printf, fprintf, sprintf, snprintf
- POSIX: fprintf, printf, snprintf, sprintf
- Microsoft CRT: printf, _printf_l, wprintf, _wprintf_l
- Microsoft CRT: format specification syntax
Stable link: /3.1/stdio.h/printf/
· short form /3.1/printf/